Il problema
L'uso improprio delle codifiche dei caratteri è un trucco popolare per far funzionare XSS anche quando sono presenti filtri. Ci sono un certo numero di situazioni diverse quando funziona, ma condividono tutti i prerequisiti comuni:
- L'attaccante invia un carico utile nella codifica dei caratteri A.
- Il server che esegue il filtraggio o la disinfezione sta funzionando nella codifica dei caratteri B.
- Il browser delle vittime interpreta la pagina come se fosse nella codifica dei caratteri A.
Diamo un'occhiata a due esempi di come ciò può accadere.
Esempio n. 1: nessun parametro di codifica in htmlspecialchars
Questo è uno spettacolo abbastanza comune in PHP:
echo htmlspecialchars($_GET["query"], ENT_COMPAT | ENT_HTML401);
Il problema qui è il comportamento predefinito che PHP ricade quando non è specificata alcuna codifica. Da il manuale :
If omitted, the default value of the encoding varies depending on the PHP version in use. In PHP 5.6 and later, the default_charset configuration option is used as the default value. PHP 5.4 and 5.5 will use UTF-8 as the default. Earlier versions of PHP use ISO-8859-1.
Quindi, ciò che la codifica di PHP utilizza dipende dalla tua versione e configurazione. Grande. Quindi ora tutto ciò che si frappone tra te e l'abisso è qualcuno che sta facendo un cambiamento innocente in php.ini
, o forse semplicemente qualcosa di semplice come un aggiornamento o una reinstallazione del server. Mi piace anche vivere pericolosamente ... ma non così pericolosamente.
Si noti che questo esempio non ha nulla a che fare con il browser. Moderno o vecchio, non importa, perché è il server e non il browser che è il problema qui.
La soluzione fuori rotta è specificare la codifica corretta e assicurarsi che lo stesso sia specificato nell'header Content-Type
HTTP della risposta:
echo htmlspecialchars($_GET["query"], ENT_COMPAT | ENT_HTML401, "UTF-8");
Esempio n. 2: euristica del browser che ti morde
Questo è un problema se il tuo server non specifica quale codifica sta usando nella risposta (o se lo fa solo in un meta tag che è molto lontano dal browser per preoccuparsene). Se non dici al browser quale codifica usare, dovrà indovinare. Sfortunatamente, tutti i browser non sono così efficaci :
If certain strings of user input -- say, +ADw-script+AD4-alert(1)+ADw-/script+AD4-
-- are echoed back early enough in the HTML page, Internet Explorer may incorrectly guess that the page is encoded in UTF-7. Suddenly, the otherwise harmless user input becomes active HTML and will execute.
Il carico utile nella citazione è <script>alert(1)</script>
codificato in UTF-7. Un disinfettante che lavora in UTF-8 non vedrebbe nulla di pericoloso in quel carico utile e lo lascia passare, ma il browser che è ingannato a funzionare in UTF-7 lo eseguirà comunque.
La mia comprensione è che si tratta di per lo più vecchie versioni di IE dove questo è un problema. Ma non ne sono sicuro, quindi sarei felice di vedere un'altra risposta dove è chiarita.
EDIT: vedi la risposta di Xavier59 per un situazione in cui funziona sui browser moderni.
La soluzione
Ciò che è necessario fare sul server è semplice in teoria. Devi assicurarti che quanto segue sia sempre vero:
- La codifica dei caratteri della risposta è impostata correttamente nelle intestazioni HTTP.
- Il filtro XSS funziona con la stessa codifica sopra specificata.
In pratica, è sorprendentemente facile sbagliare.