
Herramienta de recolección de artefactos para sistemas *nix
fennec es una herramienta de recolección de artefactos escrita en Rust para ser utilizada durante la respuesta a incidentes en sistemas basados en *nix. fennec permite escribir un archivo de configuración que contiene cómo recolectar artefactos.
fennec 0.4.1 AbdulRhman Alfaifi [email protected] Aritfact collection tool for *nix systems
USAGE: fennec [OPTIONS]
OPTIONS: -c, --config Sets a custom config file (Embedded : true)
-o, --output <FILE>
Sets output file name [default: ABDULRHMAN-PC.zip]
-l, --log-level <LEVEL>
Sets the log level [default: info] [possible values: trace, debug, info, error]
-f, --log-file <FILE>
Sets the log file name [default: fennec.log]
-u, --upload-artifact <CONFIG>...
Upload configuration string. Supported Protocols:
* s3 : Upload artifact package to S3 bucket (ex. minio)
* Format :
s3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@(http|https)://<HOSTNAME>:<PORT>/<BUCKET_NAME>:<PATH>
* Example (minio): s3://minioadmin:minioadmin@http://192.168.100.190:9000/fennec:/
* aws3 : Upload artifact package to AWS S3 bucket
* Format : aws3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@<AWS_REGOIN>.<BUCKET_NAME>:<PATH>
* Example: aws3://AKIAXXX:[email protected]:/
* scp : Upload artifact package to a server using SCP protocol
* Format : scp://<USERNAME>:<PASSWORD>@<HOSTNAME>:<PORT>:<PATH>
* Example: scp://testusername:[email protected]:22:/dev/shm
-q, --quiet
Do not print logs to stdout
-t, --timeout <SEC>
Sets osquery queries timeout in seconds [default: 60]
-h, --help
Print help information
--non-root
Run Fennec with non root permisions. This isn't recommended, most artifacts require root
permissions
--osquery-path <PATH>
Sets osquery path, if osquery is embedded it will be writen to this path otherwise the
path will be used to spawn osquery instance (Embedded : true) [default: ./osqueryd]
--output-format <FORMAT>
Sets output format [default: jsonl] [possible values: jsonl, csv, kjson]
--show-config
Show the embedded configuration file
--show-embedded
Show the embedded files metadata
-V, --version
Print version information
* `-c`, `--config` : Usar el archivo de configuración especificado en lugar de la configuración incrustada
* `-f`, `--log-file` : Cambiar el nombre predeterminado del archivo de registro (predeterminado: `fennec.log`)
* `-h`, `--help` : Imprimir mensaje de ayuda
* `-l`, `--log-level` : Cambiar el nivel de registro predeterminado (predeterminado: `info`)
* `-o`, `--output` : Cambiar el nombre de archivo de salida predeterminado para el archivo zip (predeterminado: `{HOSTNAME}.zip`, donde hostname es el nombre del host de la máquina evaluado en tiempo de ejecución)
* `--osquery-path` : Ruta al ejecutable de osquery. Este valor se usará según estas condiciones:
* Si el binario de osquery está incrustado en `fennec`, se extraerá y volcará en `--osquery-path`
* Si osquery no está incrustado en `fennec`, se usará el binario de osquery en la ruta `--osquery-path`
* `--output-format` : Elegir el formato de salida. Formatos admitidos:
* jsonl : Objetos JSON separados por nueva línea (predeterminado)
* csv: Valores separados por comas
* kjson: Use este formato si desea cargar el archivo resultante en la plataforma de análisis [Kuiper](https://github.com/DFIRKuiper/Kuiper).
* `-q`, `--quiet` : No imprimir registros en `stdout`
* `--non-root`: Ejecutar Fennec con permisos de no root. Por defecto, Fennec requiere permisos `root` y saldrá con un mensaje de error si no es root.
* `--show-config` : Imprimir la configuración incrustada y luego salir
* `--show-embedded` : Mostrar archivos incrustados
* `-t`, `--timeout` : Establece el tiempo de espera en segundos para cada osquery en el tipo de artefacto de consulta
* `-u`, `--upload-artifact` : Cargar paquete de artefactos a un servidor remoto. Protocolos admitidos:
* `s3` : Cargar paquete de artefactos a un bucket S3
* `Formato` : s3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@(http|https)://<HOSTNAME>:<PORT>/<BUCKET_NAME>:<PATH>
* `Ejemplo`: s3://minioadmin:minioadmin@http://192.168.100.190:9000/fennec:/
* `aws3` : Cargar paquete de artefactos a un bucket de AWS S3
* `Formato` : aws3://<ACCESS_KEY>:<SECRET_ACCESS_KEY>@<AWS_REGOIN>.<BUCKET_NAME>:<PATH>
* `Ejemplo`: aws3://AKIAXXXXXXXXXXXXXXXXX:[email protected]:/
* `scp` : Cargar paquete de artefactos a un servidor usando protocolo SCP
* `Formato` : scp://`<USERNAME>`:`<PASSWORD>`@`<HOSTNAME>`:`<PORT>`:`<PATH>`
* `Ejemplo`: scp://testusername:[email protected]:22:/dev/shm
* `-V`, `--version` : Imprimir la versión de `fennec` y luego salir
## Compilar con dependencias 👨💻
fennec depende de `osquery` para ejecutar los artefactos de tipo `query`. El directorio llamado `deps` contiene el archivo que se incrustará en el binario dependiendo del SO y la arquitectura de destino. Antes de compilar, siga los pasos a continuación:
* Modificar el archivo de configuración `deps/<TARGET_OS>/fennec.yaml` según sea necesario
* Construir el binario usando uno de los siguientes comandos:
* enlazado dinámicamente: ```bash
cargo build --release
También puedes usar los binarios precompilados en la sección de lanzamientos.
El siguiente es un ejemplo ejecutado en Ubuntu 20 con las mismas configuraciones de este repositorio:

Para generar datos al formato soportado por Kuiper, ejecuta Fennec con el siguiente argumento:```bash sudo ./fennec --output-format kjson
o agregue lo siguiente a la sección `args` en la configuración:```yaml
args:
- "--output-format"
- "kjson"
recompile y luego ejecute:```bash sudo ./fennec
luego suba el archivo zip resultante a Kuiper, a continuación se muestra un ejemplo:

## Configuración🔨
Por defecto, la configuración en la ruta `deps/<TARGET_OS>/fennec.yaml` se incrustará en el ejecutable durante la compilación. La configuración está en formato YAML y tiene dos secciones:
### Args
contiene una lista de argumentos que se pasarán al ejecutable como argumentos de línea de comandos, a continuación se muestra un ejemplo de la sección `args` que establecerá el formato de salida a `jsonl` y el nombre del archivo de registro a `fennec.log`:```yaml
args:
- "--output-format"
- "jsonl"
- "--log-file"
- "fennec.log"
...
Los argumentos de línea de comandos se utilizarán en las siguientes prioridades:
Contiene una lista de artefactos a recolectar. Cada artefacto contiene los siguientes campos:
stdout en caso del artefacto commandEjecuta consultas SQL de osquery. El siguiente ejemplo de artefacto para recuperar todos los usuarios del sistema:```yaml artifacts:
#### Tipos de artefacto: Recopilación
Este tipo de artefacto recopila archivos/carpetas especificados en el campo **paths**. El siguiente es un ejemplo de este tipo de artefacto que recopila registros del sistema:```yaml
artifacts:
- name: logs
type: collection
description: "Collect system logs"
paths:
- '/var/log/**/*'
...
Ejecuta comandos del sistema utilizando el intérprete de comandos del shell en el siguiente orden de prioridad:
Este es un ejemplo de este tipo de artefacto que recupera inicios de sesión fallidos:```yaml artifacts:
Este tipo de artefacto ejecutará los comandos en la lista `commands` y analizará la salida `stdout` utilizando la expresión regular especificada en el campo `regex`. Tenga en cuenta que la expresión regular solo se procesará en el flujo `stdout` y no en `stderr`. Además, el campo `regex` es opcional. Aquí hay un ejemplo de los resultados tanto usando el campo `regex` como sin él:
##### Sin el campo `regex````json
{
"line": 0,
"stdout": "root pts/1 2023-09-12T17:13:28+03:00 - 2023-09-12T17:13:28+03:00 (00:00)"
}
{ "username": "root", "tty": "pts/1", "src_ip": null, "login_time": "2023-09-12 14:13:28", "logout_time": "2023-09-12T17:13:28+03:00", "duration": "00:00", "@timestamp": "2023-09-12 14:13:28" }
#### Tipos de Artefacto: Parse
Este tipo de artefacto proporciona la capacidad de analizar archivos de texto usando regex y devolver los datos en un formato estructurado. El siguiente ejemplo analiza los registros de acceso de nginx y devuelve los resultados en un formato estructurado:```yaml
artifcats:
- name: nginx_access
type: parse
description: "Nginx access logs"
paths:
- /var/log/nginx/access.*
regex: '(?P<c_ip>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) - (?P<remote_user>[^ ]+) \[(?P<time>[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2} \+[0-9]{4})\] "(?P<method>[A-Z]+)?[ ]?(?P<uri>.*?)[ ]?(HTTP/(?P<http_prot>[0-9\.]+))?" (?P<status_code>[0-9]{3}) (?P<body_bytes_sent>[0-9]+) "(?P<referer>.*?)" "(?P<user_agent>.*?)"'
Esta configuración leerá los archivos en la ruta /var/log/nginx/access.* línea por línea y ejecutará la expresión regular para extraer campos. Este artefacto también verifica si el archivo está en formato gzip, que se utiliza para comprimir registros antiguos y ahorrar espacio, y los descomprime y analiza. La expresión regular debe estar en formato de capturas nombradas como se documenta en la biblioteca de expresiones regulares de Rust. El siguiente es un ejemplo de un registro de acceso de nginx antes y después del análisis:
* registro analizado ```json
{
"c_ip": "192.168.133.70",
"remote_user": "-",
"time": "23/Jan/2022:19:14:37 +0000",
"method": "GET",
"uri": "/blog/",
"http_prot": "1.1",
"status_code": "200",
"body_bytes_sent": "2497",
"referer": "https://u0041.co/",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
"full_path": "/var/log/nginx/access.log.9.gz"
}
Este campo opcional se puede usar para cambiar los nombres de los campos de resultado y ejecutar post procesamiento llamado modificadores sobre el valor del campo. El siguiente ejemplo mostrará los resultados de analizar registros de acceso de nginx sin maps:
* registro original```verilog
192.168.133.70 - - [23/Jan/2022:19:14:37 +0000] "GET /blog/ HTTP/1.1" 200 2497 "https://u0041.co/" "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0"
Para cambiar el nombre del campo `time` a `@timestamp`, agregamos la siguiente configuración de maps a las configuraciones del artefacto:```yaml
artifcats:
- name: nginx_access
type: parse
description: "Nginx access logs"
paths:
- /var/log/nginx/access.*
regex: '(?P<c_ip>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) - (?P<remote_user>[^ ]+) \[(?P<time>[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2} \+[0-9]{4})\] "(?P<method>[A-Z]+)?[ ]?(?P<uri>.*?)[ ]?(HTTP/(?P<http_prot>[0-9\.]+))?" (?P<status_code>[0-9]{3}) (?P<body_bytes_sent>[0-9]+) "(?P<referer>.*?)" "(?P<user_agent>.*?)"'
maps:
- from: time #change field name from
to: '@timestamp' # to this name
Después de ejecutar la herramienta de recolección con la configuración en el mismo log de acceso de nginx, obtenemos la siguiente salida:```json { "c_ip": "192.168.133.70", "remote_user": "-", "@timestamp": "23/Jan/2022:19:14:37 +0000", "method": "GET", "uri": "/blog/", "http_prot": "1.1", "status_code": "200", "body_bytes_sent": "2497", "referer": "https://u0041.co/", "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "full_path": "/var/log/nginx/access.log.9.gz" }
#### Modificadores
modificadores proporciona procesamiento posterior al valor de campo de los resultados del artefacto. Por ejemplo, reformateando fecha y hora. Continuando con el ejemplo anterior, podemos cambiar el formato de fecha y hora en el campo `@timestamp` al formato `%Y-%m-%d %H:%M:%S`. Podemos agregar lo siguiente a las configuraciones del artefacto para lograr eso:```yaml
artifacts:
- name: nginx_access
type: parse
description: "Nginx access logs"
paths:
- /var/log/nginx/access.*
regex: '(?P<c_ip>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) - (?P<remote_user>[^ ]+) \[(?P<time>[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2} \+[0-9]{4})\] "(?P<method>[A-Z]+)?[ ]?(?P<uri>.*?)[ ]?(HTTP/(?P<http_prot>[0-9\.]+))?" (?P<status_code>[0-9]{3}) (?P<body_bytes_sent>[0-9]+) "(?P<referer>.*?)" "(?P<user_agent>.*?)"'
maps:
- from: time
to: "@timestamp"
modifier:
name: datetime_to_iso
parameters:
input_time_format: '%d/%b/%Y:%H:%M:%S %z'
output_time_format: '%Y-%m-%d %H:%M:%S'
El registro resultante se verá así:```json { "c_ip": "192.168.133.70", "remote_user": "-", "@timestamp": "2022-01-23 19:14:37", "method": "GET", "uri": "/blog/", "http_prot": "1.1", "status_code": "200", "body_bytes_sent": "2497", "referer": "https://u0041.co/", "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "full_path": "/var/log/nginx/access.log.9.gz" }
Los modificadores disponibles son:
| Nombre | Detalles | input_time_format | output_time_format |
| ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------------ |
| epoch_to_iso | Convierte la marca de tiempo epoch a un formato de fecha y hora personalizado | N/A | especificar el formato de fecha y hora de salida , el valor predeterminado es `%Y-%m-%d %H:%M:%S` |
| datetime_to_iso | Reformatear la fecha y hora del formato `input_time_format` al formato `output_time_format` | especificar el formato de entrada de fecha y hora | especificar el formato de salida de fecha y hora , el valor predeterminado es `%Y-%m-%d %H:%M:%S` |
| time_without_year_to_iso | Formatear la fecha y hora sin datos de año del formato `input_time_format` al formato `output_time_format` | especificar el formato de entrada de fecha y hora | especificar el formato de salida de fecha y hora , el valor predeterminado es `%Y-%m-%d %H:%M:%S` |
| to_int | Convertir datos de cadena (como tipos de artefacto `command` y `parse`) a enteros (`i64` i.e. entero de 64 bits con signo). Esto es útil con campos como el tamaño de archivo para poder hacer comprobaciones como `size < 1024` utilizando la plataforma de datos de nuestra elección | N/A | N/A |
El modificador `time_without_year_to_iso` funciona de la siguiente manera:
* Agregar el año actual y luego verificar si el tiempo de análisis < tiempo actual, si es así, entonces es el tiempo correcto
* de lo contrario, es el año anterior
Este modificador asume que los registros son para **SOLO** un año, use este modificador con precaución
| Detalles del SO | Arquitectura | ¿Éxito? | Detalles |
|---|
| Ubuntu 20.04.3 LTS | x86_64 | ✅ | |
| Ubuntu 19.04 | x86_64 | ✅ | |
| Ubuntu 18.04.6 LTS | x86_64 | ✅ | |
| Ubuntu 17.04 | x86_64 | ✅ | |
| Ubuntu 16.04.7 LTS | x86_64 | ✅ | |
| Ubuntu 15.10 | x86_64 | ✅ | |
| Ubuntu 14.04.6 LTS | x86_64 | ✅ | |
| Ubuntu 13.04 | x86_64 | ✅ | |
| Ubuntu 12.04.5 LTS | x86_64 | ✅ | |
| CentOS 8.4.2105 | x86_64 | ✅ | |
| CentOS 7.9.2009 | x86_64 | ✅ | |
| CentOS 6.10 | x86_64 | ✅ | |
| CentOS 5.11 | x86_64 | ❌ | osquery requiere libc >= 2.12 |
| Ubuntu 20.04 | aarch64 | ✅ | |
| MacOS Monterey v12.0.1 | x86_64 | ✅ | Se requiere ajuste de configuración. Si tienes experiencia en artefactos de MacOS, siéntete libre de contribuir |
| Oracle Linux Server 7.9 | x86_64 | ✅ |