Prevention of time-based SQL injection attacks
from django.http import HttpResponse
from django.db import connection
def user_login(request):
username = request.GET['username']
password = request.GET['password']
cursor = connection.cursor()
cursor.execute("SELECT * FROM users WHERE username = '%s' AND password = '%s'" % (username, password))
user = cursor.fetchone()
if user:
return HttpResponse("User logged in.")
else:
return HttpResponse("Invalid credentials.")
The above code represents a view function in Django that handles user login. It takes a username and password from the HTTP GET request and uses these to query the
users
table in the database and fetch the corresponding user.
The vulnerability lies in the way the SQL query is constructed. The code directly uses the username and password from the GET request to create the SQL query. This means that an attacker could manipulate the
username
or
password
parameter in the GET request to inject malicious SQL code.
For instance, an attacker could set the
username
parameter to
' OR '1'='1' AND SLEEP(10)-
and the
- password
parameter to any value. The resulting SQL query would be:
SELECT * FROM users WHERE username = '' OR '1'='1' AND SLEEP(10)-
- ' AND password = 'any_value'
from django.http import HttpResponse
from django.db import connection
def user_login(request):
username = request.GET['username']
password = request.GET['password']
cursor = connection.cursor()
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", [username, password])
user = cursor.fetchone()
if user:
return HttpResponse("User logged in.")
else:
return HttpResponse("Invalid credentials.")
The original code was vulnerable to Time-based SQL Injection. This vulnerability could allow an attacker to inject a SQL command to the server with code to force a delay in the execution of the queries or with a heavy query that generates this time delay. Depending on the time response, it is possible to deduct some information and determine if a vulnerability is present to exploit it.
The fixed code now uses parameterized queries to prevent SQL injection. Instead of formatting the SQL query with user input, it uses placeholders (%s) and passes the user input as parameters to the
execute
method. This method automatically escapes special characters and protects against SQL injection.
The SQL query in the
execute
method now looks like this:
"SELECT * FROM users WHERE username = %s AND password = %s"
. The user input is passed as a list of parameters:
[username, password]
.
This way, even if an attacker tries to inject SQL commands into the 'username' or 'password' fields, the
execute
method will treat them as literal strings, not part of the SQL command.
It's also worth noting that user input should never be trusted. Always validate and sanitize user input before using it in your application. Consider using Django's built-in authentication system which provides a secure way to handle user authentication.