🛡️ OWASP Web Security

Cours OWASP ZAP — De A à Z

Scanner de sécurité web open source : proxy, spider, fuzzing, API testing et automatisation CI/CD.

11Chapitres
80+Exemples
ZAP 2.xVersion
Cyber WebOWASPScannerAPI TestingCI/CD
🔍

Aucun résultat pour cette recherche.

OWASP ZAP (Zaproxy) - Guide Complet de A à Z

Table des matières

  1. Introduction
  2. Installation et Configuration
  3. Interface et Concepts Fondamentaux
  4. Proxy et Interception
  5. Scan Passif et Actif
  6. Spider et Découverte
  7. Fuzzing et Tests Avancés
  8. Automatisation et Scripting
  9. API Testing
  10. Authentication et Session Management
  11. Reporting et Documentation
  12. ZAP en Mode Headless/CLI
  13. Intégration CI/CD
  14. Extensions et Add-ons
  15. Cas Pratiques et Scénarios Réels
  16. Bonnes Pratiques et Éthique

Introduction

Qu’est-ce qu’OWASP ZAP ?

OWASP Zed Attack Proxy (ZAP) est un scanner de vulnérabilités web open-source et gratuit. C’est l’un des projets phares de l’OWASP (Open Web Application Security Project).

Caractéristiques principales

Pourquoi utiliser ZAP ?

Avantages : - Gratuit et open-source - Facile à utiliser (GUI + CLI) - Excellent pour l’apprentissage - Intégration CI/CD native - Communauté active - Mises à jour fréquentes

ZAP vs Burp Suite

Critère ZAP Burp Suite
Prix Gratuit Gratuit (limité) / Payant
Open Source ✅ Oui ❌ Non
Interface Java Swing Java Swing
Automatisation ✅ Excellente ✅ Excellente (Pro)
Intégration CI/CD ✅ Native ⚠️ Limitée (Free)
Extensions ✅ Marketplace ✅ BApp Store
Courbe d’apprentissage Moyenne Moyenne
Support API ✅ Oui ✅ Oui

Installation et Configuration

Installation sur Linux (Debian/Ubuntu)

# Méthode 1 : Via Snap (recommandé)
sudo snap install zaproxy --classic

# Méthode 2 : Téléchargement direct
wget https://github.com/zaproxy/zaproxy/releases/download/v2.14.0/ZAP_2.14.0_Linux.tar.gz
tar -xvf ZAP_2.14.0_Linux.tar.gz
cd ZAP_2.14.0
./zap.sh

# Méthode 3 : Via package manager (peut être obsolète)
sudo apt update
sudo apt install zaproxy

# Vérification de l'installation
zap.sh -version

Installation sur macOS

# Méthode 1 : Homebrew
brew install --cask owasp-zap

# Méthode 2 : Téléchargement depuis le site officiel
# Télécharger depuis https://www.zaproxy.org/download/
# Ouvrir le fichier .dmg et glisser dans Applications

# Lancer ZAP
open /Applications/OWASP\ ZAP.app

# Ou via terminal
/Applications/OWASP\ ZAP.app/Contents/MacOS/OWASP\ ZAP.sh

Installation sur Windows

# Méthode 1 : Chocolatey
choco install zap

# Méthode 2 : Téléchargement installeur
# Télécharger ZAP_2.14.0_windows.exe depuis le site officiel
# Exécuter l'installeur

# Méthode 3 : Version portable
# Télécharger ZAP_2.14.0_windows.zip
# Extraire et exécuter zap.bat

# Lancer ZAP
"C:\Program Files\OWASP\Zed Attack Proxy\zap.bat"

Installation via Docker

# Pull de l'image officielle
docker pull zaproxy/zap-stable

# Lancer ZAP en mode daemon (headless)
docker run -u zap -p 8080:8080 -i zaproxy/zap-stable zap.sh -daemon -host 0.0.0.0 -port 8080 -config api.addrs.addr.name=.* -config api.addrs.addr.regex=true

# Lancer ZAP avec interface GUI (Linux avec X11)
xhost +local:docker
docker run -u zap -p 8080:8080 -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix zaproxy/zap-stable zap.sh

# Version weekly (dernières features)
docker pull zaproxy/zap-weekly

Configuration initiale

Premier lancement

# Lancer ZAP
zap.sh  # Linux/macOS
zap.bat # Windows

Au premier lancement, vous verrez :

  1. Session Persistence : - “Do you want to persist the ZAP session?” - Recommandation : Choisir “Yes, I want to persist this session”

  2. Quick Start : - Automated Scan - Manual Explore - Choisir selon votre besoin

Configuration du proxy

Paramètres par défaut : - Host : localhost ou 127.0.0.1 - Port : 8080

Pour changer le port : 1. Tools → Options → Local Proxies 2. Modifier “Address” et “Port” 3. Cliquer “OK”

# Ou via ligne de commande
zap.sh -port 8081

Configuration du certificat SSL

ZAP génère son propre certificat CA pour intercepter HTTPS.

Installation du certificat :

  1. Dans ZAP : Tools → Options → Dynamic SSL Certificates
  2. Cliquer “Save”
  3. Enregistrer owasp_zap_root_ca.cer

Installation dans le navigateur (Firefox) :

1. Firefox  Settings  Privacy & Security
2. Certificates  View Certificates
3. Authorities  Import
4. Sélectionner owasp_zap_root_ca.cer
5. Cocher "Trust this CA to identify websites"

Installation dans le navigateur (Chrome/Edge) :

1. Settings  Privacy and security  Security
2. Manage certificates  Authorities  Import
3. Sélectionner owasp_zap_root_ca.cer
4. Cocher "Trust this certificate for identifying websites"

Installation système (Linux) :

# Copier le certificat
sudo cp owasp_zap_root_ca.cer /usr/local/share/ca-certificates/zap.crt

# Mettre à jour les certificats
sudo update-ca-certificates

Installation système (macOS) :

# Ajouter au keychain
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain owasp_zap_root_ca.cer

Configuration du navigateur comme proxy

Firefox (manuel) :

1. Settings  General  Network Settings
2. Cliquer "Settings"
3. Sélectionner "Manual proxy configuration"
4. HTTP Proxy: localhost, Port: 8080
5. Cocher "Also use this proxy for HTTPS"
6. Cliquer "OK"

Chrome/Edge (via extension) :

1. Installer "FoxyProxy" ou "Proxy SwitchyOmega"
2. Configurer un profil :
   - HTTP: localhost:8080
   - HTTPS: localhost:8080
3. Activer le profil

Configuration système (Linux) :

# Temporary
export http_proxy=http://localhost:8080
export https_proxy=http://localhost:8080

# Ajouter au ~/.bashrc pour permanent
echo 'export http_proxy=http://localhost:8080' >> ~/.bashrc
echo 'export https_proxy=http://localhost:8080' >> ~/.bashrc

Interface et Concepts Fondamentaux

Vue d’ensemble de l’interface

┌─────────────────────────────────────────────────────────────┐
│  Menu Bar: File, Edit, View, Analyze, Report, Tools, Help  │
├─────────────────────────────────────────────────────────────┤
│  Top Toolbar: New Session, Spider, Active Scan, Attack...  │
├──────────────┬──────────────────────────────────────────────┤
│              │                                              │
│   Sites      │          Work Area (Tabs)                    │
│   Tree       │   - Quick Start                              │
│              │   - Request/Response                         │
│   [+] Sites  │   - Spider                                   │
│     [+] http │   - Active Scan                              │
│       GET    │   - Fuzzer                                   │
│       POST   │   - etc.                                     │
│              │                                              │
├──────────────┴──────────────────────────────────────────────┤
│  Bottom Tabs:                                               │
│  History | Search | Alerts | Output | Breakpoints          │
└─────────────────────────────────────────────────────────────┘

Panneau Sites Tree

Affiche l’arborescence des sites explorés.

Structure :

Sites
└── http://exemple.com
    ├── GET:index.php
    ├── GET:about.php
    ├── POST:login.php
    └── GET:admin
        └── GET:dashboard.php

Codes couleur : - 🔴 Rouge : Alerte haute sévérité - 🟠 Orange : Alerte moyenne - 🟡 Jaune : Alerte basse - 🔵 Bleu : Information - ⚪ Blanc : Pas d’alerte

Panneau History

Liste toutes les requêtes/réponses interceptées.

Colonnes importantes : - # : Numéro de séquence - Method : GET, POST, PUT, DELETE, etc. - URL : URL complète - Code : Code HTTP (200, 404, 500, etc.) - Reason : OK, Not Found, Internal Server Error - RTT : Round Trip Time (temps de réponse) - Size : Taille de la réponse - Flags : Indicateurs (cookies, scripts, etc.)

Filtres disponibles :

Clic droit  Filter
- Show only in scope
- Show only with alerts
- Show only POST requests
- Etc.

Panneau Alerts

Affiche toutes les vulnérabilités détectées.

Niveaux de sévérité : - High : Critique, exploitation immédiate possible - Medium : Importante, nécessite attention - Low : Mineure, amélioration recommandée - Informational : Information, pas de risque direct

Informations par alerte : - Description - URL(s) affectée(s) - Paramètre vulnérable - Preuve (payload utilisé) - Solution recommandée - Références (CWE, OWASP, etc.)

Concepts clés

1. Context

Un contexte définit le périmètre de test.

Créer un contexte :

1. Clic droit sur un site  Include in Context  New Context
2. Nommer le contexte (ex: "MonAppWeb")
3. Définir les URLs incluses/exclues
4. Configurer l'authentification si nécessaire

Exemple de regex d’inclusion :

https://exemple\.com/app/.*

Exemple de regex d’exclusion :

https://exemple\.com/app/logout.*
https://exemple\.com/app/static/.*

2. Scope

Le scope limite les tests aux URLs pertinentes.

Ajouter au scope :

Clic droit sur URL  Include in Scope

Avantages : - Évite les tests hors périmètre - Optimise les performances - Respecte le périmètre autorisé

3. Sessions

Une session sauvegarde tout votre travail.

Sauvegarder une session :

File → Persist Session
Ou : Ctrl+S

Charger une session :

File → Open Session

Format : Fichier .session contenant : - Sites explorés - Historique des requêtes - Alertes détectées - Configuration

4. Breakpoints

Les breakpoints permettent d’intercepter et modifier les requêtes/réponses.

Activer les breakpoints :

1. Bouton "Break" dans la toolbar (icône pause)
2. Ou : Ctrl+B

Types de breakpoints : - Break on all requests - Break on all responses - Break on specific URL pattern - Break on specific HTTP method

Utilisation :

1. Activer le breakpoint
2. Naviguer dans l'application
3. Modifier la requête/réponse dans l'éditeur
4. Cliquer "Continue" ou "Drop"

Proxy et Interception

Configuration basique du proxy

Vérifier que le proxy fonctionne :

  1. Configurer votre navigateur pour utiliser localhost:8080
  2. Visiter http://example.com
  3. Observer le trafic dans ZAP (onglet History)

Test rapide :

# Via curl
curl -x http://localhost:8080 http://example.com

# Via wget
wget -e use_proxy=yes -e http_proxy=localhost:8080 http://example.com

Interception manuelle

Scénario : Modifier une requête de connexion

  1. Activer l’interception : Toolbar → Bouton "Break" (vert → rouge)

  2. Naviguer vers le formulaire de login : http://exemple.com/login.php

  3. Soumettre le formulaire : Username: test Password: password123

  4. La requête est interceptée dans ZAP : ```http POST /login.php HTTP/1.1 Host: exemple.com Content-Type: application/x-www-form-urlencoded Cookie: PHPSESSID=abc123

username=test&password=password123 ```

  1. Modifier la requête : ```http POST /login.php HTTP/1.1 Host: exemple.com Content-Type: application/x-www-form-urlencoded Cookie: PHPSESSID=abc123

username=admin&password=admin’ OR ‘1’=‘1 ```

  1. Envoyer la requête modifiée : Bouton "Continue" ou "Submit and continue to break"

Interception de réponses

Activer l’interception de réponses :

Break  Break on all responses

Exemple : Modifier une réponse JSON

Réponse originale :

{
  "user": "john",
  "role": "user",
  "admin": false
}

Réponse modifiée :

{
  "user": "john",
  "role": "admin",
  "admin": true
}

Filtres d’interception avancés

Intercepter uniquement certaines requêtes :

  1. Tools → Options → Breakpoints
  2. Add Custom HTTP Breakpoint
  3. Configurer : URL String Match: /api/ Method: POST Request/Response: Request

Exemples de filtres :

# Intercepter tous les POST vers /api/
URL: /api/.*
Method: POST

# Intercepter les réponses 302 (redirections)
Status Code: 302
Response: Checked

# Intercepter les requêtes avec un cookie spécifique
Header (name): Cookie
Header (value): admin=true

Resend/Replay

Renvoyer une requête modifiée :

  1. Sélectionner une requête dans History
  2. Clic droit → Open/Resend with Request Editor
  3. Modifier la requête
  4. Cliquer “Send”

Exemple : Test d’injection SQL manuelle

Requête originale :

GET /product.php?id=42 HTTP/1.1
Host: exemple.com

Requête modifiée :

GET /product.php?id=42' HTTP/1.1
Host: exemple.com

Observer la réponse pour détecter une erreur SQL :

Error: You have an error in your SQL syntax near ''42'' at line 1

Manual Request Editor

Envoyer une requête arbitraire :

Tools → Manual Request Editor
Ou : Ctrl+M

Exemple : Test d’API REST

POST /api/v1/users HTTP/1.1
Host: api.exemple.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

{
  "username": "newuser",
  "email": "test@exemple.com",
  "role": "admin"
}

HUD (Heads Up Display)

ZAP HUD est une interface moderne overlay dans le navigateur.

Activer le HUD :

1. Tools  Options  HUD
2. Cocher "Enable when using the ZAP Desktop"
3. Lancer le HUD : Quick Start  Manual Explore  Launch Browser

Fonctionnalités HUD : - Attack Modes : Safe, Protected, Standard, Attack - Scope : Ajouter rapidement au scope - Alerts : Voir les alertes en temps réel - Spider : Lancer le spider sur la page courante - Active Scan : Scan actif rapide - Break : Activer/désactiver l’interception

Modes d’attaque :

Safe       → Pas de requêtes potentiellement dangereuses
Protected  → Uniquement sur les URLs en scope
Standard   → Toutes les requêtes autorisées
Attack     → Mode agressif, toutes attaques activées

Scan Passif et Actif

Scan Passif

Le scan passif analyse le trafic sans envoyer de nouvelles requêtes.

Caractéristiques : - ✅ Sans risque - ✅ Pas d’impact sur l’application - ✅ Toujours activé par défaut - ❌ Détection limitée

Activer/Désactiver :

Toolbar → Enable/Disable Passive Scan (icône bouclier)

Types de vulnérabilités détectées :

  1. Informations sensibles exposées - Commentaires HTML avec infos - Messages d’erreur détaillés - Divulgation de versions

  2. Headers de sécurité manquants - X-Frame-Options - X-Content-Type-Options - Content-Security-Policy - Strict-Transport-Security

  3. Cookies non sécurisés - Absence de flag Secure - Absence de flag HttpOnly - Absence de flag SameSite

  4. Autres : - Mixed Content (HTTP dans HTTPS) - Scripts obsolètes - Autocomplete activé sur champs sensibles

Exemple d’alerte passive :

Alert: Cookie Without Secure Flag
Risk Level: Low
Confidence: Medium

Description:
A cookie has been set without the secure flag, which means that the cookie can be accessed via unencrypted connections.

URL: https://exemple.com/login
Parameter: sessionid
Evidence: Set-Cookie: sessionid=abc123; Path=/; HttpOnly

Solution:
Whenever a cookie contains sensitive information or is a session token, then it should always be passed using an encrypted channel. Ensure that the secure flag is set for cookies containing such sensitive information.

Reference:
https://owasp.org/www-community/controls/SecureCookieAttribute
CWE-614

Scan Actif

Le scan actif envoie des payloads malveillants pour détecter les vulnérabilités.

⚠️ ATTENTION : - Peut modifier des données - Peut causer des DoS - Peut déclencher des alertes WAF/IDS - Nécessite une autorisation écrite

Lancer un scan actif :

Méthode 1 : Via Quick Start

1. Quick Start  Automated Scan
2. Entrer l'URL : http://exemple.com
3. Cliquer "Attack"

Méthode 2 : Via Sites Tree

1. Clic droit sur un site/dossier
2. Attack  Active Scan
3. Configurer les options
4. Cliquer "Start Scan"

Méthode 3 : Via Menu

Tools → Active Scan

Configuration du scan actif :

1. Clic droit sur site  Attack  Active Scan
2. Onglet "Policy"
3. Sélectionner ou créer une politique de scan

Politiques de scan prédéfinies :

Politique Description Temps Risque
Default Équilibré Moyen Moyen
Light Tests basiques Rapide Faible
Medium Tests standards Moyen Moyen
Heavy Tests approfondis Lent Élevé
SQLi Focus injection SQL Rapide Moyen
XSS Focus XSS Rapide Moyen

Personnaliser une politique :

1. Analyze  Scan Policy Manager
2. Cliquer "Add"
3. Nommer la politique : "Custom Policy"
4. Configurer les seuils :
   - Threshold : Off, Low, Medium, High
   - Strength : Low, Medium, High, Insane

Exemple de configuration :

Vulnerability: SQL Injection
Threshold: Medium (lance le test si probabilité moyenne)
Strength: High (teste beaucoup de variantes)

Vulnerability: Path Traversal
Threshold: Low (toujours lancer)
Strength: Medium

Vulnerability: CRLF Injection
Threshold: Off (désactivé)

Types de vulnérabilités détectées (scan actif) :

  1. Injection - SQL Injection - OS Command Injection - LDAP Injection - XPath Injection - SSTI (Server-Side Template Injection)

  2. XSS (Cross-Site Scripting) - Reflected XSS - Stored XSS - DOM-based XSS

  3. Autres - Path Traversal - Remote File Inclusion - CSRF (Cross-Site Request Forgery) - XXE (XML External Entity) - SSRF (Server-Side Request Forgery) - Insecure Deserialization

Exemple d’alerte active :

Alert: SQL Injection
Risk Level: High
Confidence: Medium

Description:
SQL injection may be possible.

URL: http://exemple.com/product.php?id=42
Parameter: id
Attack: 42' AND '1'='1' --
Evidence: JDBC error: You have an error in your SQL syntax

Solution:
Do not trust client side input, even if there is client side validation. Use parameterized queries (prepared statements) for all database queries.

Original Value: 42
Attack Value: 42' AND '1'='1' --

Reference:
https://owasp.org/www-community/attacks/SQL_Injection
CWE-89
WASC-19

Optimisation des scans

Limiter le nombre de threads :

Tools → Options → Active Scan
Host per Scan: 2 (défaut: 2)
Concurrent Scans: 2 (défaut: 2)

Ajuster les timeouts :

Tools → Options → Connection
Timeout (in seconds): 20

Exclure certaines technologies :

1. Analyze  Scan Policy Manager
2. Sélectionner votre politique
3. Technology  Exclude
   - Exclure les technologies non utilisées
   - Ex: MySQL si l'app utilise PostgreSQL

Limiter le scan à certains types :

Clic droit  Attack  Active Scan
Onglet "Policy"  Show Advanced Options
Cocher uniquement :
- Injection
- XSS
- Path Traversal

Spider et Découverte

Spider Traditionnel

Le spider explore l’application en suivant les liens HTML.

Lancer le spider :

Méthode 1 : Via Quick Start

Quick Start → Manual Explore
Entrer URL → Launch Browser
Toolbar → Spider (icône araignée)

Méthode 2 : Via Sites Tree

Clic droit sur site → Attack → Spider

Méthode 3 : Via Menu

Tools → Spider

Configuration du spider :

Tools → Options → Spider

Paramètres importants :

Paramètre Description Valeur recommandée
Maximum Depth Profondeur max 5-10
Maximum Children Liens max par page 0 (illimité)
Maximum Duration Durée max (minutes) 0 (illimité)
Thread Count Nombre de threads 2-5
Parse Comments Parser les commentaires HTML
Parse robots.txt Respecter robots.txt ❌ (en pentest)
Parse sitemap.xml Parser sitemap.xml
POST Form Soumettre les formulaires
Process Form Traiter les formulaires

Exemple de configuration avancée :

1. Tools  Options  Spider
2. Onglet "Advanced"
3. Configurer :
   - Maximum Depth to Crawl: 5
   - Number of Threads: 3
   - Parse Comments: checked
   - Parse Git metadata: checked
   - Parse SVN metadata: checked
   - Post Form: checked

Exclure des URLs du spider :

Tools  Options  Spider
Onglet "Advanced"  Excluded URLs

Ajouter regex :
.*logout.*
.*delete.*
.*admin/remove/.*

AJAX Spider

Le spider AJAX utilise un navigateur réel pour explorer les applications JavaScript/AJAX.

Quand utiliser l’AJAX Spider : - Applications Single Page (SPA) - Sites utilisant massivement JavaScript - AJAX pour charger du contenu - React, Angular, Vue.js applications

Lancer l’AJAX Spider :

Clic droit sur site → Attack → AJAX Spider

Configuration AJAX Spider :

Tools → Options → AJAX Spider

Paramètres importants :

Paramètre Description Valeur
Browser Navigateur utilisé Firefox Headless
Max Duration Durée max (minutes) 60
Max Crawl Depth Profondeur max 10
Number of Browsers Instances parallèles 1
Max Crawl States États max explorés 0 (illimité)
Click Elements Cliquer sur éléments
Random Inputs Valeurs aléatoires forms

Exemple complet : Spider une SPA

1. Ajouter le site au scope :
   Clic droit  Include in Scope

2. Lancer le spider traditionnel d'abord :
   Clic droit  Attack  Spider
   (pour découvrir les ressources statiques)

3. Lancer l'AJAX Spider :
   Clic droit  Attack  AJAX Spider

4. Observer les nouveaux liens dans Sites Tree

5. Analyser avec scan passif puis actif

Sortie exemple :

Sites découvertes après spider traditionnel :
└── http://spa.exemple.com
    ├── GET:/ (index.html)
    ├── GET:/css/app.css
    ├── GET:/js/app.js
    └── GET:/js/vendor.js

Sites découvertes après AJAX spider :
└── http://spa.exemple.com
    ├── GET:/ (index.html)
    ├── GET:/css/app.css
    ├── GET:/js/app.js
    ├── GET:/js/vendor.js
    ├── GET:/api/users
    ├── POST:/api/login
    ├── GET:/api/products
    ├── GET:/dashboard
    └── GET:/settings

Forced Browse / Directory Busting

Découvre les fichiers et répertoires cachés.

Installer l’add-on :

1. Manage Add-ons (icône puzzle)
2. Marketplace
3. Rechercher "Forced Browse"
4. Installer

Lancer Forced Browse :

Clic droit sur site → Attack → Forced Browse

Configuration :

1. Select list: Common directories (default)
2. Liste personnalisée disponibles :
   - Common directories
   - Common files
   - SVN files
   - Git files
   - Admin pages
   - Backup files

Liste personnalisée :

Créer un fichier custom-dirs.txt :

/admin
/administrator
/backup
/config
/.git
/.svn
/test
/dev
/api
/api/v1
/api/v2
/.env
/web.config
/config.php
/database.sql
/backup.zip

Utiliser la liste :

Forced Browse → File → Load → custom-dirs.txt

Exemple de résultats :

✅ Found: http://exemple.com/admin (200 OK)
✅ Found: http://exemple.com/.git/config (200 OK)
✅ Found: http://exemple.com/backup.zip (200 OK)
❌ Not Found: http://exemple.com/test (404)
❌ Not Found: http://exemple.com/dev (403 Forbidden)

Fuzzing et Tests Avancés

Fuzzer intégré

Le fuzzer permet de tester une application avec des données variées et malformées.

Lancer le fuzzer :

  1. Sélectionner une requête dans History
  2. Clic droit → Attack → Fuzz
  3. Sélectionner le paramètre à fuzzer
  4. Configurer les payloads

Exemple pratique : Fuzzer un paramètre

Requête de base :

GET /search.php?q=test HTTP/1.1
Host: exemple.com

Étapes :

  1. Sélectionner “test” dans la requête
  2. Clic droit → Fuzz
  3. Bouton “Add”
  4. Choisir le type de payload

Types de payloads disponibles :

Type Description Exemple
File Depuis un fichier wordlist.txt
File Fuzzers Listes intégrées XSS, SQLi, LFI
Strings Liste personnalisée Manual input
Regex Génération par regex [a-z]{5}
Numberzz Séquence numérique 1-1000
Scripts Script personnalisé JavaScript/Python

Exemple 1 : Fuzzing XSS

1. Sélectionner le paramètre à tester
2. Add  File Fuzzers  XSS
3. Payloads XSS chargés (100+ variantes)
4. Start Fuzzer

Payloads XSS utilisés :

<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
<svg/onload=alert('XSS')>
<iframe src=javascript:alert('XSS')>
'><script>alert(String.fromCharCode(88,83,83))</script>
"><script>alert(String.fromCharCode(88,83,83))</script>

Résultats :

Payload #42: <script>alert('XSS')</script>
Response Code: 200
Response Size: 2456 bytes
Match: <script>alert('XSS')</script> (reflected)

Exemple 2 : Fuzzing SQL Injection

1. Sélectionner le paramètre ID
2. Add  File Fuzzers  SQL Injection
3. Options :
   - Encode: URL encode
   - Threads: 5
4. Start Fuzzer

Payloads SQLi utilisés :

' OR '1'='1
' OR '1'='1' --
' OR '1'='1' /*
admin' --
admin' #
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
1' AND 1=1--
1' AND 1=2--
1' ORDER BY 1--
1' ORDER BY 2--
1' ORDER BY 3--

Résultats :

Payload #15: ' OR '1'='1' --
Response Code: 200
Response Size: 15234 bytes (anomalie: 10x taille normale)
Match: "MySQL syntax error" in response

Exemple 3 : Fuzzing énumération d’ID

1. Requête: GET /user/profile?id=42
2. Sélectionner "42"
3. Add  Numberzz
4. Configuration:
   - From: 1
   - To: 1000
   - Step: 1
5. Start Fuzzer

Analyse des résultats :

ID 1-100   : 200 OK (taille ~2KB)
ID 101     : 403 Forbidden
ID 102-500 : 200 OK (taille ~2KB)
ID 501     : 200 OK (taille ~15KB) ← Anomalie!
ID 502-1000: 200 OK (taille ~2KB)

Conclusion: ID 501 contient plus de données (admin?)

Fuzzing avancé avec payloads personnalisés

Créer une liste de payloads :

Fichier custom-sqli.txt :

' OR '1'='1
' OR '1'='1' --
' OR '1'='1' /*
admin' --
admin' #
' UNION SELECT NULL,NULL,NULL--
' AND SLEEP(5)--
'; DROP TABLE users--
' OR 1=1 LIMIT 1--
' OR 'x'='x

Utiliser la liste :

1. Fuzzer  Add  File
2. Sélectionner custom-sqli.txt
3. Start Fuzzer

Fuzzing de multiples paramètres

Requête avec plusieurs paramètres :

POST /login.php HTTP/1.1
Host: exemple.com
Content-Type: application/x-www-form-urlencoded

username=admin&password=test123

Fuzzer username ET password simultanément :

  1. Sélectionner “admin” → Add → Strings admin administrator root user test

  2. Sélectionner “test123” → Add → File /usr/share/wordlists/rockyou.txt

  3. Start Fuzzer

Résultats :

Total combinations: 5 usernames × 14,344,392 passwords = 71,721,960 requêtes

Request #42:
username=admin&password=admin123
Response: 302 Redirect to /dashboard

✅ Credentials trouvées: admin:admin123

Fuzzer avec encodage

Encodages disponibles : - URL Encoding - Base64 - HTML Entity - Unicode - Hex

Exemple : Bypass WAF avec encodage

1. Payload original: <script>alert('XSS')</script>
2. Add  File Fuzzers  XSS
3. Options  Processors  Add  Encode  URL
4. Options  Processors  Add  Encode  HTML Entity

Résultat:
%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%27%58%53%53%27%29%3C%2F%73%63%72%69%70%74%3E

Analyse des résultats de fuzzing

Trier par code de réponse :

Colonne "Code" → Cliquer pour trier

Trier par taille de réponse :

Colonne "Size Resp. Body" → Cliquer pour trier
Identifier les anomalies (tailles différentes)

Rechercher dans les réponses :

Fuzzer → Onglet "Filter"
Response Header: Location
Response Body: error, success, admin, etc.

Exporter les résultats :

Fuzzer → Right click → Export Results
Formats: CSV, HTML, XML

Automatisation et Scripting

Scripts ZAP

ZAP supporte plusieurs types de scripts pour l’automatisation.

Types de scripts :

Type Description Utilisation
Stand Alone Script autonome Automatisation complète
Targeted Sur une requête spécifique Tests personnalisés
Authentication Gestion authentification Login automatique
Session Management Gestion de session Maintien de session
Passive Rules Scan passif custom Détection personnalisée
Active Rules Scan actif custom Attaques personnalisées
Proxy Modification à la volée Interception automatique
HTTP Sender Avant envoi requête Ajout headers, etc.

Langages supportés : - JavaScript (ECMAScript) - Python (Jython) - Groovy - Ruby (JRuby) - Zest (langage graphique)

Scripts Stand Alone

Créer un script Stand Alone :

1. Scripts (onglet en bas)
2. Clic droit  New Script
3. Type: Stand Alone
4. Engine: ECMAScript
5. Name: my_custom_script

Exemple 1 : Scanner une liste d’URLs

// Script: bulk_scanner.js
// Type: Stand Alone

// Importer les classes nécessaires
var Thread = Java.type("java.lang.Thread");
var ExtensionActiveScan = Java.type("org.zaproxy.zap.extension.ascan.ExtensionActiveScan");

// Liste des URLs à scanner
var urls = [
    "http://exemple1.com",
    "http://exemple2.com",
    "http://exemple3.com"
];

// Obtenir l'extension de scan actif
var activeScan = control.getExtensionLoader().getExtension(ExtensionActiveScan.class);

// Scanner chaque URL
for (var i = 0; i < urls.length; i++) {
    var url = urls[i];
    print("Scanning: " + url);

    // Accéder à l'URL via le spider d'abord
    var extSpider = org.parosproxy.paros.control.Control.getSingleton()
        .getExtensionLoader()
        .getExtension(org.zaproxy.zap.extension.spider.ExtensionSpider.class);

    extSpider.startScan(url, null, 0, null);

    // Attendre que le spider se termine
    while (extSpider.isScanning()) {
        Thread.sleep(1000);
    }

    print("Spider completed for: " + url);

    // Lancer le scan actif
    activeScan.startScan(url, null, null, null);

    print("Active scan started for: " + url);
}

print("All scans completed!");

Exécuter le script :

Scripts → Clic droit sur le script → Run Script

Exemple 2 : Exporter toutes les alertes

// Script: export_alerts.js
// Type: Stand Alone

var FileWriter = Java.type("java.io.FileWriter");
var SimpleDateFormat = Java.type("java.text.SimpleDateFormat");
var Date = Java.type("java.util.Date");

// Obtenir toutes les alertes
var alerts = org.parosproxy.paros.model.Model.getSingleton()
    .getDb().getTableAlert().getAllAlerts();

// Créer le fichier de sortie
var dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
var filename = "/tmp/zap_alerts_" + dateFormat.format(new Date()) + ".csv";
var writer = new FileWriter(filename);

// En-tête CSV
writer.write("Alert,Risk,Confidence,URL,Parameter,Evidence\n");

// Écrire chaque alerte
for (var i = 0; i < alerts.size(); i++) {
    var alert = alerts.get(i);
    var line =
        "\"" + alert.getAlert() + "\"," +
        "\"" + alert.getRisk() + "\"," +
        "\"" + alert.getConfidence() + "\"," +
        "\"" + alert.getUri() + "\"," +
        "\"" + alert.getParam() + "\"," +
        "\"" + alert.getEvidence() + "\"\n";
    writer.write(line);
}

writer.close();
print("Alerts exported to: " + filename);

Scripts Targeted

Scripts exécutés sur une requête sélectionnée.

Créer un script Targeted :

// Script: encode_param.js
// Type: Targeted

function invokeWith(msg) {
    // Obtenir le corps de la requête
    var body = msg.getRequestBody().toString();

    // Encoder le paramètre en base64
    var Base64 = Java.type("java.util.Base64");
    var encoded = Base64.getEncoder().encodeToString(body.getBytes());

    print("Original: " + body);
    print("Encoded: " + encoded);

    // Modifier la requête
    msg.getRequestBody().setBody(encoded);

    // Renvoyer la requête modifiée
    org.parosproxy.paros.network.HttpSender
        .sendAndReceive(msg, msg.getRequestHeader().isSecure());

    // Afficher la réponse
    print("Response Code: " + msg.getResponseHeader().getStatusCode());
    print("Response Body: " + msg.getResponseBody().toString());
}

Utiliser le script :

1. Sélectionner une requête dans History
2. Clic droit  Invoke with script  encode_param.js

Scripts Authentication

Automatise le processus de connexion.

Exemple : Script de login personnalisé

// Script: custom_auth.js
// Type: Authentication

function authenticate(helper, paramsValues, credentials) {
    var HttpRequestHeader = Java.type("org.parosproxy.paros.network.HttpRequestHeader");
    var HttpMessage = Java.type("org.parosproxy.paros.network.HttpMessage");
    var URI = Java.type("org.apache.commons.httpclient.URI");

    // URL de login
    var loginUrl = "http://exemple.com/login.php";

    // Créer la requête de login
    var requestUri = new URI(loginUrl, false);
    var requestMethod = HttpRequestHeader.POST;

    // Corps de la requête
    var username = credentials.getParam("username");
    var password = credentials.getParam("password");
    var postData = "username=" + username + "&password=" + password;

    // Construire la requête
    var msg = helper.prepareMessage();
    msg.getRequestHeader().setMethod(requestMethod);
    msg.getRequestHeader().setURI(requestUri);
    msg.setRequestBody(postData);
    msg.getRequestHeader().setContentLength(msg.getRequestBody().length());

    // Envoyer la requête
    helper.sendAndReceive(msg);

    // Vérifier le succès (présence de "dashboard" dans la réponse)
    var responseBody = msg.getResponseBody().toString();
    if (responseBody.indexOf("dashboard") !== -1) {
        return msg;
    }

    return null;
}

function getRequiredParamsNames() {
    return ["username", "password"];
}

function getOptionalParamsNames() {
    return [];
}

function getCredentialsParamsNames() {
    return ["username", "password"];
}

Scripts Passive Rules

Détection personnalisée de vulnérabilités sans scan actif.

Exemple : Détecter des secrets dans les réponses

// Script: detect_secrets.js
// Type: Passive Rules

var extensionAlert = control.getExtensionLoader()
    .getExtension(org.zaproxy.zap.extension.alert.ExtensionAlert.class);

function scan(ps, msg, src) {
    var body = msg.getResponseBody().toString();
    var url = msg.getRequestHeader().getURI().toString();

    // Patterns de secrets
    var patterns = [
        {
            name: "AWS Access Key",
            regex: /AKIA[0-9A-Z]{16}/g,
            risk: 3 // High
        },
        {
            name: "Private Key",
            regex: /-----BEGIN (RSA |DSA |EC )?PRIVATE KEY-----/g,
            risk: 3
        },
        {
            name: "API Key",
            regex: /api[_-]?key["\s:=]+[a-zA-Z0-9]{32,}/gi,
            risk: 2 // Medium
        },
        {
            name: "Password in Code",
            regex: /password["\s:=]+["'][^"']{8,}["']/gi,
            risk: 2
        }
    ];

    // Chercher chaque pattern
    patterns.forEach(function(pattern) {
        var matches = body.match(pattern.regex);
        if (matches) {
            matches.forEach(function(match) {
                // Créer une alerte
                var alertRisk = pattern.risk;
                var alertConfidence = 2; // Medium
                var alertTitle = pattern.name + " Detected";
                var alertDesc = "A " + pattern.name + " was found in the response.";
                var alertSolution = "Remove sensitive information from responses.";
                var alertReference = "https://owasp.org/www-project-top-ten/";

                ps.raiseAlert(
                    alertRisk,
                    alertConfidence,
                    alertTitle,
                    alertDesc,
                    url,
                    "",
                    "",
                    match,
                    alertSolution,
                    "",
                    0, // CWE ID
                    0, // WASC ID
                    msg
                );
            });
        }
    });
}

Scripts Active Rules

Tests personnalisés avec payloads malveillants.

Exemple : Test SSTI (Server-Side Template Injection)

// Script: ssti_scanner.js
// Type: Active Rules

function scan(as, msg, param, value) {
    // Payloads SSTI
    var payloads = [
        "{{7*7}}",
        "${7*7}",
        "<%= 7*7 %>",
        "${{7*7}}",
        "#{7*7}",
        "*{7*7}"
    ];

    var expectedResult = "49";

    payloads.forEach(function(payload) {
        // Créer une nouvelle requête avec le payload
        var testMsg = msg.cloneRequest();
        as.setParam(testMsg, param, payload);

        // Envoyer la requête
        as.sendAndReceive(testMsg, false, false);

        // Analyser la réponse
        var response = testMsg.getResponseBody().toString();

        if (response.indexOf(expectedResult) !== -1) {
            // Vulnérabilité détectée!
            as.raiseAlert(
                3, // High risk
                3, // High confidence
                "Server-Side Template Injection",
                "SSTI vulnerability detected. The application evaluates template expressions.",
                testMsg.getRequestHeader().getURI().toString(),
                param,
                payload,
                "Response contains: " + expectedResult,
                "Use a safe template engine and escape user input.",
                "Payload: " + payload + "\nExpected: " + expectedResult,
                0, // CWE-94
                0, // WASC
                testMsg
            );

            return; // Stop after first detection
        }
    });
}

API ZAP pour l’automatisation

ZAP expose une API REST complète.

Activer l’API :

Tools → Options → API
- Enable API: checked
- API Key: (générer une clé ou laisser vide pour mode insecure)
- Addresses permitted to use the API: localhost

Exemples d’utilisation de l’API :

1. Accéder au spider via API

# Lancer le spider
curl "http://localhost:8080/JSON/spider/action/scan/?url=http://exemple.com&apikey=YOUR_API_KEY"

# Vérifier le statut
curl "http://localhost:8080/JSON/spider/view/status/?apikey=YOUR_API_KEY"

# Résultats
{"status":"100"}  # 100% = terminé

2. Lancer un scan actif

# Lancer le scan
curl "http://localhost:8080/JSON/ascan/action/scan/?url=http://exemple.com&apikey=YOUR_API_KEY"

# Récupérer le scan ID
# {"scan":"0"}

# Vérifier le statut
curl "http://localhost:8080/JSON/ascan/view/status/?scanId=0&apikey=YOUR_API_KEY"

# Résultats
{"status":"45"}  # 45% complété

3. Récupérer les alertes

# Toutes les alertes
curl "http://localhost:8080/JSON/alert/view/alerts/?apikey=YOUR_API_KEY"

# Alertes pour une URL spécifique
curl "http://localhost:8080/JSON/alert/view/alerts/?url=http://exemple.com&apikey=YOUR_API_KEY"

# Alertes high risk uniquement
curl "http://localhost:8080/JSON/alert/view/alertsByRisk/?url=http://exemple.com&risk=High&apikey=YOUR_API_KEY"

4. Script Python avec l’API

#!/usr/bin/env python3
import requests
import time
import json

ZAP_URL = "http://localhost:8080"
API_KEY = "your-api-key-here"
TARGET_URL = "http://exemple.com"

def zap_spider(url):
    """Lance le spider sur une URL"""
    endpoint = f"{ZAP_URL}/JSON/spider/action/scan/"
    params = {"url": url, "apikey": API_KEY}
    response = requests.get(endpoint, params=params)
    return response.json()

def zap_spider_status():
    """Vérifie le statut du spider"""
    endpoint = f"{ZAP_URL}/JSON/spider/view/status/"
    params = {"apikey": API_KEY}
    response = requests.get(endpoint, params=params)
    return int(response.json()["status"])

def zap_active_scan(url):
    """Lance un scan actif"""
    endpoint = f"{ZAP_URL}/JSON/ascan/action/scan/"
    params = {"url": url, "apikey": API_KEY}
    response = requests.get(endpoint, params=params)
    return response.json()["scan"]

def zap_scan_status(scan_id):
    """Vérifie le statut du scan actif"""
    endpoint = f"{ZAP_URL}/JSON/ascan/view/status/"
    params = {"scanId": scan_id, "apikey": API_KEY}
    response = requests.get(endpoint, params=params)
    return int(response.json()["status"])

def zap_get_alerts():
    """Récupère toutes les alertes"""
    endpoint = f"{ZAP_URL}/JSON/alert/view/alerts/"
    params = {"apikey": API_KEY}
    response = requests.get(endpoint, params=params)
    return response.json()["alerts"]

def main():
    print(f"[*] Starting scan of {TARGET_URL}")

    # 1. Spider
    print("[*] Starting spider...")
    zap_spider(TARGET_URL)

    while zap_spider_status() < 100:
        print(f"[*] Spider progress: {zap_spider_status()}%")
        time.sleep(2)

    print("[+] Spider completed")

    # 2. Active Scan
    print("[*] Starting active scan...")
    scan_id = zap_active_scan(TARGET_URL)

    while zap_scan_status(scan_id) < 100:
        print(f"[*] Scan progress: {zap_scan_status(scan_id)}%")
        time.sleep(5)

    print("[+] Active scan completed")

    # 3. Récupérer les alertes
    print("[*] Retrieving alerts...")
    alerts = zap_get_alerts()

    # Compter par sévérité
    high = sum(1 for a in alerts if a["risk"] == "High")
    medium = sum(1 for a in alerts if a["risk"] == "Medium")
    low = sum(1 for a in alerts if a["risk"] == "Low")
    info = sum(1 for a in alerts if a["risk"] == "Informational")

    print(f"\n[+] Results:")
    print(f"    High: {high}")
    print(f"    Medium: {medium}")
    print(f"    Low: {low}")
    print(f"    Informational: {info}")

    # Sauvegarder dans un fichier
    with open("zap_alerts.json", "w") as f:
        json.dump(alerts, f, indent=2)

    print(f"\n[+] Full report saved to zap_alerts.json")

if __name__ == "__main__":
    main()

Exécuter le script :

chmod +x zap_automation.py
./zap_automation.py

API Testing

Configuration pour tester des APIs

ZAP est excellent pour tester les APIs REST, SOAP, et GraphQL.

API REST

Méthode 1 : Import OpenAPI/Swagger

1. Import  Import an OpenAPI definition
2. Choisir le fichier (swagger.json, openapi.yaml)
3. Ou entrer l'URL (http://api.exemple.com/swagger.json)
4. Cliquer "Import"

Les endpoints sont automatiquement ajoutés au Sites Tree.

Méthode 2 : Utilisation manuelle

Tools → Manual Request Editor

Exemple de requête API :

POST /api/v1/users HTTP/1.1
Host: api.exemple.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

{
  "username": "john",
  "email": "john@exemple.com",
  "role": "user"
}

Tester différents verbes HTTP :

# GET - Récupérer des données
GET /api/v1/users/42 HTTP/1.1
Host: api.exemple.com
Authorization: Bearer token123

# POST - Créer une ressource
POST /api/v1/users HTTP/1.1
Host: api.exemple.com
Content-Type: application/json
Authorization: Bearer token123

{"username": "alice", "email": "alice@test.com"}

# PUT - Mettre à jour complètement
PUT /api/v1/users/42 HTTP/1.1
Host: api.exemple.com
Content-Type: application/json
Authorization: Bearer token123

{"username": "alice_updated", "email": "alice@updated.com"}

# PATCH - Mettre à jour partiellement
PATCH /api/v1/users/42 HTTP/1.1
Host: api.exemple.com
Content-Type: application/json
Authorization: Bearer token123

{"email": "newemail@test.com"}

# DELETE - Supprimer une ressource
DELETE /api/v1/users/42 HTTP/1.1
Host: api.exemple.com
Authorization: Bearer token123

Fuzzing d’API REST :

Test 1 : Énumération d’IDs

1. Requête: GET /api/v1/users/1
2. Clic droit  Attack  Fuzz
3. Sélectionner "1"
4. Add  Numberzz (1 to 1000)
5. Start Fuzzer

Résultats attendus :

ID 1-50:   200 OK (utilisateurs existants)
ID 51-99:  404 Not Found
ID 100:    200 OK (admin? taille différente)
ID 101+:   404 Not Found

Test 2 : Manipulation de rôles

POST /api/v1/users HTTP/1.1
Content-Type: application/json

{"username": "test", "email": "test@test.com", "role": "admin"}

Fuzzer le champ “role” :

Payloads:
- user
- admin
- superadmin
- root
- moderator
- guest

Test 3 : Injection dans JSON

1. Requête avec JSON body
2. Fuzzer un champ
3. Payloads: File Fuzzers  SQL Injection

Exemple :

{
  "username": "' OR '1'='1",
  "email": "test@test.com"
}

API GraphQL

Installer l’add-on GraphQL :

1. Manage Add-ons  Marketplace
2. Rechercher "GraphQL"
3. Installer

Importer un schéma GraphQL :

1. Import  Import a GraphQL Schema
2. URL endpoint: http://api.exemple.com/graphql
3. Ou upload schema.graphql
4. Cliquer "Import"

Exemple de requête GraphQL :

POST /graphql HTTP/1.1
Host: api.exemple.com
Content-Type: application/json

{
  "query": "{ users { id username email } }"
}

Tester les mutations :

POST /graphql HTTP/1.1
Host: api.exemple.com
Content-Type: application/json

{
  "query": "mutation { createUser(username: \"test\", email: \"test@test.com\", role: \"admin\") { id username role } }"
}

Fuzzing GraphQL :

1. Sélectionner la valeur "test" dans username
2. Fuzz avec payloads XSS/SQLi
3. Observer les réponses

Test d’introspection GraphQL :

POST /graphql HTTP/1.1
Content-Type: application/json

{
  "query": "{ __schema { types { name fields { name } } } }"
}

Si l’introspection est activée, vous obtenez tout le schéma de l’API.

API SOAP

Importer un WSDL :

1. Import  Import a WSDL file
2. URL: http://exemple.com/service?wsdl
3. Cliquer "Import"

Exemple de requête SOAP :

POST /service HTTP/1.1
Host: exemple.com
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://exemple.com/GetUser"

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <GetUser xmlns="http://exemple.com/">
      <UserId>42</UserId>
    </GetUser>
  </soap:Body>
</soap:Envelope>

Fuzzing SOAP :

1. Sélectionner <UserId>42</UserId>
2. Fuzzer la valeur "42"
3. Tester avec:
   - Nombres: 1-1000
   - Strings: admin, root, etc.
   - Injections: SQLi, XPath, XXE

Test XXE (XML External Entity) :

<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <GetUser xmlns="http://exemple.com/">
      <UserId>&xxe;</UserId>
    </GetUser>
  </soap:Body>
</soap:Envelope>

Authentication et Session Management

Configurer l’authentification

ZAP supporte plusieurs méthodes d’authentification.

Types d’authentification supportés : - Form-based (formulaire HTML) - HTTP/NTLM Authentication - Script-based (personnalisé) - JSON-based (API) - Manual (authentification manuelle)

Form-Based Authentication

Scénario : Site avec login classique

Étape 1 : Créer un contexte

1. Clic droit sur site  Include in Context  New Context
2. Name: "MyWebApp"
3. Include in Context: http://exemple.com/.*
4. Exclude from Context: http://exemple.com/logout

Étape 2 : Configurer l’authentification

1. Clic droit sur contexte  Flag as Context  Authentication
2. Method: Form-Based Authentication
3. Login URL: http://exemple.com/login.php
4. Login Request:

Capturer la requête de login :

1. Se connecter manuellement via le proxy ZAP
2. Trouver la requête POST dans History
3. Clic droit  Flag as Context  Authentication Login Request

Exemple de requête de login :

POST /login.php HTTP/1.1
Host: exemple.com
Content-Type: application/x-www-form-urlencoded

username={%username%}&password={%password%}&submit=Login

Les paramètres {%username%} et {%password%} seront remplacés automatiquement.

Étape 3 : Définir l’indicateur de session

ZAP doit savoir si vous êtes connecté ou non.

Authentication  Logged In Indicator (regex):
<a href="/logout">Logout</a>

Ou Logged Out Indicator (regex):
<a href="/login">Login</a>

Étape 4 : Ajouter des utilisateurs

1. Users (dans le Context)  Add
2. Username: admin
3. Password: admin123
4. Enabled: checked

Étape 5 : Tester l’authentification

1. Clic droit sur le user  Test Authentication
2. Vérifier dans la sortie:
   - Login request sent
   - Logged in indicator found: TRUE

Exemple de sortie :

[INFO] Authentication Test Started
[INFO] Sending login request to http://exemple.com/login.php
[INFO] Login request completed (HTTP 302)
[INFO] Following redirect to /dashboard
[INFO] Checking logged in indicator: <a href="/logout">Logout</a>
[INFO] Logged in indicator FOUND
[SUCCESS] Authentication successful for user: admin

Script-Based Authentication

Pour les authentifications complexes (OAuth, JWT, 2FA, etc.)

Exemple : Authentification JWT

// Script: jwt_auth.js
// Type: Authentication

function authenticate(helper, paramsValues, credentials) {
    var HttpRequestHeader = Java.type("org.parosproxy.paros.network.HttpRequestHeader");
    var HttpMessage = Java.type("org.parosproxy.paros.network.HttpMessage");
    var URI = Java.type("org.apache.commons.httpclient.URI");

    // Endpoint de login
    var loginUrl = "http://api.exemple.com/auth/login";

    // Construire la requête JSON
    var username = credentials.getParam("username");
    var password = credentials.getParam("password");

    var jsonBody = JSON.stringify({
        "username": username,
        "password": password
    });

    // Créer la requête
    var msg = helper.prepareMessage();
    var requestUri = new URI(loginUrl, false);
    msg.getRequestHeader().setMethod(HttpRequestHeader.POST);
    msg.getRequestHeader().setURI(requestUri);
    msg.getRequestHeader().setHeader("Content-Type", "application/json");
    msg.setRequestBody(jsonBody);
    msg.getRequestHeader().setContentLength(msg.getRequestBody().length());

    // Envoyer la requête
    helper.sendAndReceive(msg);

    // Extraire le token JWT de la réponse
    var responseBody = msg.getResponseBody().toString();
    var response = JSON.parse(responseBody);

    if (response.token) {
        // Stocker le token pour les requêtes suivantes
        var token = response.token;
        msg.getRequestHeader().setHeader("Authorization", "Bearer " + token);
        return msg;
    }

    return null;
}

function getRequiredParamsNames() {
    return ["username", "password"];
}

function getOptionalParamsNames() {
    return [];
}

function getCredentialsParamsNames() {
    return ["username", "password"];
}

Configurer :

1. Context  Authentication
2. Method: Script-Based Authentication
3. Load Script: jwt_auth.js
4. Logged In Indicator: "token": "(present dans la réponse)

Session Management

Types de session management : - Cookie-Based (défaut) - HTTP Authentication - Script-Based

Cookie-Based Session (défaut) :

Context → Session Management
Method: Cookie-Based Session Management

ZAP gère automatiquement les cookies (PHPSESSID, JSESSIONID, etc.)

Script-Based Session Management :

Pour ajouter automatiquement des headers à chaque requête.

// Script: add_jwt_header.js
// Type: HTTP Sender

function sendingRequest(msg, initiator, helper) {
    // Récupérer le token JWT (stocké globalement ou via script d'auth)
    var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";

    // Ajouter le header Authorization
    msg.getRequestHeader().setHeader("Authorization", "Bearer " + token);
}

function responseReceived(msg, initiator, helper) {
    // Optionnel: Rafraîchir le token si expiré
    var responseBody = msg.getResponseBody().toString();
    if (responseBody.indexOf("token_expired") !== -1) {
        // Ré-authentifier et obtenir un nouveau token
        // (appeler le script d'auth)
    }
}

Activer le script :

Scripts → HTTP Sender → Enable add_jwt_header.js

Forced User Mode

Force ZAP à toujours utiliser un utilisateur spécifique.

Activer :

1. Context  Users
2. Sélectionner un user
3. Cliquer "Set as Forced User"
4. Toolbar  Force User Mode ON (icône utilisateur)

Utilisation : - Tous les scans utiliseront cet utilisateur - Utile pour tester les fonctionnalités authentifiées - Permet de tester différents niveaux de privilèges

Exemple de test avec 2 utilisateurs :

User 1: admin / admin123 (role: admin)
User 2: john / john123 (role: user)

1. Set "john" as Forced User
2. Active Scan sur /admin/
3. Observer les résultats (403 Forbidden?)

4. Set "admin" as Forced User
5. Active Scan sur /admin/
6. Observer les résultats (200 OK, vulnérabilités détectées)

Anti-CSRF Token Handling

ZAP gère automatiquement les tokens CSRF.

Configuration :

Tools → Options → Anti CSRF Tokens
Add token name: csrf_token, _csrf, authenticity_token

ZAP extraira automatiquement ces tokens et les réutilisera.

Exemple :

Requête 1 : Obtenir le formulaire

GET /transfer HTTP/1.1

Réponse :

<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="abc123xyz789">
  <input type="text" name="amount">
  <input type="submit" value="Transfer">
</form>

Requête 2 : Soumettre le formulaire

POST /transfer HTTP/1.1
Content-Type: application/x-www-form-urlencoded

csrf_token=abc123xyz789&amount=1000

ZAP extraira automatiquement csrf_token=abc123xyz789 et le réutilisera.


Reporting et Documentation

Générer un rapport

ZAP offre plusieurs formats de rapports.

Générer un rapport HTML :

Report → Generate HTML Report
1. Title: "Security Assessment - MyApp"
2. Template: Traditional HTML
3. Report file name: zap_report.html
4. Include: All Alerts
5. Generate Report

Générer un rapport XML :

Report → Generate XML Report

Formats disponibles : - HTML : Rapport détaillé avec styling - XML : Format structuré pour parsing - JSON : Pour intégration avec d’autres outils - Markdown : Pour documentation - PDF : Nécessite un add-on

Structure d’un rapport HTML

1. Summary
   - Total URLs analyzed
   - Alerts by risk level
   - Alerts by confidence

2. Alerts
   - High Risk
     - [Alert Name]
       - Description
       - URL(s)
       - Parameter
       - Attack
       - Evidence
       - Solution
       - Reference
       - CWE ID
       - WASC ID
   - Medium Risk
   - Low Risk
   - Informational

3. Appendix
   - Alert counts by type
   - Alert counts by site

Personnaliser les rapports

Installer le Report Generation add-on :

Manage Add-ons → Marketplace → "Report Generation"

Templates disponibles : - Traditional HTML - Modern HTML (avec graphiques) - Traditional HTML Plus - Risk and Confidence HTML - Traditional XML - Traditional MD (Markdown)

Créer un template personnalisé :

1. Aller dans ~/.ZAP/reports/
2. Copier un template existant
3. Modifier le template (Thymeleaf syntax)
4. Utiliser dans Report  Generate Report

Exporter les alertes en CSV

# Via API
curl "http://localhost:8080/OTHER/core/other/csvreport/?apikey=YOUR_KEY" -o report.csv

# Via script Python
import requests
import csv

ZAP_URL = "http://localhost:8080"
API_KEY = "your-api-key"

# Récupérer les alertes
alerts = requests.get(
    f"{ZAP_URL}/JSON/alert/view/alerts/",
    params={"apikey": API_KEY}
).json()["alerts"]

# Écrire en CSV
with open("zap_alerts.csv", "w", newline="") as csvfile:
    fieldnames = ["alert", "risk", "confidence", "url", "param", "evidence", "solution"]
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

    writer.writeheader()
    for alert in alerts:
        writer.writerow({
            "alert": alert["alert"],
            "risk": alert["risk"],
            "confidence": alert["confidence"],
            "url": alert["url"],
            "param": alert["param"],
            "evidence": alert["evidence"],
            "solution": alert["solution"]
        })

print("Report saved to zap_alerts.csv")

Comparer des scans

Installer l’add-on “Diff” :

Manage Add-ons → Marketplace → "Diff"

Comparer deux sessions :

1. Charger la première session (scan baseline)
2. Tools  Compare with another session
3. Sélectionner la deuxième session (nouveau scan)
4. Le rapport montre :
   - Nouvelles alertes
   - Alertes résolues
   - Alertes inchangées

Exemple de rapport de comparaison :

Comparison Report: Baseline vs New Scan

Summary:
- Total alerts (baseline): 45
- Total alerts (new): 38
- New alerts: 5
- Resolved alerts: 12
- Unchanged alerts: 33

New Alerts (5):
1. [High] SQL Injection in /api/products?id=
2. [Medium] XSS in /search?q=
3. [Low] Cookie without SameSite
4. [Info] Deprecated TLS version
5. [Info] Missing X-Frame-Options

Resolved Alerts (12):
1. [High] Path Traversal in /download (FIXED)
2. [Medium] CSRF in /transfer (FIXED)
...

ZAP en Mode Headless/CLI

Lancement en mode daemon

ZAP peut fonctionner sans interface graphique.

# Lancer ZAP en mode daemon
zap.sh -daemon -host 0.0.0.0 -port 8080 -config api.disablekey=true

# Avec API key
zap.sh -daemon -host 0.0.0.0 -port 8080 -config api.key=your-secret-key

# Écouter uniquement sur localhost
zap.sh -daemon -port 8080

Vérifier que ZAP fonctionne :

curl http://localhost:8080/JSON/core/view/version/
# {"version":"2.14.0"}

Automation Framework

ZAP 2.12+ introduit l’Automation Framework (meilleure méthode pour CI/CD).

Créer un plan d’automatisation (YAML) :

Fichier zap-automation.yaml :

---
env:
  contexts:
    - name: "MyApp"
      urls:
        - "http://exemple.com"
      includePaths:
        - "http://exemple.com/.*"
      excludePaths:
        - "http://exemple.com/logout.*"
  parameters:
    failOnError: true
    failOnWarning: false
    progressToStdout: true

jobs:
  - type: spider
    parameters:
      maxDuration: 5
      maxDepth: 10
      numberOfThreads: 5

  - type: spiderAjax
    parameters:
      maxDuration: 5
      maxCrawlDepth: 10
      numberOfBrowsers: 2

  - type: passiveScan-wait
    parameters:
      maxDuration: 10

  - type: activeScan
    parameters:
      policy: "Default Policy"
      maxRuleDurationInMins: 1
      maxScanDurationInMins: 10

  - type: report
    parameters:
      template: "traditional-html"
      reportDir: "/tmp/zap-reports"
      reportFile: "zap-report"
      reportTitle: "Security Assessment Report"
      reportDescription: "Automated security scan"

Exécuter le plan :

# Avec ZAP installé
zap.sh -cmd -autorun /path/to/zap-automation.yaml

# Avec Docker
docker run --rm -v $(pwd):/zap/wrk:rw zaproxy/zap-stable zap.sh \
  -cmd -autorun /zap/wrk/zap-automation.yaml

Plan d’automatisation avec authentification :

---
env:
  contexts:
    - name: "AuthApp"
      urls:
        - "http://exemple.com"
      authentication:
        method: "form"
        parameters:
          loginPageUrl: "http://exemple.com/login"
          loginRequestUrl: "http://exemple.com/auth"
          loginRequestBody: "username={%username%}&password={%password%}"
        verification:
          method: "response"
          loggedInRegex: "\\QLogout\\E"
          loggedOutRegex: "\\QLogin\\E"
      users:
        - name: "testuser"
          credentials:
            username: "admin"
            password: "admin123"
      sessionManagement:
        method: "cookie"

jobs:
  - type: spider
    parameters:
      user: "testuser"
      maxDuration: 5

  - type: activeScan
    parameters:
      user: "testuser"
      policy: "Default Policy"

  - type: report
    parameters:
      template: "traditional-html"
      reportFile: "authenticated-scan-report"

Baseline Scan (scan rapide)

Scan passif uniquement, idéal pour CI/CD.

# Baseline scan
zap-baseline.py -t http://exemple.com

# Avec rapport
zap-baseline.py -t http://exemple.com -r baseline-report.html

# Ignorer certains types d'alertes
zap-baseline.py -t http://exemple.com -c baseline-config.conf

Fichier de configuration baseline-config.conf :

# Ignorer les alertes de faible priorité
10015 IGNORE (Cookie Without Secure Flag)
10054 IGNORE (Cookie Without SameSite Attribute)

# Ignorer pour des URLs spécifiques
10021 IGNORE (X-Content-Type-Options) http://exemple.com/static/.*

# Fail sur High risk uniquement
FAIL-HIGH

Sortie :

PASS: Cookie No HttpOnly Flag [10010]
PASS: Cross-Domain Misconfiguration [10098]
WARN-NEW: Cookie Without Secure Flag [10011] x 5
    http://exemple.com/ (200 OK)
    http://exemple.com/login (200 OK)
FAIL-NEW: SQL Injection [40018] x 3
    http://exemple.com/product?id=1 (200 OK)

FAIL-NEW: 1     FAIL-INPROG: 0  WARN-NEW: 1     WARN-INPROG: 0  INFO: 0 IGNORE: 2       PASS: 45

Full Scan (scan complet)

Spider + Active Scan automatique.

# Full scan
zap-full-scan.py -t http://exemple.com

# Avec rapport et configuration
zap-full-scan.py -t http://exemple.com \
  -r full-scan-report.html \
  -c full-scan-config.conf \
  -m 10  # Maximum 10 minutes

API Scan

Scan spécialisé pour les APIs.

# API scan avec OpenAPI/Swagger
zap-api-scan.py -t http://api.exemple.com/openapi.json \
  -f openapi \
  -r api-scan-report.html

# API scan avec GraphQL
zap-api-scan.py -t http://api.exemple.com/graphql \
  -f graphql \
  -r graphql-scan-report.html

Intégration CI/CD

Intégration avec Jenkins

Installer le plugin ZAP :

Jenkins → Manage Plugins → Available → "OWASP ZAP"

Jenkinsfile exemple :

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'npm install'
                sh 'npm run build'
            }
        }

        stage('Deploy to Test') {
            steps {
                sh './deploy-test.sh'
            }
        }

        stage('ZAP Security Scan') {
            steps {
                script {
                    // Démarrer ZAP en daemon
                    sh '''
                        docker run -d --name zap \
                          -p 8080:8080 \
                          -v $(pwd)/zap-reports:/zap/wrk:rw \
                          zaproxy/zap-stable \
                          zap.sh -daemon -host 0.0.0.0 -port 8080 \
                          -config api.disablekey=true
                    '''

                    // Attendre que ZAP démarre
                    sh 'sleep 30'

                    // Exécuter le scan
                    sh '''
                        docker exec zap zap-cli quick-scan \
                          --self-contained \
                          --start-options '-config api.disablekey=true' \
                          http://test.exemple.com
                    '''

                    // Générer le rapport
                    sh '''
                        docker exec zap zap-cli report \
                          -o /zap/wrk/zap-report.html \
                          -f html
                    '''

                    // Arrêter ZAP
                    sh 'docker stop zap && docker rm zap'
                }
            }
        }

        stage('Publish Report') {
            steps {
                publishHTML([
                    reportDir: 'zap-reports',
                    reportFiles: 'zap-report.html',
                    reportName: 'ZAP Security Report'
                ])
            }
        }
    }

    post {
        failure {
            emailext (
                subject: "ZAP Security Scan Failed: ${env.JOB_NAME}",
                body: "Check console output at ${env.BUILD_URL}",
                to: "security@exemple.com"
            )
        }
    }
}

Intégration avec GitLab CI

.gitlab-ci.yml :

stages:
  - build
  - test
  - security
  - deploy

build:
  stage: build
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - dist/

deploy_test:
  stage: test
  script:
    - ./deploy-to-test.sh
  environment:
    name: test
    url: http://test.exemple.com

zap_scan:
  stage: security
  image: zaproxy/zap-stable
  script:
    - mkdir -p /zap/wrk/reports
    - zap-baseline.py -t http://test.exemple.com -r /zap/wrk/reports/baseline.html -c baseline.conf || true
    - zap-full-scan.py -t http://test.exemple.com -r /zap/wrk/reports/full.html -m 10 || true
  artifacts:
    when: always
    paths:
      - /zap/wrk/reports/
    reports:
      junit: /zap/wrk/reports/*.xml
  allow_failure: true

deploy_prod:
  stage: deploy
  script:
    - ./deploy-to-prod.sh
  when: manual
  only:
    - main

Intégration avec GitHub Actions

.github/workflows/zap-scan.yml :

name: ZAP Security Scan

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron: '0 2 * * 1'  # Every Monday at 2am

jobs:
  zap_scan:
    runs-on: ubuntu-latest
    name: ZAP Baseline Scan

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.7.0
        with:
          target: 'https://test.exemple.com'
          rules_file_name: '.zap/rules.tsv'
          cmd_options: '-a'

      - name: Upload ZAP Report
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: zap-report
          path: report_html.html

      - name: Create Issue on Failure
        if: failure()
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: 'ZAP Security Scan Failed',
              body: 'ZAP scan detected security issues. Check the workflow run for details.',
              labels: ['security', 'zap']
            })

Fichier de règles .zap/rules.tsv :

10015   IGNORE  (Cookie Without Secure Flag - Dev environment)
10054   IGNORE  (Cookie Without SameSite - Dev environment)
10011   WARN    (Cookie No HttpOnly Flag)
10098   FAIL    (Cross-Domain Misconfiguration)
40018   FAIL    (SQL Injection)
40012   FAIL    (Cross Site Scripting)

Intégration avec Azure DevOps

azure-pipelines.yml :

trigger:
  - main
  - develop

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: Docker@2
    displayName: 'Start ZAP Container'
    inputs:
      command: 'run'
      arguments: >
        -d --name zap
        -p 8080:8080
        -v $(Build.ArtifactStagingDirectory):/zap/wrk:rw
        zaproxy/zap-stable
        zap.sh -daemon -host 0.0.0.0 -port 8080
        -config api.disablekey=true

  - bash: |
      sleep 30
      docker exec zap zap-baseline.py -t http://test.exemple.com -r /zap/wrk/baseline.html
    displayName: 'Run ZAP Baseline Scan'
    continueOnError: true

  - task: PublishBuildArtifacts@1
    displayName: 'Publish ZAP Report'
    inputs:
      PathtoPublish: '$(Build.ArtifactStagingDirectory)'
      ArtifactName: 'zap-reports'

  - bash: |
      docker stop zap && docker rm zap
    displayName: 'Stop ZAP Container'
    condition: always()

Extensions et Add-ons

Marketplace ZAP

Toolbar → Manage Add-ons (icône puzzle)

Onglets : - Installed : Extensions installées - Marketplace : Extensions officielles - Uninstalled : Extensions disponibles mais pas installées

Add-ons essentiels

1. AJAX Spider

Marketplace → AJAX Spider → Install

Pour les applications JavaScript/SPA.

2. GraphQL Support

Marketplace → GraphQL Support → Install

Import et test de schémas GraphQL.

3. Advanced SQLInjection Scanner

Marketplace → Advanced SQLInjection Scanner → Install

Tests d’injection SQL plus approfondis.

4. DOM XSS Scanner

Marketplace → DOM XSS → Install

Détection de XSS basées sur le DOM.

5. Wappalyzer - Technology Detection

Marketplace → Wappalyzer → Install

Identifie les technologies utilisées (frameworks, CMS, serveurs).

6. Retire.js

Marketplace → Retire.js → Install

Détecte les bibliothèques JavaScript vulnérables.

7. JWT Support

Marketplace → JWT Support → Install

Décode et manipule les JSON Web Tokens.

8. Directory List v2.3

Marketplace → Directory List → Install

Listes de répertoires pour forced browsing.

9. FuzzDB Files

Marketplace → FuzzDB Files → Install

Payloads de fuzzing additionnels.

10. Report Generation

Marketplace → Report Generation → Install

Templates de rapports supplémentaires.

Utilisation de l’add-on JWT Support

Exemple :

  1. Intercepter une requête avec JWT : http GET /api/users HTTP/1.1 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

  2. Clic droit → Show JWT

  3. Le JWT est décodé : ```json Header: { “alg”: “HS256”, “typ”: “JWT” }

Payload: { “sub”: “1234567890”, “name”: “John Doe”, “iat”: 1516239022 } ```

  1. Modifier le payload : json { "sub": "1234567890", "name": "Admin", "role": "admin", "iat": 1516239022 }

  2. Fuzzer l’algorithme (attaque None) : json Header: { "alg": "none", "typ": "JWT" }

  3. Tester la signature : - Bruteforce de la clé secrète - Test de clés faibles (secret, password, 123456)

Utilisation de Wappalyzer

Après spider ou navigation :

1. Clic droit sur un site
2. Wappalyzer  Detect Technologies

Résultats :
- Web Server: Apache 2.4.41
- Programming Language: PHP 7.4.3
- Framework: Laravel 8.x
- JavaScript Library: jQuery 3.5.1
- CMS: WordPress 5.9
- Database: MySQL
- CDN: Cloudflare

Utilité : - Adapter les tests aux technologies détectées - Identifier les versions vulnérables - Optimiser la politique de scan

Créer son propre add-on

ZAP permet de créer des add-ons personnalisés en Java.

Structure d’un add-on :

my-addon/
├── src/
│   └── org/zaproxy/zap/extension/myaddon/
│       ├── ExtensionMyAddon.java
│       ├── MyAddonPanel.java
│       └── resources/
│           └── Messages.properties
├── build.gradle
└── ZapAddOn.xml

Exemple simple : ExtensionMyAddon.java

package org.zaproxy.zap.extension.myaddon;

import org.parosproxy.paros.extension.ExtensionAdaptor;
import org.parosproxy.paros.extension.ExtensionHook;

public class ExtensionMyAddon extends ExtensionAdaptor {

    public ExtensionMyAddon() {
        super();
        setName("MyCustomAddon");
    }

    @Override
    public void hook(ExtensionHook extensionHook) {
        super.hook(extensionHook);

        // Ajouter un panel personnalisé
        if (getView() != null) {
            extensionHook.getHookView().addStatusPanel(new MyAddonPanel());
        }
    }

    @Override
    public String getAuthor() {
        return "Your Name";
    }

    @Override
    public String getDescription() {
        return "My custom ZAP addon";
    }
}

Cas Pratiques et Scénarios Réels

Scénario 1 : Test d’une application e-commerce

Objectif : Tester une boutique en ligne de bout en bout.

Étapes :

  1. Configuration initiale ```
  2. Lancer ZAP
  3. Créer un nouveau contexte “EcommerceApp”
  4. Include: https://shop.exemple.com/.*
  5. Exclude: https://shop.exemple.com/logout ```

  6. Exploration manuelle ```

  7. Quick Start → Manual Explore
  8. Launch Browser
  9. Naviguer :
    • Page d’accueil
    • Recherche de produits
    • Ajout au panier
    • Processus de checkout
    • Créer un compte
    • Se connecter
  10. Fermer le navigateur ```

  11. Configurer l’authentification ```

  12. Context → Authentication → Form-Based
  13. Login URL: https://shop.exemple.com/login
  14. Trouver la requête POST de login dans History
  15. Flag as Context → Authentication Login Request
  16. Logged In Indicator: “My Account”
  17. Add User: testuser / testpass123 ```

  18. Spider automatique ```

  19. Clic droit sur site → Attack → Spider
  20. User: testuser
  21. Start Spider
  22. Attendre la fin (100%) ```

  23. AJAX Spider (pour le JS) ```

  24. Attack → AJAX Spider
  25. Start
  26. Attendre la fin ```

  27. Analyse passive ```

  28. Vérifier les alertes détectées passivement
  29. Alerts → Filtrer par Risk: High, Medium
  30. Noter :

    • Missing security headers
    • Cookies without Secure flag
    • Mixed content ```
  31. Scan actif ciblé ```

  32. Clic droit sur /checkout → Active Scan
  33. User: testuser
  34. Policy: Default
  35. Start Scan
  36. Répéter pour :

    • /search
    • /product/view
    • /cart
    • /payment ```
  37. Tests manuels spécifiques

Test 1 : Manipulation de prix ``` Requête POST /cart/add : product_id=42&quantity=1&price=99.99

Modifier : product_id=42&quantity=1&price=0.01

Observer si le prix est validé côté serveur ```

Test 2 : Manipulation d’ID utilisateur ``` GET /orders/view?order_id=123&user_id=42

Modifier user_id pour voir les commandes d’autres utilisateurs ```

Test 3 : Bypass de paiement ``` POST /payment/process order_id=123&amount=99.99&status=pending

Modifier : order_id=123&amount=99.99&status=paid ```

  1. Génération du rapport Report → Generate HTML Report Title: "E-commerce Security Assessment" Include: All Alerts Generate

  2. Résultats attendus ``` High:

    • SQL Injection in /search
    • IDOR in /orders/view
    • Price manipulation in /cart

    Medium: - XSS in product reviews - CSRF in checkout - Weak session cookies

    Low: - Missing X-Frame-Options - Cookie without SameSite ```

Scénario 2 : API REST mobile

Objectif : Tester l’API backend d’une application mobile.

Étapes :

  1. Configuration du proxy mobile ```
  2. ZAP : Tools → Options → Local Proxies

    • Address: 0.0.0.0 (écouter sur toutes les interfaces)
    • Port: 8080
  3. Sur le smartphone :

    • WiFi Settings → Proxy Manual
    • Server: [IP de votre PC] (ex: 192.168.1.100)
    • Port: 8080
  4. Installer le certificat ZAP sur le mobile :

    • Naviguer vers http://192.168.1.100:8080
    • Télécharger le certificat
    • Installer (Settings → Security → Install from storage) ```
  5. Capturer le trafic ```

  6. Utiliser l’application mobile normalement
  7. Observer toutes les requêtes API dans ZAP History
  8. Identifier les endpoints :

    • GET /api/v1/users/me
    • POST /api/v1/auth/login
    • GET /api/v1/products
    • POST /api/v1/orders
    • etc. ```
  9. Analyse du mécanisme d’authentification ``` Requête de login : POST /api/v1/auth/login Content-Type: application/json

{“email”: “user@test.com”, “password”: “pass123”}

Réponse : { “token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…”, “refresh_token”: “…”, “expires_in”: 3600 }

Requêtes suivantes : Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9… ```

  1. Tests JWT ```
  2. Installer JWT add-on
  3. Sélectionner une requête avec JWT
  4. Show JWT → Observer le contenu : { “user_id”: 42, “email”: “user@test.com”, “role”: “user”, “exp”: 1234567890 }

  5. Tester :

    • Modification du user_id
    • Modification du role (user → admin)
    • Algorithme “none”
    • Token expiré
    • Token malformé ```
  6. Énumération d’endpoints ```

  7. Forced Browse sur /api/v1/
  8. Liste personnalisée : /api/v1/admin /api/v1/debug /api/v1/internal /api/v1/test /api/v1/swagger /api/v1/docs /api/v2/

  9. Résultats : ✅ /api/v1/swagger (200 OK) → Documentation complète de l’API! ✅ /api/v1/admin (403 Forbidden) → Existe mais protégé ```

  10. Import Swagger/OpenAPI ```

  11. Import → OpenAPI
  12. URL: https://api.exemple.com/api/v1/swagger.json
  13. Import

Tous les endpoints sont automatiquement ajoutés! ```

  1. Fuzzing des endpoints ``` GET /api/v1/users/42

Fuzzer “42” : - 1-1000 (énumération) - SQLi payloads - -1, 0, 99999999 - ../../../etc/passwd - ```

  1. Test de limites de taux (Rate Limiting) ```
  2. Requête : POST /api/v1/auth/login
  3. Resend 1000 fois rapidement
  4. Observer :

    • 429 Too Many Requests ? (✅ protégé)
    • 200 OK toujours ? (❌ pas de protection) ```
  5. Mass Assignment ``` POST /api/v1/users { “email”: “test@test.com”, “password”: “pass123” }

Tester : { “email”: “test@test.com”, “password”: “pass123”, “role”: “admin”, “is_verified”: true, “credits”: 99999 }

Observer si les champs supplémentaires sont acceptés ```

  1. Rapport final ``` High:

    • JWT signature not verified (algorithm “none” accepted)
    • IDOR in /api/v1/users/{id}
    • Mass assignment in user creation

    Medium: - No rate limiting on authentication - Swagger documentation publicly accessible - Verbose error messages expose stack traces

    Low: - API versioning in URL (should use headers) ```

Scénario 3 : Application avec 2FA

Objectif : Tester une application avec authentification à deux facteurs.

Méthode pour contourner/tester 2FA :

  1. Test de bypass direct ``` Étapes normales :
  2. POST /login → Redirect to /2fa
  3. POST /2fa/verify → Redirect to /dashboard

Test : 1. POST /login 2. Au lieu de /2fa, accéder directement à /dashboard 3. Observer si l’accès est autorisé (bypass!) ```

  1. Test de réutilisation de code ```
  2. Se connecter normalement
  3. Noter le code 2FA : 123456
  4. Se reconnecter
  5. Réutiliser le code : 123456
  6. Observer si accepté (le code devrait être à usage unique) ```

  7. Test de bruteforce ```

  8. Intercepter POST /2fa/verify
  9. Body: code=123456
  10. Fuzzer avec Numberzz : 000000-999999
  11. Observer :

    • Rate limiting ? (après X tentatives)
    • Account lockout ?
    • Bruteforce possible ? ```
  12. Test du backup code ``` Si des codes de backup sont fournis :

  13. Utiliser un code de backup
  14. Réutiliser le même code
  15. Observer s’il est invalidé après usage ```

Scénario 4 : Scan en CI/CD

Objectif : Intégrer ZAP dans un pipeline CI/CD.

Workflow complet :

#!/bin/bash
# ci-zap-scan.sh

set -e

# Variables
TARGET_URL="http://staging.exemple.com"
ZAP_PORT=8080
REPORT_DIR="./zap-reports"
FAIL_ON_HIGH=true

echo "[*] Starting ZAP daemon..."
docker run -d --name zap \
  -p ${ZAP_PORT}:${ZAP_PORT} \
  -v $(pwd)/${REPORT_DIR}:/zap/wrk:rw \
  zaproxy/zap-stable \
  zap.sh -daemon -host 0.0.0.0 -port ${ZAP_PORT} \
  -config api.disablekey=true

echo "[*] Waiting for ZAP to start..."
sleep 30

echo "[*] Running baseline scan..."
docker exec zap zap-baseline.py \
  -t ${TARGET_URL} \
  -r /zap/wrk/baseline-report.html \
  -J /zap/wrk/baseline-report.json \
  -c baseline.conf

echo "[*] Parsing results..."
HIGH_COUNT=$(docker exec zap python3 -c "
import json
with open('/zap/wrk/baseline-report.json') as f:
    data = json.load(f)
    high = sum(1 for alert in data['site'][0]['alerts'] if alert['riskcode'] == '3')
    print(high)
")

echo "[+] Found ${HIGH_COUNT} high-risk alerts"

echo "[*] Stopping ZAP..."
docker stop zap && docker rm zap

# Fail le build si alertes high
if [ "$FAIL_ON_HIGH" = true ] && [ "$HIGH_COUNT" -gt 0 ]; then
    echo "[!] Build failed: ${HIGH_COUNT} high-risk alerts found"
    exit 1
fi

echo "[+] Scan completed successfully"
exit 0

Bonnes Pratiques et Éthique

Aspects légaux

⚠️ AVERTISSEMENT IMPORTANT ⚠️

L'utilisation de ZAP est soumise à des restrictions légales strictes :

✅ AUTORISÉ :
- Tests sur vos propres applications
- Pentests avec autorisation écrite
- Environnements de formation et CTF
- Recherche en sécurité avec permission
- Tests dans le cadre d'un Bug Bounty program

❌ INTERDIT :
- Tests sans autorisation explicite
- Scan de sites tiers sans permission
- Exploitation de vulnérabilités découvertes
- Accès non autorisé à des systèmes
- Exfiltration de données sans permission

Authorization et Documentation

Checklist avant un test :

□ Autorisation écrite obtenue et signée
□ Périmètre clairement défini (URLs, IPs)
□ Date et heure des tests convenus
□ Contact technique identifié
□ Contact d'urgence disponible
□ Limitations comprises (pas de DoS, etc.)
□ Backup des données effectué (si applicable)
□ Plan de communication établi
□ Assurance responsabilité professionnelle à jour
□ NDA signé si nécessaire

Document d’autorisation type :

# AUTORISATION DE TEST DE SÉCURITÉ

## Informations générales
- Date : [DATE]
- Client : [NOM DE L'ENTREPRISE]
- Testeur : [VOTRE NOM / ENTREPRISE]
- Période : Du [DATE DÉBUT] au [DATE FIN]

## Périmètre autorisé
### Applications web
- https://app.exemple.com
- https://api.exemple.com
- https://admin.exemple.com

### Exclusions
- https://exemple.com/payment/* (système de paiement tiers)
- https://exemple.com/analytics/* (Google Analytics)

## Types de tests autorisés
- ✅ Scan passif
- ✅ Scan actif
- ✅ Spider/Crawling
- ✅ Fuzzing
- ❌ DoS/DDoS
- ❌ Social engineering
- ❌ Attaques physiques

## Restrictions
- Tests pendant les heures creuses (22h-6h) uniquement
- Maximum 10 threads concurrents
- Prévenir 24h avant chaque test
- Arrêter immédiatement si problème détecté

## Contacts
- Contact technique : [NOM] - [EMAIL] - [TÉLÉPHONE]
- Contact urgence : [NOM] - [EMAIL] - [TÉLÉPHONE]

## Signatures
Client : _________________ Date : _________
Testeur : ________________ Date : _________

Minimiser l’impact

1. Limiter la charge serveur

Tools → Options → Active Scan
- Host per Scan: 1
- Concurrent Scans: 1
- Max Results to List: 100

Tools → Options → Connection
- Timeout: 30 seconds
- Max connections per host: 5

2. Éviter les tests destructifs

Analyze  Scan Policy Manager
- Désactiver :
  - Persistent XSS (stockage de données)
  - SQL Injection (utiliser des payloads safe)
  - Remote File Include
  - Server Side Include

3. Exclure les fonctionnalités sensibles

Context → Exclude from Context:
.*logout.*
.*delete.*
.*remove.*
.*drop.*
.*admin/reset.*

4. Planifier les scans

# Lancer ZAP à une heure précise (cron)
0 2 * * * /opt/zap/zap.sh -cmd -autorun /path/to/plan.yaml

# Uniquement pendant les weekends
0 2 * * 6 /opt/zap/zap.sh -cmd -autorun /path/to/plan.yaml

Gestion des faux positifs

Marquer comme faux positif :

1. Sélectionner une alerte
2. Clic droit  Mark as False Positive
3. Ajouter un commentaire expliquant pourquoi

Exporter/Importer les faux positifs :

Tools → Options → Alert Filters
- Add alert filter
- Rule: SQL Injection
- URL: http://exemple.com/safe-endpoint
- Action: False Positive

File → Properties → Export Alert Filters

Utile pour : - Réutiliser entre scans - Partager avec l’équipe - Automatiser les scans récurrents

Reporting professionnel

Structure recommandée d’un rapport :

# Rapport de Test de Sécurité Web

## 1. Résumé exécutif
- Période du test
- Périmètre
- Méthodologie
- Résumé des findings
- Recommandations principales

## 2. Vue d'ensemble
### 2.1 Objectifs
### 2.2 Périmètre
### 2.3 Limitations
### 2.4 Méthodologie

## 3. Résultats détaillés
### 3.1 Statistiques
- Total URLs scanned: 1,234
- Total Alerts: 45
  - High: 3
  - Medium: 12
  - Low: 20
  - Informational: 10

### 3.2 Vulnérabilités critiques
#### 3.2.1 SQL Injection (CVSS 9.8)
- **Description** : ...
- **Impact** : ...
- **Localisation** : ...
- **Preuve de concept** : ...
- **Recommandation** : ...

### 3.3 Vulnérabilités moyennes
### 3.4 Vulnérabilités basses
### 3.5 Informations

## 4. Recommandations
### 4.1 Court terme (0-30 jours)
### 4.2 Moyen terme (30-90 jours)
### 4.3 Long terme (90+ jours)

## 5. Conclusion

## 6. Annexes
- A. Méthodologie détaillée
- B. Screenshots
- C. Logs techniques
- D. Références (OWASP, CWE, CVE)

Formation continue

Ressources pour apprendre :

  1. Environnements de pratique légaux - DVWA (Damn Vulnerable Web Application) - WebGoat (OWASP) - Juice Shop (OWASP) - bWAPP - Mutillidae - HackTheBox - TryHackMe - PentesterLab

  2. Documentation officielle - https://www.zaproxy.org/docs/ - https://www.zaproxy.org/docs/desktop/start/ - https://www.zaproxy.org/docs/api/

  3. Vidéos et tutoriels - OWASP ZAP YouTube Channel - Simon Bennetts (créateur de ZAP) talks - PentesterAcademy

  4. Certifications - OSCP (Offensive Security Certified Professional) - CEH (Certified Ethical Hacker) - GWAPT (GIAC Web Application Penetration Tester) - OSWE (Offensive Security Web Expert)

Environnement de test local :

# Installer OWASP Juice Shop
docker run -d -p 3000:3000 bkimminich/juice-shop

# Configurer ZAP pour le tester
# URL: http://localhost:3000
# 100% légal et safe!

Conclusion

OWASP ZAP est un outil extrêmement puissant et versatile pour la sécurité des applications web. Sa gratuité, son extensibilité, et son intégration CI/CD en font un choix excellent tant pour les débutants que les experts.

Points clés à retenir

  1. Toujours obtenir une autorisation avant tout test
  2. Commencer par du passif (sans risque)
  3. Progresser vers l’actif avec prudence
  4. Combiner automatisation et tests manuels pour de meilleurs résultats
  5. Documenter méticuleusement toutes les vulnérabilités
  6. Minimiser l’impact sur les systèmes testés
  7. Former continuellement vos compétences

Workflow recommandé

1. Configuration (Context, Scope, Auth)
   
2. Exploration (Manual + Spider + AJAX Spider)
   
3. Analyse passive (détection sans risque)
   
4. Tests manuels ciblés (interception, modification)
   
5. Scan actif (automatisé mais invasif)
   
6. Fuzzing (tests approfondis)
   
7. Validation manuelle (éliminer faux positifs)
   
8. Reporting (documentation complète)

Aller plus loin

Après avoir maîtrisé ZAP : - Approfondir l’exploitation manuelle - Apprendre le développement sécurisé - Explorer d’autres outils (Burp Suite Pro, Acunetix, etc.) - Participer à des Bug Bounty programs - Contribuer au projet OWASP ZAP


Version du document : 1.0 Dernière mise à jour : 2025 Auteur : Guide complet OWASP ZAP

Avertissement : Ce document est fourni à des fins éducatives uniquement. L’auteur et les distributeurs ne peuvent être tenus responsables de toute utilisation illégale ou non éthique de ces informations. Toujours obtenir une autorisation écrite avant de tester la sécurité d’un système.