
Extractor de Indicadores de Compromiso (IOC) desarmados.
Indicador de Compromiso (IOC) para algunos de los artefactos más comúnmente ingeridos.
El paquete iocextract es una biblioteca e interfaz de línea de comandos (CLI) para extraer URLs, direcciones IP, hashes MD5/SHA, direcciones de correo electrónico y reglas YARA de corpus de texto. Permite extraer IOCs codificados y "defanged" y, opcionalmente, decodificarlos o "refangearlos".
Es práctica común que los analistas de malware o el software de endpoints "defangeen" IOCs como URLs y direcciones IP, para evitar la exposición accidental a contenido malicioso en vivo. Poder extraer y agregar estos IOCs suele ser valioso para los analistas. Desafortunadamente, las herramientas existentes de "extracción de IOCs" a menudo los pasan por alto, ya que no son capturados por expresiones regulares estándar.
Por ejemplo, la técnica simple de defanging de rodear los puntos con corchetes:
127[.]0[.]0[.]1
Las herramientas existentes que usan una expresión regular simple de dirección IP ignorarán este IOC por completo.
Combinando expresiones regulares especialmente diseñadas con algún post-procesamiento personalizado, podemos detectar y desobfuscar IOCs "defanged". Esto ahorra tiempo y esfuerzo al analista, que de otro modo tendría que encontrar y convertir manualmente los IOCs a un formato legible por máquina.
Muchos usuarios de Twitter publican C2s u otra información valiosa de IOC con URLs defanged. Por ejemplo, este tuit de @InQuest:
Lectura recomendada y gran trabajo de @unit42_intel:
https://researchcenter.paloaltonetworks.com/2018/02/unit42-sofacy-attacks-multiple-government-entities/ ...
Los clientes de InQuest han tenido detección para amenazas entregadas desde hotfixmsupload[.]com
desde el 6/3/2017 y cdnverify[.]net desde el 1/2/18.
Si ejecutamos esto a través del extractor, podemos extraer fácilmente las URLs:
https://researchcenter.paloaltonetworks.com/2018/02/unit42-sofacy-attacks-multiple-government-entities/
hotfixmsupload[.]com
cdnverify[.]net
Pasando refang=True en el momento de la extracción eliminaría la ofuscación, pero como son IOCs reales, dejémoslos defanged en nuestra documentación.
Es posible que necesites instalar los encabezados de desarrollo de Python para poder instalar la dependencia regex. En sistemas basados en Ubuntu/Debian, prueba:
sudo apt-get install python-dev
Luego instala iocextract desde pip:
pip install iocextract
Si tienes problemas para instalar en Windows, prueba instalando regex directamente descargando la rueda adecuada de PyPI e instalando mediante pip:
pip install regex-2018.06.21-cp27-none-win_amd64.whl
Prueba a extraer algunas URLs defanged:
import iocextract
content = \
"""
¡Me encanta example[.]com!
Todos los bots están en hxxp://example.com/bad/url estos días.
C2: tcp://example[.]com:8989/bad
"""
for url in iocextract.extract_urls(content):
print(url)
# Salida
# hxxp://example.com/bad/url
# tcp://example[.]com:8989/bad
# example[.]com
# tcp://example[.]com:8989/bad
NOTA: Algunas URLs pueden aparecer dos veces si son capturadas por múltiples expresiones regulares.
Si lo deseas, también puedes "refangear", o eliminar métodos comunes de ofuscación de los IOCs:
import iocextract
for url in iocextract.extract_urls(content, refang=True):
print(url)
# Salida
# http://example.com/bad/url
# http://example.com:8989/bad
# http://example.com
# http://example.com:8989/bad
Si no quieres defangear los IOCs extraídos durante la extracción, también puedes deshabilitar esto:
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)
# Salida
# http://example.com/bad/url
# http://example.com:8989/bad
# http://example.com
# http://example.com:8989/bad
Todas las funciones extract_* en esta biblioteca devuelven iteradores, no listas. El beneficio de este comportamiento es que iocextract puede procesar entradas extremadamente grandes, con una sobrecarga muy baja. Sin embargo, si por alguna razón necesitas iterar sobre los IOCs más de una vez, tendrás que guardar los resultados como una lista:
import iocextract
content = \
"""
¡Me encanta example[.]com!
Todos los bots están en hxxp://example.com/bad/url estos días.
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']
También se incluye una herramienta de línea de comandos:
$ 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
NOTA: Solo las URLs, correos electrónicos y direcciones IPv4 pueden ser "refanged".
¿Estás...
P. Extrayendo IOCs posiblemente defanged de texto plano, como el contenido de tuits o publicaciones de blog?
R. ¡Sí! Esto es exactamente para lo que fue diseñado iocextract, y donde mejor funciona. ¿Quieres ir un paso más allá y automatizar la extracción y almacenamiento? Echa un vistazo a ThreatIngestor.
P. Extrayendo URLs que han sido codificadas en hexadecimal o base64?
R. Sí, pero la CLI puede no darte los mejores resultados. Intenta escribir un script en Python y llama a
iocextract.extract_encoded_urlsdirectamente.
Nota: Lo más probable es que termines con basura adicional al final de las URLs.
P. Extrayendo IOCs que no han sido defanged, desde HTML/XML/RTF?
R. Quizás, pero deberías considerar usar el flag
--strip-urlsde la CLI (o el parámetrostrip=Trueen la biblioteca), y aún así podrías obtener algo de basura extra en tu salida. Si extrayes desde HTML, considera usar algo como Beautiful Soup para primero aislar el contenido de texto, y luego pasarlo a iocextract, como este ejemplo.
P. Extrayendo IOCs que no han sido defanged, desde datos binarios como ejecutables, o entradas muy grandes?
R. Hay una versión muy simplista de esto disponible cuando se usa como biblioteca, pero requiere el parámetro
defang=Falsey podría potencialmente perder algunos de los IOCs. Las expresiones regulares en iocextract están diseñadas para ser flexibles y capturar IOCs defanged. Si no puedes recolectar la información que necesitas, considera usar algo como Cacador en su lugar.
Esta biblioteca actualmente soporta los siguientes IOCs:
[.], incluso sin especificador de protocolo@ o atPara direcciones IPv4, se soportan las siguientes técnicas de defanging:
Para direcciones de correo electrónico, se soportan las siguientes técnicas de defanging:
Para URLs, se soportan las siguientes técnicas de defanging:
NOTA: Las tablas anteriores no son exhaustivas, y otros patrones de URL/defanging también pueden extraerse correctamente. Si notas algo que falta o no funciona correctamente, no dudes en informarnos a través de los Issues de GitHub.
La expresión regular de base64 se generó con la herramienta de regex base64 de @deadpixi.
Si deseas usar la CLI para extraer IOCs usando tu propio regex personalizado, crea un archivo de texto plano con una cadena de regex por línea, y pásalo con el flag --custom-regex. Asegúrate de que cada cadena de regex incluya exactamente un grupo de captura.
Por ejemplo:
http://(example\.com)/
(?:https|ftp)://(example\.com)/
Este archivo de regex personalizado extraerá el dominio example.com de URLs coincidentes. El grupo de no captura (?: ) no se incluirá en las coincidencias.
Si deseas extraer toda la coincidencia, simplemente coloca paréntesis alrededor de toda tu cadena de regex, así:
(https?://.*?.com)
Si tu regex no es válido, verás un mensaje de error como este:
Error in custom regex: missing ) at position 5
Si tu regex no incluye un grupo de captura, verás un mensaje de error como este:
Error in custom regex: no such group
Usa siempre un solo grupo de captura cuando trabajes con regex personalizado. Aquí tienes un ejemplo rápido:
[
r'(my regex)', # Esto produce 'my regex' si el patrón coincide
r'my (re)gex', # Esto produce 're' si el patrón coincide
]
Usar más de un grupo de captura puede causar resultados inesperados. Mira este ejemplo:
[
r'my regex', # Esto no produce nada
r'(my) (re)gex', # Esto produce 'my' si el patrón coincide
]
¿Por qué? Porque el resultado siempre producirá solo la primera coincidencia de grupo de cada regex.
Para consultas regex más complicadas, puedes combinar grupos de captura y no captura así:
[
r'(?:my|your) (re)gex', # Esto produce 're' si el patrón coincide
]
Ahora puedes comparar la sintaxis (?: ) para grupos de no captura vs la sintaxis ( ) para el grupo de captura.
Si iocextract no se ajusta a tu caso de uso, existen varios proyectos similares. Revisa las etiquetas defang e indicators-of-compromise en GitHub, así como:
Si deseas automatizar la extracción, enriquecimiento, exportación y más de IOCs, echa un vistazo a ThreatIngestor.
Si trabajas con reglas YARA, puede que te interese plyara.
Si tienes una técnica de defanging que no pasa por el extractor, o si encuentras algún error, los Pull Requests e Issues son siempre bienvenidos. La biblioteca se publica bajo una licencia GPL-2.0 license.
¿Lo estás usando? ¿Quieres ver tu sitio listado aquí? ¡Háznoslo saber!
| Técnica | Defanged | Refanged |
|---|
. -> [.] | 1[.]1[.]1[.]1 | 1.1.1.1 |
. -> (.) | 1(.)1(.)1(.)1 | 1.1.1.1 |
. -> \. | 1\.1\.1\.1 | 1.1.1.1 |
| Parcial | 1[.1[.1.]1 | 1.1.1.1 |
| Cualquier combinación | 1.)1[.1.)1 | 1.1.1.1 |
| Técnica | Defanged | Refanged |
|---|
. -> [.] | 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] |
| Parcial | me@} example[.com | [email protected] |
| Espacios agregados | me@example [.] com | [email protected] |
| Cualquier combinación | me @example [.)com | [email protected] |
| Técnica | Defanged | Refanged |
|---|
. -> [.] | example[.]com/path | http://example.com/path |
. -> (.) | example(.)com/path | http://example.com/path |
. -> \. | example\.com/path | http://example.com/path |
| Parcial | 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 |
| Cualquier combinación | hxxp__ example( .com[/]path | http://example.com/path |
| Codificado en hex | 687474703a2f2f6578616d706c652e636f6d2f70617468 | http://example.com/path |
| Codificado en URL | http%3A%2F%2fexample%2Ecom%2Fpath | http://example.com/path |
| Codificado en base64 | aHR0cDovL2V4YW1wbGUuY29tL3BhdGgK | http://example.com/path |