Potential timing attack vulnerability in django-basic-auth-ip-whitelist username and password validation
- Date: 2020-04-20
- Project: django-basic-auth-ip-whitelist
- Vulnerability: Timing attack (side-channel attack)
- Severity: based on similar vulnerabilities this would be a Moderate severity, 3.7 CVSS score
Vulnerable code: baipw/utils.py#L66
def authorize(request, configured_username, configured_password):
# [...]
if username == configured_username and password == configured_password:
return True
Timing attacks rely on observing the time it takes for a given auth check to complete. If the time varies depending on how "close" the auth check is to succeeding, then an attacker can measure this time difference to determine what the auth details are.
This implementation is vulnerable to a timing attack in two ways:
- String comparison is done character-by-character in Python, so the program will take longer to execute the closer the submitted login/password is to the configured login/password.
- The
and
operator short-circuits in Python. This only allows determining that the login is correct, so relatively minor compared to the non-constant-time string comparison.
From my understanding timing attacks are meant to be somewhere between hard and impossible under real-world circumstances "over the internet", where the timing difference signal gets lost in the noise of too many other factors. However this might not be a problem for more sophisticated attacks using statistical models / started from the same data centre. As far as I understand timing attacks are confirmed to be possible over a local network.
The fix is to make sure the auth check takes a constant time regardless of what input is provided,
- Use a constant-time string comparison function such as
hmac.compare_digest
- Use a Django wrapper around that function such as django.utils.crypto.constant_time_compare
- Use a "and" operator that doesn’t short-circuit (bitwise
&
?)
- Rails basic auth username and password
- express-basic-auth username and password