This question already has answers here:
Python SQLite3 SQL Injection Vulnerable Code
(3 answers)
Closed 7 years ago.
I am supposed to look at this chunk of code and decide what parts could be vulnerable to SQL Injection, why and add fixes to them. I have been scanning the code looking for places that have too vague of parameters and such but i am having trouble finding places that could possibly be vulnerable. If anyone can just quickly scan through this code and point out any blatant vulnerabilities that would be great. The program really likes to give error messages when input is given with single quotes. This code is part of a program that tracks activities. There are 3 input fields, username, password and name of activity. Can post more code if anyone wants
#!/usr/bin/python3.4
import readline
import sqlite3
def audit(handle, event, obj=None):
"""Log an audit event."""
if handle[2] is None:
handle[2]=-1;
if obj==None:
handle[0].execute("insert into auditlog(userid, event)"
" values({0}, '{1}')".format(handle[2],event))
else:
handle[0].execute("insert into auditlog(userid, event, object)"
" values({0}, '{1}', {2})".format(str(handle[2]),
event, obj))
if handle[0].lastrowid is None:
"""On error, raise a SystemException"""
handle[1].commit()
handle[1].close()
raise SystemError("Error creating audit log entry.",
handle[2],event,obj)
handle[1].commit()
def register(cursor, connection, username, password):
"""Register a new user and return a connection to the database."""
cursor.execute("insert into user(username, password)"
" values('{0}', '{1}')".format(username, password))
userid=cursor.lastrowid;
if userid>0:
audit((cursor, connection, userid), "registered")
connection.commit()
print("Welcome, new user!")
return (cursor, connection, userid)
"""If the user could not be registered, raise a SystemError."""
audit((cursor, connection, 0),
"registeration error for {0}".format(username))
connection.commit()
connection.close()
raise SystemError("Unknown error registering user",username)
def connect(username, password):
"""Attempt to log in as the specified user."""
connection=sqlite3.connect('timelog.db')
cursor=connection.cursor()
"""The database is created if necessary."""
cursor.execute("create table if not exists user"
"( id integer primary key,"
" username varchar(50) unique not null,"
" password char(40) not null,"
" created datetime default CURRENT_TIMESTAMP,"
" modified datetime default CURRENT_TIMESTAMP"
")")
For example this statement is vulnerable to SQL injection:
cursor.execute("insert into user(username, password)"
" values('{0}', '{1}')".format(username, password))
I could for example enter the username:
test','secret');update user set password='';--
You should use parametrised queries instead. Using SQLLite you can call the sql like this instead:
cmd = "insert into user(username, password values(?, ?)"
curs.execute(cmd, (username, password))
Related
I have a log-in system, and when I enter a special symbol such as ○ I get this error message...
mysql.connector.errors.DatabaseError: 1267 (HY000): Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8mb4_general_ci,COERCIBLE) for operation '='
I think the best way to deal with this is when asking for the users username, reject inputs that are not in latin1_swedish_ci, e.g. alt codes like ☺. How would I do this? Relevant code:
username = input("Enter username")
password = input("Enter password")
insertData = "INSERT INTO users(username, password) VALUES (%s, %s)"
cursor.execute(insertData, [(username), (password)]) #Execute SQL statement
db.commit() #Commit changes
Is this problem coming from an HTML <form> that you control? If so, it probably has (or the browser defaults to)
<form accept-charset="UTF-8">.
Change that to accept only whatever the equivalent of latin1 is. That is, add the following to your form tag:
accept-charset="ISO-8859-1"
I am trying to make a register-login system in Python 3, but when I check if the Email address already exists or not, it always says that it doesn't. I inserted an email and a password in the "users" table and when asked I used that same email address in this script but it still says that it doesn't exist. I have little to none experience in MySQL and thought that this may be a nice project to start with. Thank you.
import cymysql
from getpass import getpass
def get_user_info():
while True:
email = input("Input your Email address (max. 64 chars.): ")
password = getpass("Input a password (max. 64 chars.): ")
if len(email) < 64 and len(password) < 64:
return email, password
def check_account(cur, email, password):
if(cur.execute(f"SELECT * FROM `users` WHERE `Email`='{email}' LIMIT 1")):
print("exist")
else:
print("no exist")
def main():
conn = cymysql.connect(
host='192.168.0.109',
user='root',
passwd='',
db='database'
)
cur = conn.cursor()
email = ''
password = ''
email, password = get_user_info()
check_account(cur, email, password)
cur.close()
conn.close()
if __name__ == '__main__':
main()
Disclaimer: I have yet to use cymysql – any code attached below is untested.
First, note that CyMySQL is a forked project of PyMySQL[1] so I will refer to documentation from PyMySQL.
From pymysql.cursors.Cursor.execute documentation:
execute(query, args=None)
Execute a query
Parameters:
query (str) – Query to execute.
args (tuple, list or dict) – parameters used with query. (optional)
Returns: Number of affected rows
Return type: int
The important thing to consider is the execute function returns: the number of affected rows. A SELECT query will not affect any rows, thus the function will return 0 and your function will print no exist reasonably.
Use fetchone to check that at least one row was returned.
def check_account(cur, email, password):
cur.execute(f"SELECT * FROM `users` WHERE `email`=%s LIMIT 1", (email,))
row = cur.fetchone()
if row:
print("exist")
else:
print("no exist")
(I rewrote your cur.execute call in consideration of my earlier comment.)
I am creating a Flask Application that connects to a locally-hosted MySQL database (Using SQL-Alchemy ORM). When a user creates an account, I have a method is_taken and returns True or False depending on if a user with that username already exists.
Here is the method:
def is_taken(username):
q = session.query(User).filter(User.username == username).first()
return not (q is None)
Although not on a regular basis, the following error occurs at least once a day:
StatementError: (sqlalchemy.exc.InvalidRequestError) Can't reconnect
until invalid transaction is rolled back [SQL: u'SELECT users.uid AS
users_uid, users.username AS users_username, users.fullname AS
users_fullname, users.password AS users_password, users.score AS
users_score, users.totalattempted AS users_totalattempted,
users.totalcorrect AS users_totalcorrect, users.settings AS
users_settings \nFROM users \nWHERE users.username = %s \n LIMIT
%s'] [parameters: [immutabledict({})]]
The error is triggered specifically on:
q = session.query(User).filter(User.username == username).first()
I appreciate the help!
you've had a invalid transaction before executing this query. first of all I suggest you to find the problem of previous query that led to this problem. and for fixing this problem you execute session.rollback() before running the query.
I am creating a simple app in pyramid . While inserting data i am getting db locked error.
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) database is locked [SQL: 'INSERT INTO users (name, email, number) VALUES (?, ?, ?)'] [parameters: ('test', 't#t.com', '123654')]
But first time it inserts the data correctly and on 2nd time it gives this error.
Any idea why this is happening second time ?
Here is my code :
name = request.params['name']
email = request.params['email']
no = request.params['number']
DBSession.add(User(name, email, no))
# Get the new ID and redirect
users = DBSession.query(User).all()
SQLite can only handle 1 concurrent transaction.
Have you tried commit()before performing a query() then close() to end the session?
name = request.params['name']
email = request.params['email']
no = request.params['number']
DBSession.add(User(name, email, no))
# Commit the transaction if complete
DBSession.commit()
# Get the new ID and redirect
users = DBSession.query(User).all()
# Close the session
DBSession.close()
Hey I'm okay with writing to the table, except unable to check of the data is already there and if the data is then don't write the data and print a value saying that it already exists.
Here is what I have so far
def createAccount():
username = raw_input("username: ")
password = raw_input("password: ")
c.execute("INSERT INTO Logindetails(Username, Password) VALUES (?,?)",
(username, password,))
conn.commit()
Thanks if you can help me, its for my coursework and I'm pretty new to all this.
If you change the create table statement to the following, sqlite will know that each username must be unique because you're defining a 'PRIMARY KEY', one that must be unique:
c.execute("""CREATE TABLE LoginDetails
(Username text PRIMARY KEY, Password text)""")
If you then attempt to insert a row into the table with an existing username, an integrity error will occur:
IntegrityError: column username is not unique
You can catch this (and other errors similarly) using a try, except clause as follows (this assumes you're using sqlite3):
try:
c.execute("INSERT INTO Logindetails(Username, Password) VALUES (?,?)",(username, password,))
except sqlite3.IntegrityError:
print("Username already exists!")