I've written a little bottle web app to run on my raspberry pi and control a boiler. There is a log in page and a create new user page. When I create a new user it generates a salt and uses sha512 to hash the password and both are stored in the database. When a user logs in it matches the userid's and gets the salt and password hash from the database and hashes the presented password with the salt from the database but always creates a different hash so the log in fails. I'm sure its something stupid but I just can't sort it.
This is the code that does the password hashing/checking/salt
def get_password(userid):
userid = userid.upper()
logging.debug('get password for %s' % userid)
conn_string = prop('database')
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()
sql = """
select password, salt from users where userid = %(userid)s
"""
cursor.execute(sql, {'userid':userid})
row = cursor.fetchone()
if row is not None:
dbpassword = row[0]
dbsalt = str(row[1])
logging.debug('db password hash %s' % dbpassword)
logging.debug('db password salt %s' % dbsalt)
return dbpassword, dbsalt
else:
logging.debug('No details found for user')
return None, None
def check_password(password, userid):
logging.debug('username/password to check is %s/%s' % (password, userid))
dbpassword, dbsalt = get_password(userid)
if dbpassword is not None:
test = hash_password(password, dbsalt)
logging.debug('test password hash %s' % test)
if test == dbpassword:
logging.debug('password correct')
return True
else:
logging.debug('password incorrect')
return False
else:
return False
def hash_password(password, salt):
if salt == '0':
logging.debug('hashing password')
logging.debug('generate salt')
salt = uuid.uuid4().hex
logging.debug('salt = %s' % salt)
hashed_password = crypt(password, salt)
logging.debug('hashed password = %s' % hashed_password)
return salt, hashed_password
else:
logging.debug('hash password for compare')
hashed_password = crypt(password, salt)
logging.debug('hashed password = %s' % hashed_password)
return hashed_password
def crypt(password, salt):
hashed_password = hashlib.sha512(password.encode(encoding='utf_8') + salt.encode(encoding='utf_8')).hexdigest()
return hashed_password
and this is the bit that gets the details from the login page:
def main():
try:
rqstSession = request.get_cookie('pysessionid', secret=prop('cookieSecret'))
username = request.forms.get('username').upper()
password = request.forms.get('password')
if request.forms.get('override','').strip() is '':
if check_password(password, username) is True:
set_session(rqstSession)
return template('main')
elif check_session(rqstSession) is True:
if request.forms.get('override','').strip():
logging.debug('override')
set_override()
return template('main')
else:
return template('login')
except Exception as e:
logging.debug('exception in main: %s' % e)
return '<p>Error</p>'
and this gets the details from the new user page:
def new_user():
try:
rqstSession = request.get_cookie('pysessionid', secret=prop('cookieSecret'))
if check_session(rqstSession) is True:
if request.forms.get('save','').strip():
userid = request.forms.get('userid', '').upper()
password = request.forms.get('password','')
confpassword = request.forms.get('confpassword','')
salt = '0'
if password is not '' and password == confpassword and userid is not '':
salt, hashed_password = hash_password(userid, salt)
conn_string = prop('database')
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()
sql = """
insert into users (id_usrr, userid, password, salt) values (nextval('users_id_usrr_seq'), %(userid)s, %(password)s, %(salt)s)
"""
cursor.execute(sql, {'userid':userid, 'password':hashed_password, 'salt':salt})
conn.commit()
cursor.close()
else:
return template('newuser')
else:
return template('newuser')
else:
pysessionid = ''
response.set_cookie('pysessionid', pysessionid, secret=prop('cookieSecret'), Expires='Thu, 01-Jan-1970 00:00:10 GMT', httponly=True)
return template('main')
except Exception as e:
logging.debug(e)
return '<p>Error</p>'
I tried removing the salt and it didn't help so I don't think its anything to do with that but I'm willing to try anything after bang my head against a wall for the last 2 hours
Thanks
Adam
I don't know a lot about security but i think that can solve your problem
>>> # import the hash algorithm
>>> from passlib.hash import sha256_crypt
>>> # generate new salt, and hash a password
>>> hash = sha256_crypt.encrypt("toomanysecrets")
>>> hash
'$5$rounds=80000$zvpXD3gCkrt7tw.1$QqeTSolNHEfgryc5oMgiq1o8qCEAcmye3FoMSuvgToC'
>>> # verifying the password
>>> sha256_crypt.verify("toomanysecrets", hash)
True
>>> sha256_crypt.verify("joshua", hash)
False
so something like:
if sha256_crypt.verify("given_pass", db_hash):
print("you are now logged in")
passlib
Related
I have been trying to set an account attribute for an Active Directory user but this one attribute cannot be applied the same way as other account attributes (ACE type), im applying the other attributes but "User cannot change password" is the one attribute im unable to do with python programmatically.
This is the code im using to set the password in AD and set attributes for "Password never expires" and "Store password using reversable encyption"
My sources for the code came from here: https://blog.steamsprocket.org.uk/2011/07/04/user-cannot-change-password-using-python/
Someone else other attempt was here but i'm unable to apply it:https://web.archive.org/web/20150829114442/http://www.robertmeany.com/programming/python-and-the-active-directory-security_descriptor/
Hopefully someone may be able to assist me, thank you.
import ldap3
from ldap3 import Connection,Server,ALL,SUBTREE,MODIFY_REPLACE
zid = input("username: ")
zid = str(zid).lower()
print(f'Searching for {zid}')
server = Server('ldaps://IP_OF_MY_AD_SERVER', use_ssl=True, get_info=all)
conn = Connection(server, user='DOMAIN\\USERNAME', password='password', auto_bind=True)
conn.bind()
Path_Root = "DC=domain,DC=Wan"
Filter = f'(&(objectclass=user)(&(sAMAccountName={zid})(!(objectclass=computer))))'
conn.search(search_base = Path_Root,
search_filter = Filter,
search_scope = SUBTREE,
attributes = ["cn", "sAMAccountName", "displayName"]
)
if len(conn.entries) == 1:
USER_DN = conn.response[0].get("dn")
print(USER_DN)
try:
new_password = "A__PASSWORD22"
print(new_password)
print("New password successfully applied")
except:
print("New password could not be applied")
#setting the password:
try:
res = ldap3.extend.microsoft.modifyPassword.ad_modify_password(conn, USER_DN, new_password, old_password=None, controls=None)
res = conn.extend.microsoft.modify_password(USER_DN, new_password)
changeUACattribute = {'userAccountControl': [('MODIFY_REPLACE', 66236)]}
conn.modify(USER_DN, changes=changeUACattribute)
print(conn.result)
print(res)
if res:
print('user %s change password Success.')
print('password: %s' %new_password)
else:
print('user %s change password Failed.')
except Exception as e:
print(f'Error setting AD password: {e}')
This is the code im trying to apply the nTSecurityDescriptor:
import win32security
import win32com.client as win32
domains = ["FQDN","IP_OF_DOMAIN"]
username = "DOMAIN\\USERNAME"
print(username)
password = input("Password: ")
print ("AUTHENTICATING ACCOUNT...")
for d in domains:
try:
token = win32security.LogonUser(
username,
d,
password,
win32security.LOGON32_LOGON_NEW_CREDENTIALS,
win32security.LOGON32_PROVIDER_DEFAULT)
authenticated = True
token.Close()
break
except:
authenticated = False
if (authenticated):
print ("VALID ACCOUNT!")
else:
print ("Wrong username or password!")
authenticated = bool(token)
ChangePasswordGuid = '{ab721a53-1e2f-11d0-9819-00aa0040529b}'
ADS_ACETYPE_ACCESS_DENIED_OBJECT = 0x6
SID_SELF = "S-1-5-10"
SID_EVERYONE = "S-1-1-0"
selfAccount = win32security.LookupAccountSid(None,
win32security.GetBinarySid(SID_SELF))
everyoneAccount = win32security.LookupAccountSid(None,
win32security.GetBinarySid(SID_EVERYONE))
selfName = ("%s\\%s" % (selfAccount[1], selfAccount[0])).strip('\\')
everyoneName = ("%s\\%s" % (everyoneAccount[1], everyoneAccount[0])).strip('\\')
print(USER_DN)
location = USER_DN
user = win32.GetObject("ldap://cn=%s,%s" % (zid, location))
print(user)
sd = user.nTSecurityDescriptor
dacl = sd.DiscretionaryAcl
for ace in dacl:
if ace.ObjectType.lower() == ChangePasswordGuid.lower():
if ace.Trustee == selfName or ace.Trustee == everyoneName:
ace.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT
sd.DiscretionaryAcl = dacl
user.Put('ntSecurityDescriptor', sd)
user.SetInfo()
The Error:
sd = USER_DN.nTSecurityDescriptor
AttributeError: 'str' object has no attribute 'nTSecurityDescriptor'
I am trying to fetch password from Mysql database using WHERE clause in Python and storing the password in a variable "DbPassword" but when I am printing the "DbPassword" it prints "None"
can anyone explain why this is happening and how can I solve this?
Thank you I have attached a ScreenShot of my IDE where the entire function and Output can be seen
def searchdb(self):
User = (self.Username.get())
pas = (self.Password.get())
myconn = mysql.connector.connect(host = "localhost", user = "root", passwd = "qwerty321", database = "admin")
if len(User) == 0 and len(pas) == 0 :
tkinter.messagebox.showinfo("Pharmacy Management System","Please fill in the Login Details")
elif len(User) == 0 and len(pas) != 0 :
tkinter.messagebox.showinfo("Pharmacy Management System","Please Enter a Username")
elif len(User) != 0 and len(pas) == 0:
tkinter.messagebox.showinfo("Pharmacy Management System","Please enter a Password")
else:
try:
#seacrch data
#print("%s\n%s"%(User,pas) )
sql = "SELECT password FROM users WHERE user_name = '%s'"
cur = myconn.cursor()
cur.execute(sql,(User))
DbPassword = cur.fetchone()
print("%s"%(DbPassword))
if (pas == str(DbPassword)) :
self.btnRegistration.config(state=NORMAL)
self.btnHospital.config(state=NORMAL)
else:
tkinter.messagebox.askokcancel("Pharmacy Management System","You have entered an invalid login details")
self.btnRegistration.config(state=DISABLED)
self.btnHospital.config(state=DISABLED)
self.Username.set("")
self.Password.set("")
self.txtUsername.focus()
except Error as e:
# tkinter.messagebox.showinfo("Pharmacy Management System","NO RECORD FOUND !")
myconn.rollback()
Window1.Reset(self)
myconn.close()
Finally got the answer made some changes
modified:
sql = "SELECT password FROM users WHERE user_name = '%s'" cur.execute(sql,(User))
to :
sql = "SELECT password FROM users WHERE email= '"+ self.Username.get() +"'"
cur.execute(sql)
and it is working as expected.
cur = conn.cursor()
result = cur.execute("SELECT * FROM users WHERE username = %s", [username])
if result > 0:
data = cur.fetchone()
password = data['password']
if sha256_crypt.verify(password_given, password):
app.logger.info('PASSWORD MATCHED')
else:
app.logger.info('PASSWORD Not MATCHED')
this is the actual code am using. i think the error is coming from variable 'result', i want it to get the stored password as dictionary.
cur.execute() doesn't return the result: you have to get the result using cur.fetchone(). If no result is found it will return None, otherwise it will return the tuple, or the dict, according to the cursor class used:
cur = conn.cursor()
cur.execute("SELECT * FROM users WHERE username = %s", [username])
data = cur.fetchone()
if data:
password = data['password']
Put single quote around %s Because username is a String
result = cur.execute("SELECT * FROM users WHERE username = '%s'"%str(username))
if result.rowcount >0
Corretion
cur = conn.cursor()
result = cur.execute("SELECT * FROM users WHERE username = %s", [username])
data = cur.fetchone()
if result.rowcount > 0:
password = data['password']
if sha256_crypt.verify(password_given, password):
app.logger.info('PASSWORD MATCHED')
else:
app.logger.info('PASSWORD Not MATCHED')
I have tried to create a user account in LDAP. Sample code to connect the LDAP
conn = ldap.initialize(bind_url) # Connect LDAP service
conn.set_option(ldap.OPT_REFERRALS, 0)
conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
conn.set_option(ldap.OPT_DEBUG_LEVEL, 255)
conn.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND)
conn.protocol_version = ldap.VERSION3 # Default version for LDAP protocol used
conn.set_option(ldap.OPT_REFERRALS, 0)
ldap_user = "CN=%s,%s" % (bind_username, base_dn)
conn.simple_bind_s(ldap_user, bind_password) # Authentication occurs
I can able to connect to LDAP and create a user in disable mode (UserAccountControl == 514). When i tried to set password or enable account. There will be error like
"{'info': '0000001F: SvcErr: DSID-031A12D2, problem 5003 (WILL_NOT_PERFORM), data 0\n', 'desc': 'Server is unwilling to perform'}"
I am usin python-ldap library. Here is my sample code to add and enable user account
user_attrs['objectclass'] = ['top', 'person', 'organizationalPerson', 'user']
user_attrs['cn'] = username
user_attrs['givenName'] = username
user_attrs['sn'] = username
user_attrs['displayName'] = username
user_attrs['userAccountControl'] = '514'
user_attrs['mail'] = str(user["email"])
user_attrs['department'] = str(user["department"])
user_ldif = modlist.addModlist(user_attrs)
add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password])]
# 512 will set user account to enabled
mod_acct = [(ldap.MOD_REPLACE, 'userAccountControl', '512')]
# Add the new user account
try:
ldap_connection.add_s(user_dn, user_ldif)
except ldap.LDAPError, error_message:
print "Error adding new user: %s" % error_message
return False
# Add the password
try:
ldap_connection.modify_s(user_dn, add_pass)
except ldap.LDAPError, error_message:
print "Error setting password: %s" % error_message
return False
# Change the account back to enabled
try:
ldap_connection.modify_s(user_dn, mod_acct)
except ldap.LDAPError, error_message:
print "Error enabling user: %s" % error_message
return False
print "User created %s" % username
Anyone please let me know if there any solution or fix.
My ldap.conf in ubuntu:
TLS_CACERT /etc/ssl/certs/ca-certificates.crt
I found the following blog post to be very helpful in this regard.
http://marcitland.blogspot.com/2011/02/python-active-directory-linux.html
Looks like what you need is as follows:
unicode_pass = unicode('\"' + password + '\"', UNICODE_STANDARD)
password_value = unicode_pass.encode(UNICODE_ENCODING)
add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password_value])]
We use multiple sets of predefined passwords here for test servers - I would like to try a portable Python SSH library (like the one below - spur.py) and get it to try each one in succession - but obviously stop when it is successfully connected or if it can't - ask me for a password. I'm after some sort of recursion with the exception handling I think.
def ssh_connection(user, host):
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password="abc123",
private_key_file= expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
print error
raise
Coming from the Java world I'd check if the object is null and iterate through a list until the end and then ask for a password. I can't see how to do it in Python... Here's an example I found for the list part:
passwords = ['abc123', 'abc456', 'abc789']
for password in passwords: # Second Example
print 'trying password :', password
As Joe mentioned in the comments you can do something similar:
def ssh_connection(user, host, passwords):
err = None
for password in passwords:
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password=password,
private_key_file= expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
err = error
if err:
raise error
I would cut it in 2 different functions:
def ssh_connection(user, host, password):
"""
try to connect to user:password#host
return None if failed
"""
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password=password,
private_key_file=expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
print error
return
def try_connection(user, host, passwords):
"""
try all password in passwords to connect to host
if all failed, ask for password via stdin
"""
for password in passwords:
conn = ssh_connection(user, host, password)
if not conn is None:
break
else:
# we never hit the break: ask for passwd
password = ""
while conn is None:
print "please insert password for %s#%s (empty for exit)" % (user,host)
password = raw_input("passwd:") # todo : insert Term seq for hide passwd and then restor
if password == "":
sys.exit(1)
conn = ssh_connection(user, host, password)
return conn
My comment above got mangled, so here is #Joe Doherty suggestion used with code from Ifthikan - thanks!
def loop_ssh_connection(user, host):
shell = None
passw = ['abc123', 'abc456', 'abc789']
while shell is None:
shell = ssh_connection(user, host, passw)
result = shell.run(["ls", "-l"])
print result.output # prints ouput
def ssh_connection(user, host, passw):
err = None
for password in passw:
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password=password,
private_key_file= expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
err = error
if err:
raise error