Hello,
One of our customers ran a penetration tests on our platform which uses Keycloak as
Identity & Access Management system.
The penetration result was good except a medium issue that could result a large discovery
of usernames.
Let me explain the steps to reproduce this:
1. Login to the system with valid credentials
2. Copy the execution parameter [%EXECUTION%] from the POST authenticate HTTP request
https://%KEYCLOAK%/auth/realms/%REALM%/login-actions/authenticate?code=%CODE%&execution=%EXECUTION%&client_id=%CLIENT_ID%
3. Copy the AUTH_SESSION_ID cookie [%AUTH_SESSION_ID%] from the POST authenticate HTTP
request
4. Execute the POST authenticate HTTP request again with the execution parameter
%EXECUTION% and AUTH_SESSION_ID cookie %AUTH_SESSION_ID%
POST
/auth/realms/%REALM%/login-actions/authenticate?code=%CODE%&execution=%EXECUTION%&client_id=%CLIENT_ID%
HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cookie: AUTH_SESSION_ID=%AUTH_SESSION_ID%
Cache-Control: no-cache
Body: username=%USERNAME%&password=123&login=Log+in
5. From the HTML response (Invalid username or password) extract the code %CODE% (because
unique) from the form action
<div id="kc-form" class="col-xs-12 col-sm-12 col-md-12 col-lg-12
login">
<div id="kc-form-wrapper" class="">
<form id="kc-form-login" class="form-horizontal"
action="https://%KEYCLOAK/auth/realms/%REALM%/login-actions/authenticate?code=%CODE%&execution=%EXECUTION&client_id=%CLIENT_ID%"
method="post">
<div class="form-group">
<div class="col-xs-12 col-sm-12 col-md-4
col-lg-3">
<label for="username"
class="control-label">Username</label>
6. Replay the step 4 and 5 and change the username in the body part.
We can then distinguish a pattern:
- Screenshot:
https://imgur.com/a/pwtPH
If the user is an existing username, the response time 3 - 4 time longer than if the user
doesn't existing (whatever the password). So with this method I could enumerate all
the usernames in the system using a dictionary and a brute force attack.
The Keycloak Brute Force Attack detection doesn't prevent this as it only locks out
user for a given username.
Ideal solution:
If Keycloak could prevent this behaviour by making sure the elapsed time of computation
for login in is approximately the same for an existing or non-existing user.
Alternative Solutions:
Alternative solution is to use fail2ban to block an IP when this kind of behaviour is
detected.
Thanks.
Gregoire Jeanmart