OAuth2 Cross Site Request Forgery e parametro di stato

31

Il link dice:

The client MUST implement CSRF protection [...] typically accomplished by requiring any request sent to the redirection URI endpoint to include a value that binds the request to the user-agent's authenticated state (e.g. a hash of the session cookie [...]

Tuttavia, non dice molto sull'implementazione. Mette solo un po 'di luce su come funziona il CSRF:

A CSRF attack against the client's redirection URI allows an attacker to inject their own authorization code or access token, which can result in the client using an access token associated with the attacker's protected resources rather than the victim's (e.g. save the victim's bank account information to a protected resource controlled by the attacker)

Ma l'uso della parola "piuttosto" rende piuttosto la dichiarazione senza valore.

Sto pensando a come implementare lo "stato" in GAE (usando Webapp2). Sarebbe più semplice partire da come un hacker potrebbe usare un CSRF contro OAuth2. Ho trovato solo un buon articolo sull'argomento: "Falsificazione richiesta cross-site e OAuth2" .

Sfortunatamente, mentre questo post sul blog è ben scritto, non ci sono molte informazioni oltre a spiegare OAuth2. Gli esempi non funzionano, e non conosco Spring. Tuttavia, ho trovato una raccomandazione interessante lì: il server che si connette a un provider OAuth2 deve memorizzare "stato" come una chiave di sessione casuale (ad esempio "this_is_the_random_state": "this_doesn't_matter") e non un valore sotto una chiave statica (ad es. "stato": "random_state_string").

La mia domanda è, qual è la sana attuazione dello "stato"?

  • Lo stato generato casualmente deve essere sottoposto a hash o lo stesso valore può essere memorizzato e inviato al provider OAuth2?
  • C'è una differenza qui se il back-end di sessione è un cookie sicuro o una tecnologia di storage lato server (ad esempio in GAE Memcache o nel database)?
  • Lo stato dovrebbe essere memorizzato come una chiave come suggerito?
  • Lo stato dovrebbe avere un periodo di validità, oppure la sessione (se ce n'è una) è abbastanza lunga?
posta Markus von Broady 14.09.2012 - 12:17
fonte

3 risposte

13

Semplificheremo questo problema. Falsificazione richiesta tra siti e Clikjacking sono utili perché possono forzare il browser di una vittima a compiere azioni contro la loro volontà.

La menzione di 10.12. Cross-Site Request Forgery e 10.13. Clickjacking nella OAuth v2 RFC hanno fondamentalmente la stessa preoccupazione. Se un utente malintenzionato può forzare l'autenticazione del browser di una vittima, allora è un passo utile per forzare il browser della vittima a compiere altre azioni.

   in a clickjacking attack, an attacker registers a legitimate client
   and then constructs a malicious site in which it loads the
   authorization server's authorization endpoint web page in a
   transparent iframe overlaid on top of a set of dummy buttons, which
   are carefully constructed to be placed directly under important
   buttons on the authorization page.  When an end-user clicks a
   misleading visible button, the end-user is actually clicking an
   invisible button on the authorization page (such as an "Authorize"
   button).  This allows an attacker to trick a resource owner into
   granting its client access without their knowledge.

Fonte: 10.13. Clickjacking

Ad esempio, Stack Overflow utilizza OAuth ed è vulnerabile a questo attacco. Se visiti StackOverflow e sei attualmente connesso al tuo provider OAuth, verrai automaticamente connesso a StackOverflow. Pertanto, un utente malintenzionato può automaticamente accedere a una vittima caricando Stack Oveflow all'interno di un iframe. Se Stack Overflow aveva anche una vulnerabilità CSRF ( e li ha avuti ! ), quindi un utente malintenzionato potrebbe autenticare automaticamente il browser di una vittima ed effettuare un attacco CSRF (Session Riding), Clickjacking o XSS contro stackoverflow.com in un Chained Attack .

    
risposta data 01.10.2012 - 02:35
fonte
29

Esaminiamo come funziona questo attacco.

L'attacco

  1. Visito il sito web di del cliente e avvia il processo di autorizzazione di quel client per accedere ad alcuni provider di servizi utilizzando OAuth

  2. Il client chiede al fornitore di servizi il permesso di richiedere l'accesso per mio conto, che è concesso

  3. Vengo reindirizzato al sito web del fornitore di servizi, dove normalmente inserisco il mio nome utente / password per autorizzare l'accesso

  4. Invece, trapollo / prevengo questa richiesta e salvo il suo URL

  5. In qualche modo ti chiedo di visitare quell'URL. Se hai effettuato l'accesso al fornitore di servizi con il tuo account, verranno utilizzate le tue credenziali per emettere un codice di autorizzazione

  6. Il codice di autorizzazione viene scambiato per un token di accesso

  7. Ora l'account mio sul client è autorizzato ad accedere al tuo account sul fornitore di servizi

Quindi, come possiamo impedirlo utilizzando il parametro state ?

Prevenzione

  1. Il client dovrebbe creare un valore basato in qualche modo sull'account dell'utente originale (un hash della chiave di sessione dell'utente, ad esempio). Non importa cosa sia finché è unique e generato utilizzando alcune informazioni private sull'utente originale.

  2. Questo valore viene passato al fornitore di servizi nel reindirizzamento dal passaggio tre sopra

  3. Ora ti faccio visitare l'URL che ho salvato (passaggio cinque sopra)

  4. Il codice di autorizzazione viene emesso e inviato al client in tua sessione insieme al parametro state

  5. Il client genera un valore state basato su tue informazioni sulla sessione e lo confronta con il valore state che è stato restituito dalla richiesta di autorizzazione al fornitore di servizi. Questo valore non corrisponde al parametro state sulla richiesta, poiché il valore state è stato generato in base alle informazioni della sessione my , quindi viene rifiutato.

Le tue domande

  • Lo stato generato casualmente deve essere sottoposto a hash o lo stesso valore può essere memorizzato e inviato al provider OAuth2?

Il punto è che l'utente malintenzionato non dovrebbe essere in grado di generare un valore di stato specifico per un determinato utente. Dovrebbe essere incurabile.

  • C'è una differenza qui, se il back-end di sessione è sicuro-cookie o una memoria sul lato server (in GAE Memcache o nel database)?

Non penso che questo sia importante (se ti capisco bene)

  • Lo stato dovrebbe essere memorizzato come una chiave come suggerito?

Non so cosa significhi.

  • Lo stato dovrebbe avere un periodo di validità o la sessione (se ce n'è una) è sufficiente?

Sì, lo stato dovrebbe avere una scadenza. Non necessariamente deve essere legato alla sessione, ma potrebbe essere.

    
risposta data 13.05.2014 - 20:32
fonte
2

Tratto da L'importanza del parametro state in OAuth2 :

È qui che entra in gioco l'oggetto "stato" in OAuth 2. Inviando sempre uno stato non ipotizzabile durante il POST all'endpoint di autorizzazione, l'applicazione client può essere certa che il codice di accesso ottenuto dal server di autorizzazione sia in risposta alle richieste fatte da esso piuttosto che da qualche altra applicazione client.

Esempio:

https://example.com/as/authorization?client_id=client1&response_type=code&scope=openid &state=7tvPJiv8StrAqo9IQE9xsJaDso4

Affinché il parametro di stato sia utile per prevenire attacchi CSRF come questo, tutte le richieste fatte al server OAuth devono includere un parametro di stato che il client può utilizzare per autenticarsi. Quando si invia un parametro di stato, le specifiche OAuth stabiliscono che il server di autorizzazione deve restituirlo verbatim al client. Questo verrà fatto attaccandolo sull'URL di call-back del cliente. Il client deve ricevere questo stato ed essere programmato per accettare solo i reindirizzamenti con uno stato verificabile. Se questo è un dizionario tenuto in memoria o un valore ricalcolato spetta al programmatore del client.

Al momento di decidere come implementarlo, un suggerimento è di utilizzare una chiave privata insieme ad alcune variabili facilmente verificabili, ad esempio l'ID client e un cookie di sessione, per calcolare un valore hash. Ciò si tradurrà in un valore di byte che sarà difficile da indovinare senza la chiave privata. Dopo aver calcolato tale HMAC, base-64 lo codifica e lo passa al server OAuth come parametro di stato. Un altro suggerimento è quello di hash la data e l'ora corrente. Ciò richiede che l'applicazione salvi il tempo di trasmissione per verificarlo o per consentire un periodo di validità scorrevole (ad esempio, utilizzando TOTP).

Hers è un semplice esempio di Python che usa il secondo suggerimento usando datetime:

def generate_state_parameter(client_id, private_key):
    date = datetime.datetime.today()
    raw_state = str(date) + client_id
    hashed = hmac.new(private_key, raw_state, sha1) state = base64.b64encode(hashed.digest())
    return (state, date)
    
risposta data 06.10.2016 - 12:16
fonte

Leggi altre domande sui tag