Questi controlli automatici funzionano inserendo un tag script contenente un token casuale in ogni campo. Ad esempio, /someRequest?foo=x&bar=y
potrebbe diventare:
GET /someRequest?foo=<script>alert("147230578")</script>&bar=<script>alert("561972456")</script>
Mantiene una mappa dei campi e i valori casuali scelti (in questo caso foo = 147230578, bar = 561972456) per tracciare quale parametro è iniettabile.
Quindi controlla se <script>alert("147230578")</script>
o <script>alert("561972456")</script>
appaiono nella pagina senza codifica . Se la stringa viene trovata, sa che XSS è molto probabile. In caso contrario, non è stato visualizzato nella pagina o è stato codificato in HTML.
Nel tuo caso, ha scoperto che se le stringhe venivano riflesse e identificava il campo iniettabile. Il motivo per cui non è stato eseguito è che il tag script è stato iniettato in un attributo HTML.
Quindi, osservando la tua iniezione:
<input type="text" name="cn" size="20" maxlength="20" value="<script>alert(1);</script>">
Ciò che accade qui è che l'HTML è malformato, quindi il renderer del browser cerca semplicemente di sfruttarlo al meglio, ignora entrambi i tag e chiude tutto dopo </script>
. Quindi vede ">
che assume è contenuto e lo mostra nella pagina.
Se invece inseriamo "><script>alert(1)</script>
nel parametro, otteniamo questo:
<input type="text" name="cn" size="20" maxlength="20" value=""><script>alert(1)</script>">
Questa volta il tag di input è chiuso, il che fa sì che il tag script
venga eseguito. XSS di successo! Di nuovo, il ">
alla fine viene trattato come contenuto.
Per un giro bonus, cosa potremmo fare se il parametro vulnerabile non consente l'uso di parentesi triangolari? Dato che siamo già in un attributo, possiamo manipolare l'elemento input
in cui ci stiamo iniettando per eseguire lo script:
" onmouseenter="alert(1)" x="
Questo crea il seguente output:
<input type="text" name="cn" size="20" maxlength="20" value="" onmouseenter="alert(1)" x="">
Si noti che l'attributo x
non fa nulla, è solo lì per permetterci di mantenere un HTML valido; gli attributi sconosciuti sono semplicemente ignorati.
In questo caso, quando il mouse dell'utente entra nell'elemento di input, esegue JavaScript e otteniamo di nuovo XSS.
Ma richiede l'interazione dell'utente fa schifo! Potremmo usare onload
, ma questo è spesso finnicky. Possiamo invece utilizzare alcuni trucchi CSS per forzare l'interazione dell'utente:
" onmouseenter="alert(1)" style="display:block;position:absolute;top:0;left:0;width:50000px;height:50000px;z-index:999999;
Questo diventa:
<input type="text" name="cn" size="20" maxlength="20" value="" onmouseenter="alert(1)" style="display:block;position:absolute;top:0;left:0;width:50000px;height:50000px;z-index:999999;">
Lo stile qui sembra un boccone ma è piuttosto semplice:
- Rendi l'elemento visualizzato come elemento di blocco (così possiamo ridimensionarlo arbitrariamente)
- Rendi la posizione dell'elemento assoluta all'interno della finestra (in modo che possiamo impostare la sua posizione ovunque)
- Sposta l'elemento in (0,0)
- Fai in modo che l'elemento riempia completamente la pagina (quindi il mouse dell'utente ha per inserirlo!)
- Rendi l'elemento visualizzato sopra a tutto il resto.
Spero che questo spieghi come funziona tutto questo e come puoi passare dall'esempio fornito da ZAP a un exploit XSS funzionante.