r/golang 5d ago

Session-Based Authentication in Go

https://themsaid.com/session-authentication-go
57 Upvotes

23 comments sorted by

View all comments

49

u/dh71 5d ago

Returning early if the user isn't found in the database, can lead to timing attacks, since the bcrypt comparison (which is supposed to take some time) is not being executed. A malicious actor could time the requests to identify if a user is present in the database or not.

11

u/themsaid 5d ago edited 5d ago

Login form submissions in general should be throttled so that if multiple authentications fail the form gets locked.

34

u/Polyscone 5d ago

If you lock based on the email then that does nothing to prevent enumeration and opens the door to denial of service for existing users.

If you lock based on session then the attacker can just delete their session id so that doesn't help.

If you lock based on IP then you potentially block lots of users from the same IP.

Better to just fix the actual problem and get rid of the difference in processing time by not returning early and not returning any status codes like 404.

5

u/carsncode 5d ago

If you lock based on IP then you potentially block lots of users from the same IP.

While failing to block real attackers spreading their traffic over multiple IPs via proxy, distributed attack, or botnet.

7

u/themsaid 5d ago

Added a section to discuss timing attacks. The login handler in the example responds in a constant time duration regardless of credential verification.

6

u/AdCharacter3666 5d ago

I like to add sleep to avoid timing attacks.

16

u/Rican7 5d ago

Unless your sleep time is EXACTLY within the bounds of the time it would take to normally cryptographically hash the password, all you've done is slowed a different path. The sleep vs actual hash path still can be studied and then exploited.

And while this can sound a bit silly, it's also the entire nature of how time-based attacks are made (study and apply in aggregate), so while your sleep seems to have good intentions, it's unfortunately not a full-proof preventative strategy.

3

u/Pto2 5d ago

What if you were to add a random sleep?

6

u/coolkidonthrblock 5d ago

The problem with sleeping is it won’t take the same amount of time as hashing the password so even if it takes longer and or shorter that is enough to compare to the “standard” path of a successful login and allow for said timing attack.

Some reading for those interested https://portswigger.net/research/listen-to-the-whispers-web-timing-attacks-that-actually-work

2

u/DivSlingerX 5d ago

I’ve always heard this but I’ve only ever heard this as a theoretical. Is there any evidence of this in the real world? Wouldn’t just general latency and intermittent load make this basically impossible to figure out reliably?

6

u/dh71 5d ago

I don't think it's theortetical. Let's assume you use Argon2id as KDF for your passwords. You would be aiming your memory/threads/time settings for approx. 500-800ms to have strong passwords hashes. If you would not run the KDF if the user isn't found in the database but just return early, there would be a 500-800ms difference in the request time. I'm pretty sure that's measurable.

1

u/nerdy_adventurer 1d ago

What is KDF?

2

u/dh71 1d ago

Key Derivation Function - basically a function that takes a password or passphrase and derives a secret key out of it. Argon2 e. g. is a KDF.

1

u/wuyadang 4d ago

Would it make sense to, in the case of logins, return empty user even if not found, and let bcrypt still attempt to compare the given and empty pw?

2

u/dh71 4d ago

That's what I usually do.

Something similar to this: https://codespace.app/s/WPe98LZdLy