hanakoa / alpaca

Containerized Go µServices for authentication and authorization.
https://hanakoa.github.io/alpaca/
MIT License
5 stars 0 forks source link

Password hash comparison is insecure and vulnerable to timing attacks #76

Open kevinmichaelchen opened 5 years ago

kevinmichaelchen commented 5 years ago

TL;DR This function is insecure

func MatchesHash(passwordText string, password *Password) bool {
    hash := GenerateHash(passwordText, int(password.IterationCount), password.Salt)
    return hex.EncodeToString(password.PasswordHash) == hex.EncodeToString(hash)
}

Why?

The timing of the string comparison is vulnerable to timing attacks. The response time reveals how many consecutive bytes match before a byte isn't found.

Someone who can tell how long it takes to compare the strings can make a good guess where the first difference is. In an attack scenario, an attacker has total control of $mac1 (it's taken from the attacker-made message), while $mac2 is the real valid MAC for the attacker's message. $mac2 must remain secret from the attacker, or he can stick it on his message and thus forge a valid message. The attacker, by analyzing the time it takes to get a response, can probably figure out where the first difference is between his MAC and the real one. He can try all possibilities for that one byte, find the correct one, and then work on the next byte secure in the knowledge that the first k bytes are right. At the end, he tried just 256*len MACs (if len is the length of the MAC) instead of the 256^len he should have had to try.

Solution

See https://stackoverflow.com/questions/20663468/secure-compare-of-strings-in-go