PYTHON

Prevent SQL Injection with Python SQLite Prepared Statements

Learn to use parameterized queries with Python's `sqlite3` module to effectively prevent SQL injection vulnerabilities, ensuring secure database interactions.

import sqlite3

def get_user_data(user_id):
    """
    Fetches user data from the database using a prepared statement.
    Prevents SQL injection.
    """
    db_path = 'users.db'
    conn = None
    try:
        conn = sqlite3.connect(db_path)
        cursor = conn.cursor()

        # Vulnerable approach (DO NOT USE IN PRODUCTION)
        # user_input_id = f"'{user_id}' OR 1=1 --"
        # cursor.execute(f"SELECT id, username, email FROM users WHERE id = {user_input_id}")

        # Secure approach: Using parameterized queries (prepared statements)
        # The database driver handles the escaping of the parameter.
        cursor.execute("SELECT id, username, email FROM users WHERE id = ?", (user_id,))
        
        user = cursor.fetchone()
        return user
    except sqlite3.Error as e:
        print(f"Database error: {e}")
        return None
    finally:
        if conn:
            conn.close()

def create_user_table():
    """Helper function to create a dummy users table and insert some data."""
    db_path = 'users.db'
    conn = None
    try:
        conn = sqlite3.connect(db_path)
        cursor = conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY,
                username TEXT NOT NULL UNIQUE,
                email TEXT NOT NULL
            )
        ''')
        # Insert some dummy data if table is empty
        cursor.execute("INSERT OR IGNORE INTO users (id, username, email) VALUES (1, 'alice', '[email protected]')")
        cursor.execute("INSERT OR IGNORE INTO users (id, username, email) VALUES (2, 'bob', '[email protected]')")
        conn.commit()
    except sqlite3.Error as e:
        print(f"Error creating/populating table: {e}")
    finally:
        if conn:
            conn.close()

if __name__ == "__main__":
    create_user_table()

    # Example of secure usage
    print("--- Secure Query ---")
    retrieved_user = get_user_data(1)
    if retrieved_user:
        print(f"Found user: {retrieved_user}")
    else:
        print("User not found or error occurred.")

    # Example of attempting SQL injection (will be safely handled by prepared statement)
    print("
--- Attempted SQL Injection (prevented) ---")
    malicious_id = "1 OR 1=1 --" # This would return all users in a vulnerable query
    retrieved_malicious_user = get_user_data(malicious_id)
    if retrieved_malicious_user:
        print(f"Found user with malicious input: {retrieved_malicious_user}")
    else:
        print("Malicious input safely handled. No user found for that specific string.")

    # A more subtle malicious input that often tricks non-prepared statements
    print("
--- Another SQL Injection Attempt (prevented) ---")
    another_malicious_id = "1; DROP TABLE users; --" # Would drop the table in a vulnerable query
    get_user_data(another_malicious_id) # Just calling it to show it doesn't execute
    
    # Check if table still exists (it should)
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='users';")
    if cursor.fetchone():
        print("Table 'users' still exists after injection attempt (as expected).")
    else:
        print("Table 'users' was dropped! This indicates a vulnerability.")
    conn.close()
How it works: This Python snippet demonstrates how to prevent SQL injection using prepared statements (also known as parameterized queries) with the `sqlite3` module. Instead of directly embedding user input into the SQL query string, placeholders (`?`) are used. The database driver then safely escapes the provided parameters, treating them purely as data rather than executable SQL code, thus neutralizing injection attempts.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs