Au cours de cet article, nous allons voir :

  • Comment lancer une instance OWASP Zed Attack Proxy ( Abrégé ZAP le plus souvent ) avec Docker et sans java ! 😭
  • Comment rendre l'interface de OWASP ZAP disponible derrière un reverse proxy avec une authentification par mot de passe et du HTTPS : Nous allons pour cela utiliser Traefik.

OWASP ZAP : C'est quoi ?

C'est un outil open-source et très populaire, qui permet de scanner la sécurité de vos applications webs.

Il est très populaire car il possède une interface graphique très simple d'utilisation - au premier abord - et qui permet aux débutants d'effectuer des premiers tests en toute simplicité.

Mais l'outil étant très complet, les nombreuses options permettent également aux utilisateurs expérimentés d'effectuer des actions plus complexes ( script, automatisation, etc ).

Voici la page de démarrage d'OWASP ZAP :

Quick Start OWASP ZAP

Il suffit de saisir l'adresse à attaquer/scanner, un click sur le bouton ⚡Attack et votre scan est lancé !

🚩 Je vous rappelle que des tests d'intrusion doivent être effectués sur votre propre réseau/site ou avec le consentement du propriétaire.🚩

Par contre, lorsque j'essaye d'installer ZAP sur mon ordinateur voici le message obtenu :

ZAP nécessite Java !

Installer Java sur ma machine ?! Non merci.

Heureusement il existe une image Docker très simple d'utilisation !

OWASP ZAP : en mode Docker

L'image stable est tout simplement disponible ici :

https://hub.docker.com/r/owasp/zap2docker-stable/

Vous pouvez la récupérer avec la commande pull de Docker :

docker pull owasp/zap2docker-stable

Ou utiliser la dernière version hebdomadaire :

docker pull owasp/zap2docker-weekly

Ou encore le tout dernier build :

docker pull owasp/zap2docker-live

Enfin à noter qu'il existe également une version bare qui est allégée et ne contient que le strict minimum. Cette version est idéale afin de réaliser quelques tests de sécurité dans votre CI :

docker pull owasp/zap2docker-bare

Ces images peuvent être utilisées de plusieurs façons :

  • ZAP en mode Headless,
  • ZAP Headless avec xvfb,
  • ZAP Baseline Scan ( on passe en argument du container l'adresse à scanner, ainsi que quelques options ),
  • ZAP Cli, ( ZAP avec une CLI en python ),
  • ZAPR,

Et enfin - surtout - l'option qui m'intéresse aujourd'hui : Webswing.

Avec cette option de démarrage, je vais avoir accès à ZAP et son interface directement dans mon navigateur web : idéal pour débuter.

En ligne de commande cela donne :

docker run -it -d --name zap -u zap -p 8080:8080 -p 8090:8090 -i owasp/zap2docker-stable zap-webswing.sh

J'utilise ici la dernière version stable. Vous pouvez modifier la ligne afin d'utiliser la dernière version weekly.

Enfin il ne me reste plus qu'à accéder à l'interface via l'adresse suivante : HTTP://<IP_MACHINE>:8080/zap

Last stable ZAP with webswing

Traefik

Nous allons maintenant faire fonctionner notre outil ZAP derrière un reverse-proxy. Le plus simple pour réaliser cette opération va être d'utiliser l'outil docker-compose.

S'il n'est pas installé sur votre machine, vous pouvez suivre les commandes suivantes :

sudo curl -L "https://github.com/docker/compose/releases/download/1.26.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Ensuite je vais lancer une instance de Traefik avec un fichier docker-compose.yaml :

version: '3.8'
services:
  traefik:
    image: traefik:2.2
    restart: unless-stopped
    ports:
      # The HTTP port
      - "80:80"
      # The HTTPS port
      - "443:443"
      - "8080:8080"
    command:
      --accesslog
      --entrypoints.web.Address=:80
      --entrypoints.websecure.Address=:443
      --providers.docker
      --providers.docker.exposedbydefault=false
      --entrypoints.web.http.redirections.entryPoint.to=:443
      --entrypoints.web.http.redirections.entryPoint.scheme=https
      --certificatesresolvers.myresolver.acme.tlschallenge
      [email protected]
      --certificatesresolvers.myresolver.acme.storage=acme.json
      --entrypoints.websecure.http.tls.certresolver=myresolver
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
      # ssl volumes to store acme.json
      - certs:/letsencrypt
    networks:
      - web

volumes:
  certs:

networks:
  web:
    name: traefik_web

Et il ne me reste plus qu'à lancer ZAP avec une déclaration dans mon fichier docker-compose.yaml :

version: '3.8'
services:
  zap:
    image: owasp/zap2docker-stable
    command: 'zap-webswing.sh'
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080"]
      interval: 1m30s
      timeout: 10s
      retries: 3
      start_period: 40s
    labels:
      traefik.enable: true
      traefik.docker.network: traefik_web
      traefik.http.services.zap.loadbalancer.server.port: 8080
      traefik.http.routers.zap.rule: Host(`${ZAP_URL}`)
      traefik.http.routers.zap.entrypoints: websecure
    networks:
      - traefik_web

networks:
  traefik_web:
    external: true

Je change la commande de healthcheck, car celle lancée de base reste unhealthy sur ma machine.

Ce qui a pour effet de ne pas faire remonter la machine sur Traefik, car ce dernier ne prend pas en compte les containers dans cet état.

Je lance ma stack :

ZAP_URL=ZAP.MYDOMAIN.COM docker-compose up -d

Et je n'ai plus qu'à vérifier le bon fonctionnement de l'application en me rendant sur HTTPS://<ZAP.MYDOMAIN.COM>/zap :

ZAP with Traefik & HTTPS

Finalement je vais ajouter un middleware à Traefik pour ajouter une authentification basique :

version: '3.8'
services:
  zap:
    image: owasp/zap2docker-stable
    command: 'zap-webswing.sh'
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080"]
      interval: 1m30s
      timeout: 10s
      retries: 3
      start_period: 40s
    labels:
      traefik.enable: true
      traefik.docker.network: traefik_web
      traefik.http.services.zap.loadbalancer.server.port: 8080
      traefik.http.routers.zap.rule: Host(`${ZAP_URL}`)
      traefik.http.routers.zap.entrypoints: websecure
      traefik.http.middlewares.test-auth.basicauth.users: "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/"
      traefik.http.routers.zap.middlewares: 'test-auth'
    networks:
      - traefik_web

networks:
  traefik_web:
    external: true

Je relance mes services :

docker-compose down && docker-compose up -d

Enfin une dernière vérification :

Traefik authentication

Vous pouvez maintenant lancer un scan de sécurité de votre application web en quelques minutes à l'aide de Docker et Traefik !

Nous pourrons voir prochainement qu'il est également possible d'automatiser très facilement un simple scan de votre application avec un outil supplémentaire !

Cet article n'avait bien évidement pas la prétention de faire de vous ( et encore moins de moi 😉) des experts en cybersécurité. Il s'agit d'un premier pas vers une éventuelle meilleure sécurisation de votre application.

Mais ce que nous venons de voir ensemble n'est pas suffisant pour dormir sur ses deux oreilles !  Au besoin, et surtout si votre application héberge des données sensibles, n'hésitez pas à faire appel à un professionnel du secteur.

N'hésitez pas à permettre au blog de continuer à exister et à fournir un contenu de qualité - enfin je l'espère - au travers de vos dons sur : buymeacoff.ee/lfache
Et n'hésitez pas à m'apporter des remarques ou des commentaires sur Twitter, ou ici 👇