Come funziona questo attacco XSS?

3

AVVISO SPOILER: questa domanda contiene una risposta a uno dei problemi della Sfida XSS di Google ! Per favore smetti di leggere ulteriormente se non sei interessato a conoscere la risposta in questo momento.

Sono in grado di ottenere il livello 4 della sfida , tuttavia, non so ancora come esattamente l'exploit sta funzionando. Quello che segue è il codice della sfida XSS di Google - Livello 4:

<!doctype html>
<html>
  <head>
    <!-- Internal game scripts/styles, mostly boring stuff -->
    <script src="/static/game-frame.js"></script>
    <link rel="stylesheet" href="/static/game-frame-styles.css" />

    <script>
      function startTimer(seconds) {
        seconds = parseInt(seconds) || 3;
        setTimeout(function() { 
          window.confirm("Time is up!");
          window.history.back();
        }, seconds * 1000);
      }
    </script>
  </head>
  <body id="level4">
    <img src="/static/logos/level4.png" />
    <br>
    <img src="/static/loading.gif" onload="startTimer('{{ timer }}');" />
    <br>
    <div id="message">Your timer will execute in {{ timer }} seconds.</div>
  </body>
</html>

Fondamentalmente, stanno usando il framework Django ( che utilizza una serie di misure di sicurezza contro XSS ). La variabile timer trasporta l'input dall'utente. L'obiettivo di questa attività è di avvisare un messaggio inviando un payload che può bypassare la sicurezza XSS di Django.

Sono in grado di avvisare un messaggio utilizzando uno dei seguenti payload:

');alert('xss

o

3') || alert('1

Sono in grado di cancellare il livello utilizzando i payload di cui sopra, ma non sono ancora sicuro di dove viene chiamato esattamente il metodo alert ()? Nel gestore onload OR nel metodo startTimer() ?

Sono confuso perché se controllo l'HTML sorgente della pagina dopo aver inviato il payload, Django sta codificando il payload:

<html>
  <head>
    <!-- Internal game scripts/styles, mostly boring stuff -->
    <script src="/static/game-frame.js"></script>
    <link rel="stylesheet" href="/static/game-frame-styles.css" />

    <script>
      function startTimer(seconds) {
        seconds = parseInt(seconds) || 3;
        setTimeout(function() { 
          window.confirm("Time is up!");
          window.history.back();
        }, seconds * 1000);
      }
    </script>
  </head>
  <body id="level4">
    <img src="/static/logos/level4.png" />
    <br>
    <img src="/static/loading.gif" onload="startTimer('&#39;);alert(&#39;xss');" />
    <br>
    <div id="message">Your timer will execute in &#39;);alert(&#39;xss seconds.</div>
  </body>
</html>
    
posta Rahil Arora 09.06.2014 - 16:34
fonte

4 risposte

0

Capisco perché l'XSS ha funzionato! Una delle sezioni del cheat di OWASP XSS dice:

HTML entity encoding is okay for untrusted data that you put in the body of the HTML document, such as inside a tag. It even sort of works for untrusted data that goes into attributes, particularly if you're religious about using quotes around your attributes. But HTML entity encoding doesn't work if you're putting untrusted data inside a tag anywhere, or an event handler attribute like onmouseover, or inside CSS, or in a URL. So even if you use an HTML entity encoding method everywhere, you are still most likely vulnerable to XSS. You MUST use the escape syntax for the part of the HTML document you're putting untrusted data into. That's what the rules below are all about.

In questo caso, l'input dell'utente viene inserito in un gestore di eventi, che lo tratterà come JS anziché HTML. E, l'input viene scappato nel contesto HTML (non nel contesto JS). Pertanto, JS tratterà startTimer('3&#39;) || alert(&#39;1'); come startTimer('') || alert('1'); e semplicemente eseguirà questo script.

PS: l'escape di JS potrebbe aver impedito l'attacco.

    
risposta data 09.06.2014 - 19:45
fonte
1

Quello che succede è che l'output HTML è:

<img src="/static/loading.gif" onload="startTimer('{{ timer }}');" />

{{ timer }} è una variabile che viene "tradotta" in qualunque sia il parametro ?timer GET. Supponiamo quindi di avere un parametro legit: ?timer=3 . Viene "tradotto" in:

<img src="/static/loading.gif" onload="startTimer('3');" />

Ma cosa succede se metti un codice in timer ? 3');alert('xss');//

<img src="/static/loading.gif" onload="startTimer('3');alert('xss');//')" />

Come puoi vedere, il logo si carica e, una volta caricato, viene eseguito il callback onload . C'è la vulnerabilità.

P.S. non è in startTimer stesso, perché parseInt s la variabile, e rimuove tutto tranne i numeri, essenzialmente 3'); ... diventando in 3 .

    
risposta data 09.06.2014 - 18:03
fonte
1

Il problema è che le stringhe all'interno dei valori degli attributi HTML interpretano &#39; come equivalente a ' .

Quindi, mentre l'escape intelligente gira l'input 3') || alert('1 in 3&#39;) || alert(&#39;1 , quindi l'elemento img nella pagina diventa:

<img src="./test_files/loading.gif" onload="startTimer('3&#39;) || alert(&#39;1');">

il tuo browser considera questo come equivalente a:

<img src="./test_files/loading.gif" onload="startTimer('3') || alert('1');">

e l'XSS funziona.

La ragione per cui lo fa è quando vuoi dire che <img src="image" alt="O&#39;Malley"> il testo alt legge come O'Malley .

    
risposta data 09.06.2014 - 18:32
fonte
0

Il tuo avviso è in esecuzione nell'onload perché l'avviso non può essere un valore di parametro. In questo modo viene eseguito immediatamente.

    
risposta data 09.06.2014 - 17:38
fonte

Leggi altre domande sui tag