Come vengono utilizzate le codifiche dei caratteri per bypassare i disinfettanti XSS?

8

Ho letto in diversi blog che la funzione% di% di% di file% ha alcuni problemi quando uno non fornisce il set di caratteri previsto come parametro facoltativo.

Qualcuno può spiegare alcune cose di base sugli exploit XSS derivanti dall'uso errato delle funzioni di sanitizzazione con alcuni esempi relativi alla codifica dei caratteri?

Questo influisce anche sui browser moderni?

    
posta XII 28.02.2018 - 08:26
fonte

3 risposte

11

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.

    
risposta data 28.02.2018 - 14:12
fonte
5

Questo si presenta come un'aggiunta alla risposta di Anders (che è fantastica).

My understanding is that it is mostly old versions of IE where this is a problem. But I do not have a source for that, and I am not sure, so I would be happy to see another answer where it is clarified.

Sì, questo riguarda i browser moderni.

Prendiamo la seguente sanificazione:

<?php
    header('Content-Type: text/html;charset=utf-8');
    echo preg_replace('/<\w+/', '', $_GET['name']).", can you p0wn it ?"
?>

Questo potrebbe non sembrare vulnerabile perché:

  • < seguito da una o più lettere è stato rimosso in modo che un utente malintenzionato non possa aprire un nuovo tag.
  • Content-Type header è correttamente impostato su utf-8

Ora, immagina di inviare %00%3C%00 , il parser regex fallirà perché < ( %3C ) non è seguito da una lettera (come definito da \w ) ma da %00 (il byte null ). In UTF-8 , l'input riflesso non eseguirà nulla, ma se riusciamo a trovare un modo per farlo riflettere in UTF-16 ...

Ecco cosa possiamo leggere da W3 :

If you have a UTF-8 byte-order mark (BOM) at the start of your file then recent browser versions other than Internet Explorer 10 or 11 will use that to determine that the encoding of your page is UTF-8. It has a higher precedence than any other declaration, including the HTTP header.

You could skip the meta encoding declaration if you have a BOM, but we recommend that you keep it, since it helps people looking at the source code to ascertain what the encoding of the page is.

Il carattere BOM in UTF-16 è il carattere unicode U+FEFF (la codifica BOM diversa è meglio descritta su > Wikipedia). Pertanto, poiché il nostro input viene riflesso all'inizio del dom , possiamo modificare il set di caratteri in UTF-16 e ottenere il nostro codice da eseguire.

Carico utile completo:

%FE%FF%00%3C%00s%00c%00r%00i%00p%00t%00%3E%00a%00l%00e%00r%00t%00(%00%22%00P%000%00w%00n%00e%00d%00%22%00)%00;%00%3C%00/%00s%00c%00r%00i%00p%00t%00%3E

Ecco un POC che ho creato. La maggior parte degli auditor xss non si innamorerà di questo, ma Firefox dal momento che il suo auditor è disabilitato di default. (testato su Firefox Nightly 60.0a1 - ultima versione ad oggi)

Tuttavia, htmlspecialchars e htmlentities non cadranno per questo. Ciò nonostante, ciò dimostra che ci sono sempre casi complicati dietro l'angolo!

Altri attacchi alla codifica includono mappatura dei personaggi , che sono ancora attuali fino ad oggi.

    
risposta data 28.02.2018 - 20:22
fonte
1

Dalla pagina OWASP XSS :

"Cross-Site Scripting attacks are a type of injection problem, in which malicious scripts are injected into the otherwise benign and trusted web sites. Cross-site scripting (XSS) attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application uses input from a user in the output it generates without validating or encoding it.

An attacker can use XSS to send a malicious script to an unsuspecting user. The end user’s browser has no way to know that the script should not be trusted, and will execute the script. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other sensitive information retained by your browser and used with that site. These scripts can even rewrite the content of the HTML page."

Questo è un esempio di cattive pratiche di codifica in cui non si sanifica l'input dell'utente.

Immaginiamo che tu sia uno sviluppatore web e crei questo file nel tuo sito web ( name.php ):

<form action="" method="GET">
  What is your name: <input type="text" name="username"><br>
  <input type="submit" value="Submit">
</form>

<?php
  print("Entered name is: ".$_GET["username"]);
?>

Quando apri questa pagina sul tuo browser, vedrai qualcosa di simile a questo:

Mettiamounnomeevediamoilcomportamentodiquestosemplicefile,datochestiamousandoilmetodoGET,saremoingradodivedereidatiinviatisull'URL:

Ma,cosasuccedesequalcunotentadiiniettaredelcodiceHTMLinquestacasellainput, qualcosacome

<marquee><h1>Andrewng</h1></marquee>

Vediirisultatinell'immaginequisotto:

L'inputdell'utenteèstatoresocomesefossepartedelcodicesorgenteoriginaledelfile.

OraseproviamolastessacosaconilcodiceJavascript,vediamocosasuccede,ilcodicediiniezionedatestaresuibrowsersarà2modidiXSS:

<h1>Andrew</h1><script>alert("XSS");</script>

<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">

In entrambi i casi Google Chrome ha bloccato l'esecuzione di questo script:

Tuttavia,inMozillaFirefoxentrambigliscriptvengonoeseguiticorrettamente:

SperochequestopossadartiunamigliorecomprensionediXSSedellasituazioneattualeconibrowsermoderni,questoèstatotestatosu:

  • GoogleChrome64.0.3282.119(buildufficiale)(64-bit)
  • MozillaFirefoxQuantum58.0(64-bit)

Informazionisullafunzionehtmlspecialchars()puoitrovareulterioriinformazioni qui .

Un altro esempio di XSS che potrebbe interessarti è questo nel mio blog.

Spero che ti aiuti.

    
risposta data 28.02.2018 - 09:27
fonte

Leggi altre domande sui tag