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}")