L'XSS è possibile quando non è sfuggito, ma non viene visualizzato anche se seguito da un carattere?

10

Ho capito che < non è stato codificato come &lt; . Invece, semplicemente non viene inviato dal server se viene seguito direttamente da qualcosa. Ad esempio, <a non mostrerà nulla. Ma sono in grado di visualizzare < a> (notare lo spazio), che non è utile.

Tranne il carattere < , non ci sono restrizioni e nessun carattere codificato.

Ecco il codice indicato:

<span>USER INPUT</span>

Ecco il tipo di contenuto della pagina:

text/html; charset=utf-8

E il tipo di contenuto per la richiesta di input:

application/x-www-form-urlencoded; charset=UTF-8 

Altre informazioni specifiche:

Server: nginx
X-Powered-By: PHP/5.5.18-1~dotdeb.1

C'è un modo in cui questo metodo è vulnerabile a XSS?

    
posta Xavier59 09.05.2016 - 23:04
fonte

4 risposte

8

No, in un contesto HTML non puoi inserire nuovi tag senza lettere dopo la parentesi aperta. Tuttavia, questa tecnica di filtraggio è inutilmente rischiosa.

Il parser HTML del tuo browser web analizza il codice come macchina di stato . Per capire quali sono le tue opzioni, dai un'occhiata alla specifica della sintassi HTML e alle possibili transizioni di stato.

Il punto di iniezione si trova nello stato dei dati (che è il " predefinito "stato, al di fuori di qualsiasi tag):

8.2.4.1 Data state

Consume the next input character:

U+0026 AMPERSAND (&)
    Switch to the character reference in data state.
"<" (U+003C)
    Switch to the tag open state.
U+0000 NULL
    Parse error. Emit the current input character as a character token.
EOF
    Emit an end-of-file token.
Anything else
    Emit the current input character as a character token.

Per XSS, l'unica continuazione interessante è aprire un tag con < e passare a tag open state :

8.2.4.8 Tag open state

Consume the next input character:

"!" (U+0021)
    Switch to the markup declaration open state.
"/" (U+002F)
    Switch to the end tag open state.
Uppercase ASCII letter
    Create a new start tag token, set its tag name to the lowercase version of the current input character (add 0x0020 to the character's code point), then switch to the tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
Lowercase ASCII letter
    Create a new start tag token, set its tag name to the current input character, then switch to the tag name state. (Don't emit the token yet; further details will be filled in before it is emitted.)
"?" (U+003F)
    Parse error. Switch to the bogus comment state.
Anything else
    Parse error. Switch to the data state. Emit a U+003C LESS-THAN SIGN character token. Reconsume the current input character. 

Qui le tue opzioni sono a-z , A-Z , ! , / e ? . Non sei stato chiaro se anche i caratteri speciali siano nella lista nera. Ma anche se non lo sono, sei sfortunato:

  • Da <! si ottiene solo un commento ( <!-- ), una dichiarazione doctype ( <!DOCTYPE ) o una sezione CDATA ( <![CDATA ). Questi non sono veri nodi DOM e quindi sono inutili per XSS. (Ad esempio, non si sarebbe in grado di allegare un gestore di eventi a un commento.)
  • <? potrebbe essere interessante in XML, ma è trattato come un commento in HTML.
  • </ ti consente solo di chiudere i tag.

Potresti aver notato che le specifiche non tollerano alcun carattere di riempimento, come spazi, tabulazioni, nuove righe o caratteri di controllo.

Se vuoi approfondire un po 'e verificare l'implementazione, puoi sempre consultare il codice sorgente. Ad esempio, questo estratto fa parte del tokenizzatore HTML5 utilizzato in Mozilla Firefox . Come puoi vedere, lo stato tag open aderisce strettamente alle specifiche:

case NS_HTML5TOKENIZER_TAG_OPEN: {
  for (; ; ) {
    if (++pos == endPos) {
      NS_HTML5_BREAK(stateloop);
    }
    c = checkChar(buf, pos);
    if (c >= 'A' && c <= 'Z') {
      endTag = false;
      clearStrBufAndAppend((char16_t) (c + 0x20));
      state = P::transition(mViewSource, NS_HTML5TOKENIZER_TAG_NAME, reconsume, pos);
      NS_HTML5_BREAK(tagopenloop);
    } else if (c >= 'a' && c <= 'z') {
      endTag = false;
      clearStrBufAndAppend(c);
      state = P::transition(mViewSource, NS_HTML5TOKENIZER_TAG_NAME, reconsume, pos);
      NS_HTML5_BREAK(tagopenloop);
    }
    switch(c) {
      case '!': {
        state = P::transition(mViewSource, NS_HTML5TOKENIZER_MARKUP_DECLARATION_OPEN, reconsume, pos);
        NS_HTML5_CONTINUE(stateloop);
      }
      case '/': {
        state = P::transition(mViewSource, NS_HTML5TOKENIZER_CLOSE_TAG_OPEN, reconsume, pos);
        NS_HTML5_CONTINUE(stateloop);
      }
      case '\?': {
        if (viewingXmlSource) {
          state = P::transition(mViewSource, NS_HTML5TOKENIZER_PROCESSING_INSTRUCTION, reconsume, pos);
          NS_HTML5_CONTINUE(stateloop);
        }
        if (P::reportErrors) {
          errProcessingInstruction();
        }
        clearStrBufAndAppend(c);
        state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos);
        NS_HTML5_CONTINUE(stateloop);
      }
      case '>': {
        if (P::reportErrors) {
          errLtGt();
        }
        tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 2);
        cstart = pos + 1;
        state = P::transition(mViewSource, NS_HTML5TOKENIZER_DATA, reconsume, pos);
        NS_HTML5_CONTINUE(stateloop);
      }
      default: {
        if (P::reportErrors) {
          errBadCharAfterLt(c);
        }
        tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
        cstart = pos;
        reconsume = true;
        state = P::transition(mViewSource, NS_HTML5TOKENIZER_DATA, reconsume, pos);
        NS_HTML5_CONTINUE(stateloop);
      }
    }
  }
  tagopenloop_end: ;
}

Quindi, il filtro XSS che descrivi sembra essere sicuro secondo le specifiche HTML. È un ghiaccio molto sottile, difficile. Non si sa mai, se un venditore presenta un'implementazione stravagante che potrebbe comunque consentire un exploit. (Microsoft, ti sto guardando!)

La corretta protezione XSS è quindi semplicemente sfuggire al staffe .

    
risposta data 17.05.2016 - 04:26
fonte
4

Molto improbabile. L'unico vettore che riesco a vedere è un bug di codifica dei caratteri in base al quale il linguaggio di backend (ad es. PHP) è configurato per utilizzare una codifica di caratteri diversa da UTF-8 e non è in grado di riconoscere la codifica durante l'output della stringa.

Detto questo, direi che quasi certamente non è possibile ottenere XSS in questa istanza. Tuttavia, puoi ottenere XSS in qualsiasi posizione in cui ti trovi già all'interno di un tag (ad esempio, eco in un attributo).

    
risposta data 10.05.2016 - 11:24
fonte
1

In questo caso particolare, stai immettendo il tuo input come codice HTML (poiché si trova tra i tag di estensione e il tipo di contenuto è text / html). Quindi, l'unico modo che posso immaginare per il codice JavaScript di injection qui è l'uso di tag HTML. Dato il modo in cui il server risponde, è molto improbabile che puoi inserire JavaScript in questo caso specifico.

Hai 2 opzioni: in primo luogo, puoi provare a trovare se riesci a trovare un altro posto dove ti trovi già all'interno di un tag HTML (come menzionato @Polynomial). In secondo luogo, puoi trovare un posto nella pagina, dove questo input viene iniettato come JavaScript (ad esempio come valore per i gestori di eventi, all'interno di tag, ecc.), Al contrario di HTML.

Se sei in grado di trovare una seconda condizione (immetti input come JS) e ti trovi in una situazione simile in cui il server sta tentando di inserire in una lista nera determinati caratteri, puoi provare a utilizzare qualcosa come JSF##k per evitare un particolare filer / lista nera. JSF ## k è uno stile di programmazione esoterico ed educativo basato sulle parti atomiche di JavaScript. Usa solo sei caratteri diversi per scrivere ed eseguire codice. Dai un'occhiata a questo post per maggiori informazioni su di esso.

    
risposta data 16.05.2016 - 22:41
fonte
1

Prima di tutto XSS dipende interamente dal contesto in cui viene visualizzato l'output. Forzare tutti gli input anche se lo stesso filtro non funzionerà mai tutto il tempo e richiederà agli sviluppatori e ai penetration tester di cercare tutte le iniezioni. La politica di sicurezza dei contenuti aiuterà a prevenire tutti i tipi di XSS, anche quando l'applicazione soffre da servizi igienico-sanitari in uscita.

Ci sono molti modi in cui XSS è possibile date queste restrizioni arbitrarie. Ciò che viene in mente prima è XSS basato su DOM e iniezione del gestore di eventi . Reflective XSS funzionerà anche nelle seguenti condizioni:

<script>
var a="$xss";
</script>

Prova del concetto: "+alert(document.cookie)+"

O se è un luogo:

<a href="$xss">click me</a>
<iframe src="$xss"/>

Prova del concetto: javascript:alert(1)

    
risposta data 17.05.2016 - 05:53
fonte

Leggi altre domande sui tag