From f7334552e839ef3d0b31a02cda1bd55a156de53c Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Sat, 12 Nov 2022 11:50:04 +0100 Subject: Rename --- docs/chapters/api-attack.tex | 77 -------------------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 docs/chapters/api-attack.tex (limited to 'docs/chapters/api-attack.tex') diff --git a/docs/chapters/api-attack.tex b/docs/chapters/api-attack.tex deleted file mode 100644 index e6a44d1..0000000 --- a/docs/chapters/api-attack.tex +++ /dev/null @@ -1,77 +0,0 @@ -In genere, quando vogliamo tenere traccia del traffico di richieste che vi è dentro una web app (XHR \cite{XHR:1}, loading di immagini, fonts, codice JS) apriamo la "console sviluppatore" che ci dà a disposizione Firefox (o qualsiasi altro browser, come Chrome) e iniziamo a guardare. -Con questa relazione però, vogliamo fare un attacco attraverso un dispositivo mobile, quindi controlleremo il traffico in uscita nella nostra rete per scoprire a quale server la nostra mobile app sta facendo capo. -\newline\newline -Imposteremo tutto il necessario per replicare l'attacco visto nel capitolo precedente: -\begin{itemize} - \item Una REST API con un problema di autorizzazione nell'endpoint degli utenti, il quale non verifica che l'utente loggato è effettivamente il possessore di quella risorsa. La installeremo in un server su internet; - \item Un'applicazione mobile che fa richieste a tale API; - \item Wireshark\cite{WIRESHARK:1} per monitorare la rete. -\end{itemize} - -\section{API} -Nella realtà, come questa API pubblica \cite{REDDIT:1} fa, si espone un endpoint \emph{/api/v1/me/} dove \emph{v1} è la versione dell'API in cui si ritornano i dati per l'utente autenticato. E questa è una buona prassi, un endpoint che si può trovare più o meno in tutte le REST API. - -\textbf{Cosa proveremo a fare noi?} Proprio un'API che fa ciò, niente più e niente meno. Ci limiteremo però solo a controllare che il JWT passato è valido in modo da ritornare i dati dell'utente che noi pensiamo sia stato autorizzato. -\newline\newline -Il codice di questo servizio è presente al link \underline{\url{https://git.dcariotti.me/m6-ie/tree/server}}. -\newline\newline -La parte incriminata è la route qui sotto. Qui non si limita a ritornare la riga utente che corrisponde all'ID utente passato dall'header. - -\begin{lstlisting} -async fn get_user(claims: Claims) -> Result, AppError> { - match User::find_by_id(claims.user_id).await { - Ok(user) => Ok(Json(user)), - Err(_) => Err(AppError::NotFound), - } -} -\end{lstlisting} - -in realtà qui non vi è nessun problema reale di sicurezza. È un API che funziona, ad ogni richiesta infatti controlla se il token è valido - -\begin{lstlisting} -// bearer = variable with token string - -let token_data = decode::(bearer.token(), &KEYS.decoding, &Validation::default()) - .map_err(|_| AppError::InvalidToken)?; -\end{lstlisting} - -infatti il problema sta nell'inizializzazione della codifica/decodifica di JWT, in particolare quando definiamo il secret. - -\begin{lstlisting} -static KEYS: Lazy = Lazy::new(|| { - let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); - Keys::new(secret.as_bytes()) -}); - -impl Keys { - fn new(secret: &[u8]) -> Self { - Self { - encoding: EncodingKey::from_secret(secret), - decoding: DecodingKey::from_secret(secret), - } - } -} -\end{lstlisting} - -E proprio in questo "errore" nel secret che andremo ad attaccare. Useremo un attacco di bruteforcing all'header Authorization per far sì di avere i dati dell'utente con ID che noi vogliamo. - -\subsection{Forcing del secret} -L'Authorization token è qualcosa di pubblico, che possiamo veder ad ogni richiesta HTTP. Il secret no, è usato per fare verificare la firma e rendere valido il token stesso. Quindi useremo un approccio simile a quello impiegato per "forzare" il login di una piattaforma: proveremo per forza bruta tutte le password possibili. -In questo caso proveremo i possibili secret per far sì che la firma sia lo stesso valida. - -Prendendo una lista ben nota di secrets impiegati in servizi in produzione \cite{JWT_SECRETS_LIST:1} useremo il software open-source \textbf{Hashcat} \cite{HASHCAT}. -Per crackare la password usando Hashcat bisogna dare in input il parametro dell'hash type di JWT, il sorgente in cui vi è il token che si vuole crackare e il sorgente in cui vi è la lista dei secrets. - -\begin{lstlisting} -$ hashcat -m 16500 my-secret.dat jwt-secrets-list.dat - -eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMywiZXhwIjoxNjY2Mjk0Nzk2fQ.ay_RPoeTuV4e -lBFqqCdTzF64GPcoEDOlJN2DUAOqwds:hello - -Session..........: hashcat -Status...........: Cracked -Hash.Type........: JWT (JSON Web Token) -Hash.Target......: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIj...AOqwds -\end{lstlisting} - -Qui vediamo come sia riuscito a trovare il secret, ovvero la stringa \emph{hello}. -- cgit v1.2.3-18-g5258