
Экстрактор дефангированных индикаторов компрометации (IOC).
Индикатор компрометации (IOC) — извлекатель для некоторых наиболее часто используемых артефактов.
Пакет iocextract — это библиотека и интерфейс командной строки (CLI) для извлечения URL-адресов, IP-адресов, MD5/SHA-хешей, адресов электронной почты и правил YARA из текстовых корпусов. Он позволяет извлекать закодированные и «обезвреженные» (defanged) IOC и при необходимости декодировать или восстанавливать их (refang).
Среди аналитиков вредоносного ПО и разработчиков конечных средств защиты распространена практика «обезвреживания» (defanging) IOC, таких как URL-адреса и IP-адреса, чтобы предотвратить случайный доступ к живому вредоносному контенту. Возможность извлекать и агрегировать такие IOC часто полезна для аналитиков. К сожалению, существующие инструменты «извлечения IOC» часто пропускают их, поскольку они не распознаются стандартными регулярными выражениями.
Например, простая техника обезвреживания — обрамление точек квадратными скобками:
127[.]0[.]0[.]1
Существующие инструменты, использующие простое регулярное выражение для IP-адресов, полностью игнорируют такой IOC.
Объединяя специально разработанные регулярные выражения с некоторой пользовательской постобработкой, мы можем как обнаруживать, так и деобфусцировать «обезвреженные» IOC. Это экономит время и усилия аналитика, которому в противном случае пришлось бы вручную находить и преобразовывать IOC в машиночитаемый формат.
Многие пользователи Twitter публикуют C2 или другую ценную информацию об IOC с обезвреженными URL-адресами. Например, этот твит от @InQuest:
Рекомендуемое чтение и отличная работа от @unit42_intel:
https://researchcenter.paloaltonetworks.com/2018/02/unit42-sofacy-attacks-multiple-government-entities/ ...
Клиенты InQuest имели обнаружение угроз, доставленных с hotfixmsupload[.]com
с 6/3/2017 и cdnverify[.]net с 2/1/18.
Если пропустить это через извлекатель, мы легко получим URL-адреса:
https://researchcenter.paloaltonetworks.com/2018/02/unit42-sofacy-attacks-multiple-government-entities/
hotfixmsupload[.]com
cdnverify[.]net
Если при извлечении передать refang=True, обфускация будет удалена, но поскольку это реальные IOC, оставим их обезвреженными в нашей документации.
Возможно, потребуется установить заголовочные файлы для разработки на Python, чтобы установить зависимость regex. В системах на базе Ubuntu/Debian попробуйте:
sudo apt-get install python-dev
Затем установите iocextract через pip:
pip install iocextract
Если возникают проблемы с установкой в Windows, попробуйте установить regex напрямую, скачав соответствующий wheel с PyPI и установив через pip:
pip install regex-2018.06.21-cp27-none-win_amd64.whl
Попробуйте извлечь некоторые обезвреженные URL-адреса:
import iocextract
content = \
"""
Я очень люблю example[.]com!
Все боты сейчас на hxxp://example.com/bad/url.
C2: tcp://example[.]com:8989/bad
"""
for url in iocextract.extract_urls(content):
print(url)
# Вывод
# hxxp://example.com/bad/url
# tcp://example[.]com:8989/bad
# example[.]com
# tcp://example[.]com:8989/bad
ПРИМЕЧАНИЕ: Некоторые URL-адреса могут появляться дважды, если они попадают под несколько регулярных выражений.
При желании вы также можете «восстановить» (refang) или удалить распространенные методы обфускации из IOC:
import iocextract
for url in iocextract.extract_urls(content, refang=True):
print(url)
# Вывод
# http://example.com/bad/url
# http://example.com:8989/bad
# http://example.com
# http://example.com:8989/bad
Если вы не хотите обезвреживать извлеченные IOC при извлечении, вы можете отключить это:
import iocextract
content = \
"""
http://example.com/bad/url
http://example.com:8989/bad
http://example.com
http://example.com:8989/bad
"""
for url in iocextract.extract_urls(content, defang=False):
print(url)
# Вывод
# http://example.com/bad/url
# http://example.com:8989/bad
# http://example.com
# http://example.com:8989/bad
Все функции extract_* в этой библиотеке возвращают итераторы, а не списки. Преимущество такого поведения в том, что iocextract может обрабатывать очень большие входные данные с очень низкими накладными расходами. Однако если по какой-то причине вам нужно перебирать IOC более одного раза, вам придется сохранить результаты в виде списка:
import iocextract
content = \
"""
Я очень люблю example[.]com!
Все боты сейчас на hxxp://example.com/bad/url.
C2: tcp://example[.]com:8989/bad
"""
print(list(iocextract.extract_urls(content)))
# ['hxxp://example.com/bad/url', 'tcp://example[.]com:8989/bad', 'example[.]com', 'tcp://example[.]com:8989/bad']
Также включен инструмент командной строки:
$ iocextract -h
usage: iocextract [-h] [--input INPUT] [--output OUTPUT] [--extract-emails]
[--extract-ips] [--extract-ipv4s] [--extract-ipv6s]
[--extract-urls] [--extract-yara-rules] [--extract-hashes]
[--custom-regex REGEX_FILE] [--refang] [--strip-urls]
[--wide]
Advanced Indicator of Compromise (IOC) extractor. If no arguments are
specified, the default behavior is to extract all IOCs.
optional arguments:
-h, --help show this help message and exit
--input INPUT default: stdin
--output OUTPUT default: stdout
--extract-emails
--extract-ips
--extract-ipv4s
--extract-ipv6s
--extract-urls
--extract-yara-rules
--extract-hashes
--custom-regex REGEX_FILE file with custom regex strings, one per line, with one capture group each
--refang default: no
--strip-urls remove possible garbage from the end of urls. default: no
--wide preprocess input to allow wide-encoded character matches. default: no
ПРИМЕЧАНИЕ: Только URL-адреса, адреса электронной почты и IPv4-адреса могут быть «восстановлены» (refanged).
Вы...
В. Извлекаете потенциально обезвреженные IOC из обычного текста, например, содержимого твитов или постов в блогах?
О. Да! Именно для этого и был разработан iocextract, и в этом он показывает наилучшие результаты. Хотите пойти дальше и автоматизировать извлечение и хранение? Ознакомьтесь с ThreatIngestor.
В. Извлекаете URL-адреса, закодированные в hex или base64?
О. Да, но CLI может не дать наилучших результатов. Попробуйте написать скрипт на Python и вызвать
iocextract.extract_encoded_urlsнапрямую.
Примечание: Скорее всего, в конце URL-адресов будет лишний мусор.
В. Извлекаете IOC, которые не были обезврежены, из HTML/XML/RTF?
О. Возможно, но вам стоит рассмотреть использование флага
--strip-urlsв CLI (или параметраstrip=Trueв библиотеке), и в выводе всё равно может оказаться лишний мусор. Если вы извлекаете из HTML, подумайте об использовании чего-то вроде Beautiful Soup для предварительного выделения текстового содержимого, а затем передайте его в iocextract, как в этом примере.
В. Извлекаете IOC, которые не были обезврежены, из двоичных данных (например, исполняемых файлов) или очень больших входных данных?
О. Существует очень упрощенная версия этого при использовании в качестве библиотеки, но она требует параметра
defang=Falseи может пропустить некоторые IOC. Регулярные выражения в iocextract разработаны гибкими для обнаружения обезвреженных IOC. Если вам не удается собрать необходимую информацию, рассмотрите возможность использования, например, Cacador.
В настоящее время библиотека поддерживает следующие IOC:
[.], даже без указания протокола@ или atДля IPv4-адресов поддерживаются следующие техники обезвреживания:
Для адресов электронной почты поддерживаются следующие техники обезвреживания:
Для URL-адресов поддерживаются следующие техники обезвреживания:
ПРИМЕЧАНИЕ: Приведенные выше таблицы не являются исчерпывающими, и другие шаблоны URL/обезвреживания также могут быть извлечены корректно. Если вы заметили, что что-то отсутствует или работает неправильно, сообщите нам об этом через GitHub Issues.
Регулярное выражение для base64 было сгенерировано с помощью инструмента base64 regex от @deadpixi.
Если вы хотите использовать CLI для извлечения IOC с помощью собственных регулярных выражений, создайте текстовый файл с одним регулярным выражением на строку и передайте его с флагом --custom-regex. Убедитесь, что каждое регулярное выражение содержит ровно одну группу захвата.
Например:
http://(example\.com)/
(?:https|ftp)://(example\.com)/
Этот файл пользовательских регулярных выражений извлечет домен example.com из соответствующих URL-адресов. Группа без захвата (?: ) не будет включена в совпадения.
Если вы хотите извлечь всё совпадение целиком, просто поместите в скобки всё регулярное выражение, например:
(https?://.*?.com)
Если ваше регулярное выражение недействительно, вы увидите сообщение об ошибке вида:
Error in custom regex: missing ) at position 5
Если ваше регулярное выражение не содержит группы захвата, вы увидите сообщение об ошибке:
Error in custom regex: no such group
Всегда используйте одну группу захвата при работе с пользовательскими регулярными выражениями. Вот краткий пример:
[
r'(my regex)', # Это даёт 'my regex', если шаблон совпадает
r'my (re)gex', # Это даёт 're', если шаблон совпадает
]
Использование более одной группы захвата может привести к неожиданным результатам. Ознакомьтесь с этим примером:
[
r'my regex', # Это ничего не даёт
r'(my) (re)gex', # Это даёт 'my', если шаблон совпадает
]
Почему? Потому что результат всегда будет возвращать только первое совпадение группы из каждого регулярного выражения.
Для более сложных запросов можно комбинировать группы захвата и группы без захвата следующим образом:
[
r'(?:my|your) (re)gex', # Это даёт 're', если шаблон совпадает
]
Теперь вы можете сравнить синтаксис (?: ) для групп без захвата и ( ) для группы захвата.
Если iocextract не подходит для вашего случая использования, существует несколько похожих проектов. Посмотрите теги defang и indicators-of-compromise на GitHub, а также:
Если вы хотите автоматизировать извлечение IOC, обогащение, экспорт и другое, ознакомьтесь с ThreatIngestor.
Если вы работаете с правилами YARA, вас может заинтересовать plyara.
Если у вас есть техника обезвреживания, которая не проходит через извлекатель, или вы нашли какие-либо ошибки, Pull Requests и Issues всегда приветствуются. Библиотека выпущена под лицензией GPL-2.0 license.
Вы используете его? Хотите увидеть свой сайт в этом списке? Дайте нам знать!
| Техника | Обезвреженный | Восстановленный |
|---|
. -> [.] | 1[.]1[.]1[.]1 | 1.1.1.1 |
. -> (.) | 1(.)1(.)1(.)1 | 1.1.1.1 |
. -> \. | 1\.1\.1\.1 | 1.1.1.1 |
| Частичная | 1[.1[.1.]1 | 1.1.1.1 |
| Любая комбинация | 1.)1[.1.)1 | 1.1.1.1 |
| Техника | Обезвреженный | Восстановленный |
|---|
. -> [.] | me@example[.]com | [email protected] |
. -> (.) | me@example(.)com | [email protected] |
. -> {.} | me@example{.}com | [email protected] |
. -> _dot_ | me@example dot com | [email protected] |
@ -> [@] | me[@]example.com | [email protected] |
@ -> (@) | me(@)example.com | [email protected] |
@ -> {@} | me{@}example.com | [email protected] |
@ -> _at_ | me at example.com | [email protected] |
| Частичная | me@} example[.com | [email protected] |
| Добавленные пробелы | me@example [.] com | [email protected] |
| Любая комбинация | me @example [.)com | [email protected] |
| Техника | Обезвреженный | Восстановленный |
|---|
. -> [.] | example[.]com/path | http://example.com/path |
. -> (.) | example(.)com/path | http://example.com/path |
. -> \. | example\.com/path | http://example.com/path |
| Частичная | http://example[.com/path | http://example.com/path |
/ -> [/] | http://example.com[/]path | http://example.com/path |
| Cisco ESA | http:// example .com /path | http://example.com/path |
:// -> __ | http__example.com/path | http://example.com/path |
:// -> :\\ | http:\\example.com/path | http://example.com/path |
: -> [:] | http[:]//example.com/path | http://example.com/path |
hxxp | hxxp://example.com/path | http://example.com/path |
| Любая комбинация | hxxp__ example( .com[/]path | http://example.com/path |
| Hex-кодирование | 687474703a2f2f6578616d706c652e636f6d2f70617468 | http://example.com/path |
| URL-кодирование | http%3A%2F%2fexample%2Ecom%2Fpath | http://example.com/path |
| Base64-кодирование | aHR0cDovL2V4YW1wbGUuY29tL3BhdGgK | http://example.com/path |