Loading...
Loading...
Stored input is later used unsafely in a different query context.
1def register(username, password):2 # Input is safely parameterized here3 cursor.execute(4 "INSERT INTO users (username, password) VALUES (?, ?)",5 (username, password)6 )78def change_password(username, new_password):9 # But username from DB is used unsafely later!10 cursor.execute(11 f"UPDATE users SET password = '{new_password}' WHERE username = '{username}'"12 )
Second-order SQL injection occurs when malicious input is stored safely but later retrieved and used unsafely. Always use parameterized queries even for data that "should be safe" from your own database.
Attacker registers with malicious username to later compromise admin
Step 1: Register as "admin'--"
Step 2: Request password change
Step 3: Query becomes: UPDATE users SET password='x' WHERE username='admin'--'✓ Stored payload activates in different context
✓ Admin password changed to attacker's choice
✓ Full admin account takeover