- 2026, jue 11 junio
- Laboratorio
- @fotosycaptura
- #laboratorio, #programacion, #software, #blog, #config, #contenedor, #emacs

En una de estas clases introductorias de un diplomado dedicados al Blue Team, presentaron muy por encima un programa llamado OpenCTI... Y me pareció bien interesante como para intentar desplegarlo en un laboratorio o en una Intranet de algún trabajo...
Seguramente estarás pensando que necesitas para poder montarlo y tenerlo configurado... Nah, seguro que ni pájara idea tienes... XDDD Bien, como soy un ser de pura bondad, te iluminaré... Con la linterna del conocimiento... XD
Así que, dicho eso, veremos:
Qué es OpenCTI
OpenCTI es una plataforma Open Source de Cyber Threat Intelligence. Sirve para centralizar, estructurar y relacionar información como:
- Actores de amenaza;
- Campañas;
- Malware;
- TTPs;
- Indicadores IOC;
- Observables: IPs, dominios, hashes, URLs;
- Reportes;
- Relaciones con MITRE ATT&CK.
La idea es que no tengas datos sueltos, sino un grafo de conocimiento de amenazas basado en STIX2, con API GraphQL, frontend web y conectores hacia herramientas como MISP, TheHive, MITRE ATT&CK, etc
Si a estas alturas no estás entendiendo nada, te recomiendo que no sigas viendo en la carpeta de Laboratorio, digo yo, para que después no me reclames. Yo con esto entiendo que ya estás advertido…
Instalación
La instalación no fue compleja, se supone que a estas alturas de la vida, y por el hecho de que este post está etiquetado con contenedor, sabrás que habrá que usar Docker.
Además de ello, te recomiendo tener:
- Idealmente 16 GB en memoria RAM.
- 80 GB en espacio de disco. Si te parece demasiado, piensa que se instalará en conjunto además: Elasticsearch/OpenSearch, Redis, RabbitMQ, MinIO, workers y diversos conectores.
- Linux. Bueno, en teoría puedes usar WSL si usas WinBugs, pero como no lo he probado, esto es pura teoría… XD
Eso al menos en términos de Hardware.
Descarga
En este punto asumiré que tienes git, jq, openssl, y también no menos importante Docker. Si no es así te sugiero mirar por acá.
Una vez que cumplas con ello, necesitarás en algún lugar de tu disco duro deberás crear una carpeta y clonar un repositorio. Para ello haz lo siguiente:
mkdir -p ~/lab/opencti
cd ~/lab/opencti
git clone https://github.com/OpenCTI-Platform/docker.git
cd docker
cp .env.sample .env
Configuración
Tendrás que editar el archivo .env que copiaste en la última instrucción del bloque de código reciente. Puedes usar tu editor de texto favorito, es decir Emacs, o por último ViM. Si usas otro: fuera de mi iglesia XDD 1
Necesitarás cambiar a lo menos estos valores:
OPENCTI_HOST=localhost
OPENCTI_PORT=8080
OPENCTI_EXTERNAL_SCHEME=http
OPENCTI_ADMIN_EMAIL=admin@opencti.local
OPENCTI_ADMIN_PASSWORD=UnaClaveUltraySeguraAqui
OPENCTI_ADMIN_TOKEN=<uuid>
OPENCTI_HEALTHCHECK_ACCESS_KEY=<uuid>
OPENCTI_ENCRYPTION_KEY=<clave_base64>
Para los valores uuid y clave en base64 necesitarás ejecutar:
uuidgen
openssl rand -base64 32
Con esos comandos obtendrás unos valores adecuados, de lo contrario, es posible que no te funcione y después estés pasando rabias… Y si te pasa eso, es por no leerme y seguir mis instrucciones al pie de la letra…
Configuración de Elastic Search
Elastic Search es bien especial en sus requisitos y parámetros de funcionamiento… Por tanto, te recomiendo que realices lo siguiente antes de desplegar el contenedor:
sudo sysctl -w vm.max_map_count=1048575
echo "vm.max_map_count=1048575" | sudo tee /etc/sysctl.d/99-opencti.conf
sudo sysctl --system
Desplegando (Por fin)
Si te pareció eterno, intenta hacerle una imagen de disco a un disco de 1 TB y después a analizarlo mediante métodos de informática forense… Ejem…
Bueno, vamos con lo que sigue…
cd ~/lab/opencti/docker
docker compose pull
docker compose up -d
Puedes revisar el estado usando:
docker compose ps
docker compose logs -f opencti
Si todo ha resultado bien, entonces tendrás que ir a tu navegador Firefox favorito e ir a la ruta
http://localhost:8080
Verás una hermosa página en azul en la que pedirá las credenciales… Si te preguntas cuales…. Creo que necesitas que te diga Fuera de mi iglesia, o también te podría decir deja la informática, no es para ti. También te diré lo mismo si usas otro navegador que no sea Firefox.
Qué bonito ¿Y ahora?
Pues ya está, listo… ¡Adiós!
… XD
Pero casi, deberías de comenzar a explorar su Dashboard2
Ahí puedes observar y hacer muchas cosas, como por ejemplo:
- Explorar entidades: Intrusion Sets, Malware, Campaigns, Indicators.
- Activar o revisar conectores como MITRE ATT&CK.
- Crear manualmente un observable, por ejemplo una IP sospechosa.
- Relacionar la IP con un reporte o amenaza.
- Exporta información en STIX/CSV para ver cómo estructura los datos.
- Y muchas cosas más… ¡Llama ahora, llama ya! XD
Y… ¿Conectores?
Aún no estas preparado, dijo Illidan Tempestira3, pero si quieres experimentar, tendrás que buscar por internet…
Pero vamos, no soy tan malo… XDD, te mostraré como ingresar por ejemplo uno muy bueno llamado Alienvault. Para ello, deberías dirigirte a la página de AlienVault y registrarte.
Busca el API KEY OTX.
También necesitarás un uuid, que lo generarás tal como se realizó en el apartado anterior…
Ahora, con tu editor Emacs o VIM favorito, editarás el archivo Docker-Compose.yml y buscarás por ejemplo Mitre. Justo después de ello y fijándote que estás en el apartado de conectores, agregarás lo siguiente:
connector-alienvault:
image: opencti/connector-alienvault:latest
environment:
- OPENCTI_URL=http://localhost
- OPENCTI_TOKEN=ChangeMe # <-- Acá colocarás el token de OpenCTI, está más arriba, puedes copiar y pegar el mismo que está en la sección de Mitre.
- CONNECTOR_ID=8bbae241-6289-4faf-b7d6-7503bed50bbc # Optional (default: 8bbae241-6289-4faf-b7d6-7503bed50bbc) <-- Acá colocarás tu uuid generado.
- CONNECTOR_NAME=AlienVault # Optional (default: AlienVault)
- CONNECTOR_SCOPE=alienvault # Optional (default: alienvault)
- CONNECTOR_LOG_LEVEL=error # Optional (default: error)
- CONNECTOR_DURATION_PERIOD=PT30M # Optional (default: PT30M) - ISO8601 Format starting with "P" for Period ex: "PT30M" = Period time of 30 minutes
- ALIENVAULT_BASE_URL=https://otx.alienvault.com # Optional (default: https://otx.alienvault.com)
- ALIENVAULT_API_KEY=ChangeMe # Required <-- Acá colocarás el API KEY OTX
- ALIENVAULT_TLP=White # Optional (default: White)
- ALIENVAULT_CREATE_OBSERVABLES=true # Optional (default: true)
- ALIENVAULT_CREATE_INDICATORS=true # Optional (default: true)
- ALIENVAULT_PULSE_START_TIMESTAMP=2020-05-01T00:00:00 # Optional (default: 2020-05-01T00:00:00) - ISO 8601 format, UTC - BEWARE! Could be a lot of pulses!
- ALIENVAULT_REPORT_TYPE=threat-report # Optional (default: threat-report)
- ALIENVAULT_REPORT_STATUS=New # Optional (default: New) - New, In progress, Analyzed and Closed
- ALIENVAULT_GUESS_MALWARE=false # Optional (default: false) - Use tags to guess malware
- ALIENVAULT_GUESS_CVE=false # Optional (default: false) - Use tags to guess CVE
- ALIENVAULT_EXCLUDED_PULSE_INDICATOR_TYPES=FileHash-MD5,FileHash-SHA1 # Optional (default: "") - Comma-separated list of Pulse indicator types to exclude
- ALIENVAULT_ENABLE_RELATIONSHIPS=true # Optional (default: true) - Enable/Disable relationship creation between SDOs
- ALIENVAULT_ENABLE_ATTACK_PATTERNS_INDICATES=true # Optional (default: true) - Enable/Disable "indicates" relationships between indicators and attack patterns
- ALIENVAULT_FILTER_INDICATORS=false # Optional (default: false) - Filter indicators by their created datetime
- ALIENVAULT_DEFAULT_X_OPENCTI_SCORE=50 # Optional (default: 50) - The default x_opencti_score to use for indicators
- ALIENVAULT_X_OPENCTI_SCORE_IP=60 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for IP indicators
- ALIENVAULT_X_OPENCTI_SCORE_DOMAIN=70 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for Domain indicators
- ALIENVAULT_X_OPENCTI_SCORE_HOSTNAME=75 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for Hostname indicators
- ALIENVAULT_X_OPENCTI_SCORE_EMAIL=70 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for Email indicators
- ALIENVAULT_X_OPENCTI_SCORE_FILE=80 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for StixFile indicators
- ALIENVAULT_X_OPENCTI_SCORE_URL=80 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for URL indicators
- ALIENVAULT_X_OPENCTI_SCORE_MUTEX=60 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for Mutex indicators
- ALIENVAULT_X_OPENCTI_SCORE_CRYPTOCURRENCY_WALLET=80 # Optional (default: uses default_x_opencti_score) - The x_opencti_score to use for Cryptocurrency Wallet indicators
restart: always
Se cuidadoso con el tema de los espacios, ve guiándote con el anterior de Mitre, no uses la tecla tab.
Una vez que hayas terminado con ello, guarda y sale, y ahora tocará verificar si el archivo quedó correcto para su ejecución. La manera de comprobarlo será ejecutando:
docker compose config
Si de resultado te arroja el contenido del archivo completo de docker-compose.yml, entonces todo está bien, en caso contrario, deberás de corregir la indentación, que muy probablemente no me hayas hecho caso y hayas cometido un error… Si ni para eso sirves… En fin…
Luego, hay que levantar el contenedor, digo el conector, ¿O era el contenedor? Es que ¿Sabes? te vas a sorprender, es casi la misma manera de levantarla:
docker compose up -d connector-alienvault
Puedes revisar los logs del conector desde la terminal mediante:
docker compose logs -f connector-alienvault
Si todo va bien, ya puedes ir a la interfaz de OpenCTI e ir hacia Datos, Ingestión, AlienVault.
Revisando la ingesta de Alientvault
Si se ve similar, entonces vas bien… Solo… Un detalle.. Verás que no hay progreso… Y eso es porque te faltará suscribirte a los Pulses… Así que, ve a la página de Alientvault y suscribirte debes, es gratis… Solo, no te suscribas a todo lo que vez, prueba con uno… La información que hay es demasiada y puede que luego el servidor que estás armando se encuentre sin poder procesar más información… Quizás ahí también tengas que jugar un poco con el tiempo en el que realiza la tarea…
Suscribiéndose
Una vez que hayas realizado esto, ahora sí luego de un momento comenzará a aparecer una barra de progreso y se estará procesando la información… Ten paciencia… El profesor del diplomado tardó toda una noche… Yo he tardado 2 días, le he dado demasiada información…
Si todo te ha ido bien, verás algo como esto:
Ya comienza a visualizarse información interesante
Acá puedes observar que:
- El conector está importando datos de forma correcta.
- Ya creó un Threat Report.
- Está creando entidades relacionadas.
- Está importando observables (IPs, dominios, URLs).
- Está importando patrones ATT&CK y relacionándolos con el informe.
Y lo más importante: el programa ya está trabajando, y relacionando información automáticamente.
¡Hasta la próxima!
Hotfix
Hace unos días me encontré con una publicación acá en la que mencionan un bug conocido respecto a un conector de cierto alien… Por tanto, les comento un poco los pasos para la resolución.
Lo primero será ingresar a la terminal y desde ahí ingresar a la terminal4 del contenedor. Pero si no sabes que nombre o de que manera acceder te lo explicaré así que tranquilo.
Primero, revisa que contenedor es del conector, por ejemplo tomemos el del extraterrestre como ejemplo:
docker ps | grep alienvault
Una vez ubicado podrás ingresar como:
docker exec -it f4683c09c4d8 /bin/sh
Siendo ese revoltijo de números y letras el identificador del contenedor. También funciona si usas el nombre, pero yo uso ese ID.
Luego, una vez dentro de esa terminal, buscas el archivo client.py de esta manera:
find /opt -path "*alienvault/client.py" -o -path "*client.py" | grep alienvault
Una vez que lo encuentres e identifiques la ruta, deberás editarlo con algún editor de texto. En general suele estar disponible nano, pero yo usé VI.
Pero, antes de llegar y editar, te recomiendo hacer una copia de seguridad… Sí, se que eres manitos de hacha, así que mejor hay que hacer las cosas a prueba de we… De fallos…
cp /opt/opencti-connector-alienvault/alienvault/client.py /opt/opencti-connector-alienvault/alienvault/client.py.back
Bueno, ahora que has realizado la copia de seguridad por si dejas la escoba, vamos con lo siguiente:
vi /opt/opencti-connector-alienvault/alienvault/client.py
Puedes usar nano, yo no estoy acostumbrado, así que uso VI, ya que no hay emacs…
Finalmente, el archivo denominado client.py deberás editarlo y cambiar el código de la definición de la función por lo siguiente.
def get_pulses_subscribed(self, modified_since: datetime, limit: int = 20):
# Use activity endpoint instead of subscribed
activity_url = f"/api/v1/pulses/activity?limit={limit}"
response = self.otx.get(activity_url)
if response and isinstance(response, dict) and 'results' in response:
all_pulses = response['results']
filtered_pulses = []
for pulse in all_pulses:
# Add default TLP if missing
if 'tlp' not in pulse:
pulse['tlp'] = 'white'
if 'modified' in pulse:
pulse_modified_str = pulse['modified'].replace('Z', '+00:00')
try:
pulse_modified = datetime.fromisoformat(pulse_modified_str)
if pulse_modified >= modified_since:
filtered_pulses.append(pulse)
except Exception:
filtered_pulses.append(pulse)
else:
filtered_pulses.append(pulse)
pulses = parse_obj_as(List[Pulse], filtered_pulses)
else:
pulses = []
return pulses
Ya solo resta salir del contenedor con exit y tocaría reiniciar el contenedor sin recrearlo.
Básicamente, con todo lo anterior explicado, lo que estarás haciendo con esto es utilizar la API para obtener las actividades en vez de las suscripciones. Y con eso todo volverá a la normalidad. Al menos hasta este momento puedo decir que todo ha estado funcionando bien.
Notas al pie de página
1 Siempre quise decir eso XDD
2 También se le dice tablero.
3 Personaje famoso de World Of Warcraft, un juego multi jugador masivo muy popular en Internet.
4 Que recursivo