Please let me know will following codes 100% prevent SQL injection in python
Sample1
username = request.GET('username') # non-filtered user input
connection.execute("SELECT id,name,email FROM user WHERE username=%s LIMIT 1", (username,))
Sample2
username = request.POST('username') # non-filtered user input
name = request.POST('name') # non-filtered user input
email = request.POST('email') # non-filtered user input
connection.execute("UPDATE user SET name=%s, email= %s WHERE username=%s LIMIT 1", (name, email, username,))
The concept of the %s is to isolate the data from the query. When you pass two arguments, they are combined in the module. It is intended to mitigate injection, but I'd be hesitant to say "100%"
Edit: many wiser than myself (maybe even real life security experts!) have weighed in here:
https://security.stackexchange.com/questions/15214/are-prepared-statements-100-safe-against-sql-injection
Related
I want to store userid in a variable after the users logged in and I am not sure how to do that. I used getpass.getuser(), but it gives me the username from my computer system. Does session work in tkinter? Can somebody give me an idea how should I approach this?
The user id is increased automatically for new user
class data:
def checks(name, password):
conn = sqlite3.connect('login.db')
cur = conn.cursor()
if cur.execute('SELECT * FROM user WHERE name = ? AND password = ?', (name, password)):
if cur.fetchone():
window.destroy()
login_backend.back()
else:
messagebox.showinfo('error', 'Username and password is wrong')
def login_student(self):
if len(self.namee.get()) == 0 or len(self.password1e.get()) == 0:
messagebox.showinfo("ERROR", "Mandatory Field is empty")
else:
data.checks(self.namee_text.get(), self.password1e_text.get())
Do you want to get a password and user name on the command line? If so, the secure way to do this is with getpass.getpass(). This will prompt the user. getpass.getuser(), as you discovered, is for the system user.
https://docs.python.org/2/library/getpass.html
You don't want to print the password on the command line because of the security risk. Generally, you want to consume the sensitive credentials only as long as needed to access the resource.
I'm pretty new to SQL but I need it for a school project. I'm trying to make a (python) web-app which requires accounts. I'm able to put data into my SQL database but now I need some way to verify if an e-mail (inputted via html form) already exists inside the database. Probably the easiest query ever but I haven't got a single clue on how to get started. :(
I'm sorry if this is a duplicate question but I can't find anything out there that does what I need.
if you are using SQLAlchemy in your project:
#app.route("/check_email")
def check_email():
# get email from you form data
email = request.form.get("email")
# check if someone already register with the email
user = Users.query.filter_by(email=email).first()
if not user:
# the email doesnt exist
pass
else:
# the email exists
pass
Users.query.filter_by(email=email).first() equal to SQL:
SELECT * from users where email="EMAIL_FROM_FORM_DATA"
if you are using pymsql(or something like that):
import pymsql
#app.route("/check_email")
def check_email():
# get email from you form data
email = request.form.get("email")
conn = connect(host='localhost',port=3306,user='',password='',database='essentials')
cs1 = conn.cursor()
params = [email]
# cursor return affected rows
count = cs1.execute('select * from users where email=%s', params) # prevent SqlInject
if count == 0:
# count 0 email
else:
# the email exists
# and if you want to fetch the user's info
user_info = cs1.fetchall() # the user_info should be a tuple
# close the connection
cs1.close()
conn.close()
I was able to solve my issue by simply using
INSERT IGNORE and after that checking if it was ignored with the primary key.
Thank you for everyone that helped out though!
I'm having a problem when trying to verify credentials ( I will post the code below ). I was wondering if it's happening because I stored username and password as a string within the database, should I have stored it as an integer?
The problem: I think it's easier to simply give an example of what the problem is, maybe it's easier to understand.
Information that is correct ( username = something and password = testing )
Example 1: You input "something" as username and "password" as password - that's fine it works, HOWEVER the next example is where things go wrong.
Example 2: You input the username "somethingfpsadadoia" and the password "testing" - the program will say it's correct as long as the password is correct. So as long as you have part of the username under username entry then the password works, but anything after that is not taken in consideration to say it's actually wrong.
Much appreciated if anyone can help !
"""
def Is_Valid():
UsernameValidity=UserName_Entry.get()
PasswordValidity=Password_Entry.get()
cursor.execute('''SELECT password FROM users WHERE username = ?''', (UsernameValidity,))
cursor.execute('''SELECT username FROM users WHERE password = ?''', (PasswordValidity,))
LogInAttempt = cursor.fetchone()
print (Is_Valid) # Testing to see if it works on shell
if LogInAttempt:
print (" One of the accounts have successfully logged in ")
IsValidText.config(text=" You have logged in! ", fg="black", highlightthickness=1)
myGUI.after(1000, CoreContent) # Ignore this one for now.
else:
print (" One of the accounts inputted the wrong credentials! ")
IsValidText.config(text=" Invalid username or Password! ", fg="black", highlightthickness=1)
"""
You are executing two entirely independent queries. The second call to execute throws away any results from the first one; what you fetch from cursor is the result of the second query.
You have to tell the database to check both values when looking at each row:
cursor.execute('SELECT 1 FROM users WHERE username = ? AND password = ?',
[UsernameValidity, PasswordValidity])
LogInAttempt = cursor.fetchone()
I have a database with username and password. I want to search for both these to be matching and if it matches, user can login (and if not error shows).
However the if condition of my code doesn't ever fulfil (even when username and password match).
My SQL query must be wrong, I tried finding a solution to searching for more than one variable in a query but couldn't find an answer that worked for me unfortunately, hence why I've asked.
def userLogin(self):
username, password = self.getUserPass()
con = sql.connect("database.db")
cur = con.cursor()
cur.execute("SELECT * FROM users WHERE (?) AND (?)", (username, password))
if cur.fetchmany(size=1):
print("Username and Password match!")
else:
print("Wrong username and password combination.")
Parameter substitution simply inserts the contents of the given variables into the query. So for user "myuser" and password "mypass", the query you're running is:
SELECT * FROM users WHERE ('myuser') AND ('mypass')
This isn't going to do what you expect because you haven't specified which columns to check. Start by writing a full example query that you could run from an interactive SQLite shell. For example, if your username column is called "user" and your password column is called "pass", your query might be:
SELECT * FROM users WHERE user='myuser' AND pass='mypass'
Then just replace the variable values (including quotes if it's a string) with question marks:
SELECT * FROM users WHERE user=? AND pass=?
Substitute that query into your code and it should act as you expect.
I have a table named 'staff', with several columns, but the two I'm interested in are 'username' and 'password'. I am trying to create a prompt which asks the user for their username (and later I will do password) and checks the table in the database to see if that username exists. I am a bit clueless about how to do this, but this is what I have coded so far.
import MySQLdb
db = MySQLdb.connect(host="127.0.0.1", user="root", passwd="", db="sakila")
cur = db.cursor()
search = raw_input("Enter username: ")
query = ('SELECT username, password FROM staff')
cur.execute(query)
results = cur.fetchall()
if search in results:
print("username found")
else:
print("invalid username")
db.close()
EDIT: Make sure to check the comment from #FallenAngel at the bottom and check for security risks in your code!
As Gordon mentioned, you should use a WHERE clause to make things easier. Like so:
import re
import MySQLdb
db = MySQLdb.connect(host="127.0.0.1", user="root", passwd="", db="sakila")
cur = db.cursor()
search = raw_input("Enter username: ")
user_regex = # input a regex here to make sure the username matches a format which avoids SQL injection.
if re.search(user_regex, search):
query = ("SELECT password FROM staff WHERE username = %s", (search,)) # add a WHERE clause
cur.execute(query)
results = cur.fetchall()
else:
results = None
if results: # Now we just need to check if the queryset is empty or not.
print("username found")
else:
print("invalid username")
db.close()
General rule of thumb is to try and make SQL do the searching for things, it's built for it so will be faster than Python.
Make sure your username column is a primary key (or a unique one at least) so you don't have duplicates.
EDIT: Based on #FallenAngels point, you shouldn't directly inject user input into an SQL query as it would expose you to SQL injection.
EDIT2:
First note that we are no longer using "%s" % var formatting for this solution as it is unsafe! Instead we are using "%s", (var,) formatting which is for db queries.
%s (it can also be %d, %n and a few other letters) in a string is a form of string formatting used to insert variable content into a string.
Essentially if you say:
"some stuff here: %s" % var
Anything that is in var will replace the %s in the string. There are several intricacies so it's worth reading more here: https://docs.python.org/2/library/string.html
Perhaps you need to distribute this in two files
In first file you please build the form and through app.route you link it to the def in python file.
This way you can have your presentation and business model completely separate and that will remain more maintainable as well.
Please let me know if you need more simplification along with the code.