Issue 2551171
Created on 2021-11-24 22:36 by rouilj, last changed 2022-05-12 02:51 by rouilj.
Messages | |||
---|---|---|---|
msg7371 | Author: [hidden] (rouilj) | Date: 2021-11-24 22:36 | |
Somebody asked if Roundup supported Have I been Powned (https://haveibeenpwned.com/) using the password API: https://haveibeenpwned.com/API/v3 It doesn't but along the lines of https://wiki.roundup-tracker.org/TestPasswordComplexity a similar mechanism can use: https://pypi.org/project/pyhibp/ to get a password check. Also adding support for specifying an API key (https://haveibeenpwned.com/API/Key) in: detectors/config.ini for the tracker allows use of checks for the email address(es) of the user that can be done in a detector. |
|||
msg7425 | Author: [hidden] (rouilj) | Date: 2021-12-21 01:06 | |
Adding this function allows checking the entered password for exposure on have I been powned. import hashlib import requests from roundup.exceptions import Reject def check_pw_hibp(password, mode="change"): # encode to unicode string and return a hex encoded sha1 hash pwhash = hashlib.sha1(password.encode()).hexdigest() # search hibp using the first 5 hash characters try: rqst = requests.get('https://api.pwnedpasswords.com/range/' + pwhash[:5], timeout=2.5) # timeout 2.5 seconds except requests.exceptions.Timeout: return False # don't let API failure stop login or change # turn string like FA31ED547EE63D61B812DABE2F37D2AAFE2:2\r\n<another hash> # into list element of FA31ED547EE63D61B812DABE2F37D2AAFE2 res_hash_list = [ x.split(':')[0] for x in rqst.text.split('\r\n') ] # hibp returns hash residual after removing first 5 requested chars # so search for it. if pwhash.upper()[5:] in res_hash_list: if mode == 'change': # reject change of password to the password value raise Reject("Password has been exposed on have i been powned. ") elif mode == "login": # Evaluates to true - have been found on hibp. Allow # the user to login (and change password) but provide an error message. return "Warning password has been exposed on have i been powned. Change password" return False # false == not found in hibp Using the technique in: https://wiki.roundup-tracker.org/TestPasswordComplexity and calling this with mode="change" allows you to check it when it gets changed. You can put this in the login flow using the technique in: https://wiki.roundup-tracker.org/LoginWithEmail so the password is checked for exposure on every login. Use code like: r = check_pw_hibp(self.form['__login_password'].value) if r: self.client.add_error_message(r) in the login action wrapper. Probably checking in both places is a good idea. One makes sure the user isn't starting off with an exposed password and the other verifies that it is still unexposed. I put this on the wiki as well. https://wiki.roundup-tracker.org/CheckForExposedPasswordHIBP |
|||
msg7515 | Author: [hidden] (rouilj) | Date: 2022-05-12 02:51 | |
Since this is documented on the wiki, I consider it done. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-05-12 02:51:25 | rouilj | set | priority: normal assignee: rouilj messages: + msg7515 status: new -> closed resolution: fixed |
2021-12-21 01:06:58 | rouilj | set | messages: + msg7425 |
2021-11-24 22:36:58 | rouilj | create |