Chargement en cours

StepCA, Caddy et MISP via ACME !

StepCA, Caddy et MISP via ACME !

Découverte de trois tools d’un coup 😎

En faisant un peu de CTI dernièrement (Cyber Threat Intelligence), j’ai rebossé avec l’outil Open Source MISP, que je vais vous faire découvrir ici.

Cela dit, ‘me suis aperçu que l’image docker que j’utilisais suivait les best practices qui consistent à faire tourner l’applicatif en HTTP, et mettre un reverse proxy au devant… rien de sorcier en soit, et ça marche très bien.

D’ailleurs, le lien de l’image est celle-ci: https://github.com/NUKIB/misp, elle nous vient tout droit de l’équivalent de l’ANSSI mais en République Tchèque~ 🇨🇿

C’est du solide, souvent mise à jour, bien construite…

‘le p’tit truc, c’est que j’aime bien penser un peu moyen/long terme, et vu que pour 2030 environ, Google/Apple/Consort forcent pour réduire la durée de vie des certificats TLS à 30-60 jours, j’me suis dit que ce serait sympa d’en apprendre davantage sur le protocole ACME… et pourquoi pas, de setuper mon propre ACME local afin d’automatiser tout ce qui est Issue/Renewal de certifs 🙂

Ça tombe super bien car StepCA permet justement d’avoir le combo PKI/ACME interne ! Et pour ce qui est de Caddy comme reverse proxy, ‘ayant toujours utilisé Traefik j’ai voulu tester ça…

Du coup, here we go ! On va voir le lab rapidos puis j’vous parlerai de MISP juste en bas~

I) Présentation du lab

Rien de super poussé comme d’hab, on va décortiquer ça ensemble:

  • Une root CA, via StepCA, qui sera offline ;
  • Une sub CA, toujours via StepCA. En plus d’être autorité de certification, elle fera serveur ACME privé (et yes, j’ai oublié de noter son IP: 192.168.10.100) ;
  • Un p’tit serveur DNS, classique ;
  • Une VM faisant tourner Docker, avec deux conteneurs:
    • Un Caddy, qui fera reverse proxy et permettra du SSL offloading ;
    • Une instance MISP, qui tournera en HTTP sur localhost ;

Au tout début, j’pensais taper un Nginx proxy manager et faire du SSL offloading de manière classique, mais bon obligé de mettre le MISP et le proxy dans un même VLAN, sinon possible Man-in-the-Middle, vu que le flux échangé entre les deux sera HTTP… puis en réfléchissant me suis dit que je pouvais très bien faire tourner l’app en localhost, et comme ça hop, problem solved !

M’enfin bref, c’est bien beau tout ça mais vous connaissez l’ADN du blog, ‘toujours un peu de théorie avant la pratique ! 🥸

Alors du coup, c’est quoi MISP ? Et le fameux CTI ?

II) CTI et MISP, kézako ?

Le CTI, ou Cyber Threat Intelligence, c’est une discipline qui consiste à collecter, analyser et partager des informations sur les différences menaces informatiques. Le but ? Permettre aux équipes de sécurité de prévenir, détecter et réagir plus rapidement face aux attaques. En général ça inclut des indicateurs de compromission (IoC) comme des IP malveillantes, des hashs de fichiers ou des domaines utilisés par des acteurs malveillants 🙂

Et c’est précisément là qu’intervient MISP !


MISP, pour Malware Information Sharing Platform, c’est une plateforme open source dédiée au partage d’informations sur les menaces. En gros, il permet de centraliser les IoC, de structurer les données, et surtout de les partager facilement entre organisations ou équipes internes, tout en gardant un suivi et un historique… On peut par exemple télécharger des feeds directement depuis l’ANSSI, le CCB, ou encore d’acteurs privés comme ThreatConnect, ou CrowdStrike.

On peut résumer ça comme ça: le CTI nous indique quoi surveiller et pourquoi, et MISP nous permet de collecter, organiser, et partager ces infos. Ça fait partie de la « cybersécurité pro-active » comme on dit dans l’milieu~

Aller, assez de blabla, passons à la pratique maintenant !

III) Installation de la CA Root

Bien, la première étape est donc d’installer notre autorité de certification racine. Pour ce faire, rien de plus simple:

cat <<EOT > /etc/yum.repos.d/smallstep.repo
[smallstep]
name=Smallstep
baseurl=https://packages.smallstep.com/stable/fedora/
enabled=1
repo_gpgcheck=0
gpgcheck=1
gpgkey=https://packages.smallstep.com/keys/smallstep-0x889B19391F774443.gpg
EOT
dnf makecache && dnf install -y step-cli step-ca

Pour initialiser le tout, un petit step ca init et on obtient un joli shell interactif:

  • On choisit le mode Standalone ;
  • On renseigne le nom de notre CA ;
  • On bind l’IP qui sera utilisée ;
  • On créer le premier provisionner, nommé pki@tips4tech.local ;
  • Et enfin on tape un password pour la paire de clefs ;

Notre CA est prête, rapide non ? 😎

Maintenant créer un service systemd, histoire que le truc soit plus propre.

Pour ce faire, on va créer en premier lieu un fichier qui va contenir le password pour le déchiffrement:

Et ensuite, on créer notre service sous /etc/systemd/system/step-ca.service:

[Unit]
Description=Step CA Root (offline)
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/step-ca /root/.step/config/ca.json \
  --password-file /root/.step/secrets/root-ca-decrypt
Restart=on-failure
User=root

[Install]
WantedBy=multi-user.target

Et on valide le tout via un p’tit:

systemctl daemon-reload && systemctl enable --now step-root-ca

Maintenant, passons au setup de notre CA Intermediate !

IV) Configuration de la CA Intermediate

Identique à la root, il conviendra d’installer StepCA et de créer un service, je vous renvois donc plus au dessus 😊

Pensez simplement à changer le FQDN/IP, mais c’est strictement identique sinon.

Une fois fait, on peut supprimer la clé de notre « root« , car notre intermediate sera signée par notre « vraie » root:

rm ~/.step/secrets/root_ca_key

Ensuite on remplace le certificat de notre ca « root » par celui de notre « vraie » root:

# Sur notre VRAIE CA Root
root@pki-root-01:~/.step# cat certs/root_ca.crt
-----BEGIN CERTIFICATE-----
MIIBrDCCAVKgAwIBAgIRAMr5JmNuRJN0E0GjFK2iuRYwCgYIKoZIzj0EAwIwNDEU
MBIGA1UEChMLcGtpLXJvb3QtMDExHDAaBgNVBAMTE3BraS1yb290LTAxIFJvb3Qg
Q0EwHhcNMjYwMTE4MTgzMDU0WhcNMzYwMTE2MTgzMDU0WjA0MRQwEgYDVQQKEwtw
a2ktcm9vdC0wMTEcMBoGA1UEAxMTcGtpLXJvb3QtMDEgUm9vdCBDQTBZMBMGByqG
SM49AgEGCCqGSM49AwEHA0IABHhqbvXes0scZ6Lt5hZyWTDHcZ5RhNIajlAY+sgy
A2Mvkdg9tq3d+4JJh7WVKoBDGWUUntW6LQ9gJNhBFmGRRmSjRTBDMA4GA1UdDwEB
/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBRqLKkKjCEwevIg
vD0t3RDeIv1WvjAKBggqhkjOPQQDAgNIADBFAiB3irv6FCq7iJk8B8ojR3wM6DSD
EoGYjCMpJZ0u/CWnCAIhAM+ERvcryL4EStlv1NF2OVj8IU3MeTOhhdYRypz+GWqT
-----END CERTIFICATE-----
root@pki-root-01:~/.step#

# Sur notre Intermediate CA, on édite et on remplace
root@pki-int-01:~/.step# vim certs/root_ca.crt

Car oui, par défaut le step ca init génère une « CA Root/CA Intermediate », histoire de valider d’entrée de jeu certains POCs, mais une fois qu’on a compris le fonctionnement c’est facile 😉

Bref, on génère notre CSR, qui pour rappel veut dire certificate signing request:

step certificate create "pki-int-01" intermediate.csr intermediate_ca_key --csr

On transfère cette CSR vers notre CA Root, et puis on la signe:

step certificate sign --profile intermediate-ca intermediate.csr certs/root_ca.crt secrets/root_ca_key

Et ensuite, il ne nous reste plus qu’à le copier pour remplacer le certificat sur notre CA Intermediate, qui est sous certs/intermediate_ca.crt !

Et même chose pour la clef privée, qu’on a généré en même temps que le CSR:

rm /secrets/intermediate_ca_key
mv intermediate_ca_key /secrets/

On peut ensuite redémarrer le service, et c’est tout bon ! 😎

On peut d’ailleurs vérifier notre certificat et voir qu’il a bien été signé par notre root:

Et avant de clôturer, ‘pas oublier le petit firewall-cmd –permanent –zone=public –add-service=https si vous êtes sur RHEL/dérivés, pour ouvrir l’https afin d’utiliser l’ACME plus tard:

V) Configurations docker pour Caddy & MISP

Voici déjà notre fameux docker-compose, qui regroupera les différents services:

services:

  db:
    image: mariadb:10.11
    environment:
      MYSQL_ROOT_PASSWORD: "SuperP4$$w0Rd"
      MYSQL_DATABASE: misp
      MYSQL_USER: misp
      MYSQL_PASSWORD: "SuperP4$$w0Rd"
    volumes:
      - misp_db:/var/lib/mysql
    restart: unless-stopped
    networks:
      - web

  redis:
    image: redis:7
    restart: unless-stopped
    networks:
      - web

  misp-modules:
    image: ghcr.io/nukib/misp-modules:latest
    restart: unless-stopped
    networks:
      - web

  misp:
    image: ghcr.io/nukib/misp:latest
    depends_on:
      - db
      - redis
      - misp-modules
    environment:
      MYSQL_HOST: db
      MYSQL_LOGIN: misp
      MYSQL_PASSWORD: "SuperP4$$w0Rd"
      MYSQL_DATABASE: misp
      REDIS_HOST: redis
      MISP_BASEURL: "https://misp.tips4tech.local"
      MISP_UUID: "9f3c7a8e-6b42-4e5c-bd6d-1e0b2c9a7f44"
      MISP_ORG: "Tips4Tech-LAB"
      SECURITY_SALT: "d6c4e1a9f8b27e0c3a5d94b61f2e8c7a"
      MISP_MODULES_HOST: misp-modules
      MISP_MODULES_PORT: 6666
      MISP_EMAIL: "admin@mondomaine.fr"
      MISP_ADMIN_EMAIL: "admin@mondomaine.fr"
      MISP_ADMIN_PWD: SuperP4$$w0Rd
    restart: unless-stopped
    networks:
      - web

  caddy:
    image: caddy:latest
    depends_on:
      - misp
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy_data:/data
      - ./caddy_config:/config
      - ./root-ca.pem:/etc/caddy/trusted-roots/root-ca.pem:ro
    restart: unless-stopped
    networks:
      - web

volumes:
  misp_db:
  caddy_data:
  caddy_config:

networks:
  web:
    driver: bridge

Et notre fichier Caddyfile, qui contient simplement la config quant au Reverse Proxy. Par rapport à l’URL, vous pouvez la récup depuis la CA Intermediate:

misp.tips4tech.local {
    reverse_proxy misp:80

    tls {
        ca https://pki-int-01.tips4tech.local/acme/acme-01/directory
        ca_root /etc/caddy/trusted-roots/root-ca.pem
    }

    encode gzip
}

Pour résumer rapidos:

  • On créer une DB via MariaDB ;
  • On installe un Redis pour le caching ;
  • On créer une instance MISP, en localhost, pas de ports ouverts sur l’hôte ;
  • On créer une instance MISP-Modules ;
  • On créer un proxy via Caddy ;

Rien de super compliqué en soit, bien penser à adapter password/FQDN, créer le fichier Caddyfile, bref vous connaissez la chanson~

A noter que pour Caddy, on doit lui installer le certificat de notre CA Root ! Voir cette partie dans le Docker compose:

      - ./root-ca.pem:/etc/caddy/trusted-roots/root-ca.pem:ro

Et enfin la dernière étape, c’est de créer un provisioner pour l’ACME. En effet, lors du setup de la PKI intermediate, on a créé celui-ci « pki@tips4tech.local« , mais il ne prend pas en compte l’ACME.

Je vais pas épiloguer ici mais sachez qu’on peut créer plusieurs provisioners, l’approche est bien sympa mais on va zapper cette partie ici, bref:

On va rectifier ça et en créer un, en le nommant sobrement « acme-01« :

step ca provisioner add acme-01 --type ACME

Nous voilà fin prêts !

Et au lancement de notre docker compose, si on check les logs de notre conteneur Caddy…

Et si l’on se rend sur notre URL en HTTPS…

Tadaaaa ! 🥳

Vous avez donc réussi à:

  • Setuper une CA Root, ainsi qu’une Intermediate avec StepCA ;
  • Installer MISP via Docker ;
  • Installer Caddy et l’utiliser via ACME pour réaliser du SSL offloading sur un second conteneur en localhost, afin d’automatiser la gestion de vos certificats TLS et d’éviter du possible MITM ;

Plutôt pas mal j’dois dire 😎

VI) Conclusion et side notes

Tout est donc fonctionnel ! Après comme toujours, il s’agit ici d’un labo, si vous désirez passer en production-ready, y’a pas mal de bricoles à ajuster. Pour le coup, la doc de chez StepCA est vraiment bien fichue, avec pléthore de recommandations et best-practices: https://smallstep.com/docs/step-ca/certificate-authority-server-production/#good-security-practices.

Concernant l’ACME itself, voir la génération de certificats en général, vous aurez vu que nous n’avons pas fait de fine-tuning:

Ici par exemple, on voit que le certificat est valable 24h, et qu’il n’y a pas d’attributs spécifiques par défaut… alors calmez-vous, calmez-vous:

  • Valable 24h certes, mais Caddy fait le renewal bien avant qu’il soit expiré, donc pas de souci, le tout est automatique ;
  • Concernant les attributs, on peut utiliser des templates, du genre « step ca provisioner update acme-01 \ –x509-template-file=/path/to/my-template.tpl« , ou encore update en brut le provisioner via CLI en faisant des « step ca provisioner update acme-01 –x509-default-duration=2160h » ;

On peut aussi noter qu’il n’y a pas de challenges actuellement, donc n’importe quel asset sur notre réseau peut obtenir un certificat… en général on met en place des restrictions IPs + challenge du genre http-01/dns-01, voir plus encore, mais encore une fois cet article n’a pas pour vocation d’être un guide « enterprise ready« .

Bref, si vous souhaitez affiner, optimiser, et plus encore, RTFM comme on dit!

Pour ma part c’est une très chouette découverte, j’avoue être resté encore à titre privé avec ma bonne vieille EasyRSA, mais je pense sauter le pas et pleinement migrer sur cette nouvelle solution.

A noter d’ailleurs qu’il y a moyen via Prometheus de réaliser une belle page web permettant d’obtenir la liste des certificats issued, leur durée de validité, etc… ‘p’tet un second article, qui sait?

Sur ce, je n’ai plus qu’à vous souhaiter une belle journée/belle soirée, et vous reviens très vite !

*Et oui, mon lab physique arrive vraiment soon ! 😌

Laisser un commentaire