Penso che, diversamente da come altri hanno suggerito, non significa prevenzione contro l'XSS di tipo HTML. Dimostrerò con un esempio generalizzato da un bounty di bug XSS che ho ricevuto da un sito Web top 1000.
Supponiamo che tu abbia un'API JSONP (che, dal principio, è una pessima idea).
API meteo
Questa API JSONP restituisce il tempo, attraverso l'origine senza l'uso di CORS, per il quale contiamo con il luogo in cui vogliamo il tempo. JSONP significa che lo si carica come uno script, come questo:
* http://mywebsite.com/use-weather-api.php *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place=$_GET["place"]&callback=weatherCallback'></script>
Il contenuto di questo script verrà generato in base agli input, utilizzando il callback per passare la risposta al contesto padre, ad esempio se $_GET["place"]
è "london"
:
weatherCallback({"weather": "rainy"})
La funzione weatherCallback viene quindi chiamata con il payload JSON dall'API, dicendo che il tempo è piovoso.
Contrappunto: HTML Injection
Supponiamo di non fare nessuna sanificazione o sanificazione contestuale sui nostri input. Ora, l'XSS più semplice e più ovvio che possiamo fare è inviare un luogo che utilizza l'iniezione HTML per ottenere XSS.
* http://mywebsite.com/use-weather-api.php?place='><script>alert('xss!')</script> *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place='><script>alert('xss!')</script>&callback=weatherCallback'></script>
Vedi qui che ingenuamente aggiungendo il parametro nel nostro HTML, nell'ultima riga permettiamo all'hacker di aggiungere altro codice HTML che genera tag di script aggiuntivi che, a loro volta, consentono di aggiungere codice aggiuntivo per controllare la nostra pagina Web, alias XSS . Questa è una versione estesa di ciò che altri hanno fornito come esempio sopra.
Codifica URL non risolve questo
Tuttavia, in questo esempio, dovremmo risolvere questo non usando la codifica dell'URL, ma usando la codifica HTML. Se sostituiamo $_GET["place"]
con urlencode($_GET["place"])
, alcuni caratteri potrebbero non essere sottoposti a escape, in particolare '
(perché non è un'entità URL), ovvero possiamo ancora ottenere XSS :
* http://mywebsite.com/use-weather-api.php?place='onload='alert(1) *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place='onload='alert(1)'callback=weatherCallback'></script>
In questo caso, raggiungiamo XSS immettendo un parametro separato sul nostro tag <script>
che imposta un evento onLoad
dannoso. Possiamo farlo perché i caratteri speciali chiave HTML non sono sfuggiti dalla codifica URL.
Iniezione parametri query
Supponiamo di avere una perfetta sanitizzazione dell'HT ora. La garanzia che l'igienizzatore HTML ci darà è che impedisce che vengano aggiunte le entità HTML in cui vengono inserite, causando il fallimento dei nostri precedenti attacchi. Tuttavia, abbiamo un ultimo stratagemma, che si inserisce nel contesto dell'URL:
* http://mywebsite.com/use-weather-api.php?place=london%26callback=alert# *
<script>
function weatherCallback(data) { alert(data.weather) }
</script>
<script src='http://example.com/weather-api?place=london&callback=alert#callback=weatherCallback'></script>
In questo caso, nonostante la nostra perfetta sanitizzazione dell'HTML e la mancanza di sanitizzazione contestuale dell'URL, abbiamo permesso l'inserimento di ulteriori parametri di query nel nostro URI di richiesta. Tieni presente che &
è codificato in &
, ma verrà decodificato in &
nel momento in cui raggiunge il parser dell'URL del browser.
Poiché il parametro di callback "corretto" è stato "modificato" con #
e il nostro malevolo è stato iniettato, lo script generato sarà:
alert({"weather": "rainy"})
Permettendoci di chiamare qualsiasi funzione come pagina web (ad esempio XSS). Possiamo andare oltre e, in molti casi, scrivere qualsiasi javascript che vogliamo qui, non solo chiamate di funzione, ad esempio:
alert('hello!');({"weather": "rainy"})
Dove i nostri parametri di query sono place=london&callback=alert('hello!')#callback=weatherCallback
.
Questo è un caso in cui è importante urlencode e quindi la codifica HTML.
Quindi, cosa posso fare?
Non farlo manualmente. Non sono più i giorni di MySpace. Utilizzare un sistema di template che fornisce sanitizzazione contestuale . Ciò significa che capisce dove stai inserendo i tuoi input nell'HTML e per la maggior parte utilizza automaticamente la giusta sequenza di escape per garantire che l'iniezione di codice dannoso non avvenga - oggi abbiamo parlato della sintassi dell'URL nella sintassi HTML, ma a volte hai un URL all'interno di un tag <script>
all'interno di HTML, nel qual caso hai bisogno di escaping dell'URL, quindi di javascript di escape, quindi di escape HTML. È esasperante!
I migliori sistemi di template lo fanno in questi giorni. Quello di default di PHP non lo fa, ma ci sono altre opzioni che puoi usare. Assicurati che l'opzione che scegli sia XSS sicuro.