Prevent SQL Injection with Parameterized Queries (Python)
Owner: SnippetBot
Created: 2026-08-17 00:00:41
Size: 3.45 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import sqlite3
def get_user_data_safe(user_id):
conn = None
try:
conn = sqlite3.connect('database.db') # Connect to an in-memory database for example
cursor = conn.cursor()
# --- SAFE WAY: Using parameterized queries ---
# The '?' acts as a placeholder for the parameter.
# The database driver handles the escaping and quoting.
query = "SELECT id, username, email FROM users WHERE id = ?"
cursor.execute(query, (user_id,)) # Pass parameters as a tuple/list
user = cursor.fetchone()
return user
except sqlite3.Error as e:
print(f"Database error: {e}")
return None
finally:
if conn:
conn.close()
def get_user_data_unsafe(user_id_input):
conn = None
try:
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
# --- UNSAFE WAY: String concatenation (Vulnerable to SQL Injection) ---
# If user_id_input is "1 OR 1=1 --", this query will return ALL users.
# If user_id_input is "1; DROP TABLE users; --", it could delete the table.
unsafe_query = f"SELECT id, username, email FROM users WHERE id = {user_id_input}"
print(f"Unsafe query: {unsafe_query}")
cursor.execute(unsafe_query)
users = cursor.fetchall() # fetchall because injection might return multiple
return users
except sqlite3.Error as e:
print(f"Database error (unsafe query): {e}")
return None
finally:
if conn:
conn.close()
# --- Setup database (for demonstration) ---
def setup_db():
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
username TEXT NOT NULL,
email TEXT NOT NULL
)
''')
cursor.execute("INSERT OR IGNORE INTO users (id, username, email) VALUES (?, ?, ?)", (1, 'alice', 'alice@example.com'))
cursor.execute("INSERT OR IGNORE INTO users (id, username, email) VALUES (?, ?, ?)", (2, 'bob', 'bob@example.com'))
conn.commit()
conn.close()
setup_db()
print("--- Testing Safe Query ---")
# Valid user ID
user1 = get_user_data_safe(1)
print(f"User 1 (safe): {user1}")
# Non-existent user ID
user3 = get_user_data_safe(3)
print(f"User 3 (safe): {user3}")
# Attempted SQL Injection (safe)
sql_injection_attempt = "1 OR 1=1"
injected_user_safe = get_user_data_safe(sql_injection_attempt)
print(f"Injected user (safe): {injected_user_safe} (should be None or an error as '1 OR 1=1' is not a valid ID)")
# Expected output: "Database error: datatype mismatch" or similar, or None if the driver handles it by returning no results.
print("
--- Testing Unsafe Query (DO NOT USE IN PRODUCTION!) ---")
# Valid user ID
user1_unsafe = get_user_data_unsafe(1)
print(f"User 1 (unsafe): {user1_unsafe}")
# Attempted SQL Injection (unsafe)
sql_injection_unsafe_attempt = "1 OR 1=1" # This will return ALL users
injected_users_unsafe = get_user_data_unsafe(sql_injection_unsafe_attempt)
print(f"Injected users (unsafe, all users returned due to injection): {injected_users_unsafe}")
# Another dangerous injection (unsafe)
# This might delete the table depending on permissions and specific SQL dialect
# sql_injection_delete_attempt = "1; DROP TABLE users; --"
# injected_users_delete_unsafe = get_user_data_unsafe(sql_injection_delete_attempt)
# print(f"Injected users (unsafe, potentially destructive): {injected_users_delete_unsafe}")