SQL injection

Tip: Choose Save as PDF in the print dialog to download. Use A4 paper size.

SQL injection

Name:
Date:
Class:

Quick Questions

Shade in the A or B circle for each question.

1. A login form builds its query by joining the typed username straight into the SQL text. Which attack does this allow?
A Denial of service
B SQL injection
2. What does a parameterised query do with user input?
A Treats it only as data, never as SQL commands
B Runs it as part of the SQL command
3. Which line is open to SQL injection?
A query = "SELECT * FROM users WHERE name = '" + name + "'"
B query = "SELECT * FROM users WHERE name = ?"
4. An attacker types ' OR '1'='1 into a password box. What is the attacker trying to do?
A Make the website load faster
B Make the WHERE condition always true
5. SQL injection is an example of which idea?
A Code injection: input is run as code
B Interception: data is read on a network

Match the Pairs

Draw a line connecting each item on the left to its match on the right.

Left columnRight column
1' OR '1'='1 AThe user input is joined straight into the SQL string, so an attacker could type extra commands like 1 OR 1=1 and delete every note. Use a parameterised query instead.
2cursor.execute("SELECT * FROM users WHERE name = ?", (name,)) Bcursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
3Code injection happens when a program joins user input straight into a query string, so typed text becomes part of the command Cquery = "SELECT * FROM users WHERE name = '" + name + "'"
4A parameterised query stops SQL injection by sending the command and the input separately DEven though execute is used, the name is still joined into the query text, so it is not parameterised and injected SQL can still run.
5query = "DELETE FROM notes WHERE id = " + user_input EInjected text that makes a login check always true, so the attacker gets in without a password
6cursor.execute("SELECT * FROM users WHERE name = '" + name + "'") FA parameterised query that treats the input only as data, so injected SQL cannot run

Definitions

SQL injection

Fill in the Blanks

Complete each line of code by filling in the missing parts.

1.
q = "SELECT * FROM users WHERE id=" _ uid
2.
name = "x' __ '1'='1"
3.
sql = "SELECT * FROM users WHERE id=_" cur.execute(sql, (uid,))
4.
sql = "SELECT * FROM users WHERE id=?" cur._______(sql, (uid,))
5.
sql = "SELECT * FROM users WHERE id=?" cur.execute(sql, (___,))

Spot the Error

Shade in the letter of the line that contains an error.

Question 1
A name = eval(input("Name: "))
B q = "SELECT * FROM users"
C q += " WHERE name = ?"
D cur.execute(q, (name,))
Question 2
A q = "SELECT * FROM pets"
B q += " WHERE owner = '?'"
C owner = input("Owner: ")
D cur.execute(q, (owner,))
Question 3
A name = input("Name: ")
B q = "SELECT * FROM users"
C q += " WHERE name = " + name
D cur.execute(q, (name,))
E print(cur.fetchall())
Question 4
A q = "SELECT * FROM accounts"
B q += " WHERE email = "
C email = input("Email: ")
D cur.execute(q, (email,))
Question 5
A uid = input("ID: ")
B q = "SELECT * FROM users"
C q += f" WHERE id = {uid}"
D cur.execute(q, (uid,))

Answer Key

SQL injection
Section A: Quick Questions
Q1
B — SQL injection
Q2
A — Treats it only as data, never as SQL commands
Q3
A — query = "SELECT * FROM users WHERE name = '" + name + "'"
Q4
B — Make the WHERE condition always true
Q5
A — Code injection: input is run as code
Section B: Match the Pairs
Q1
' OR '1'='1 → Injected text that makes a login check always true, so the attacker gets in without a password
Q2
cursor.execute("SELECT * FROM users WHERE name = ?", (name,)) → A parameterised query that treats the input only as data, so injected SQL cannot run
Q3
Code injection happens when a program joins user input straight into a query string, so typed text becomes part of the command → query = "SELECT * FROM users WHERE name = '" + name + "'"
Q4
A parameterised query stops SQL injection by sending the command and the input separately → cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
Q5
query = "DELETE FROM notes WHERE id = " + user_input → The user input is joined straight into the SQL string, so an attacker could type extra commands like 1 OR 1=1 and delete every note. Use a parameterised query instead.
Q6
cursor.execute("SELECT * FROM users WHERE name = '" + name + "'") → Even though execute is used, the name is still joined into the query text, so it is not parameterised and injected SQL can still run.
Section C: Definitions
Q1
SQL injection — An attack where SQL commands typed into an input box run because the program joins the input straight into a query. Parameterised queries stop it by treating input only as data.
Section D: Fill in the Blanks
Q1
q = "SELECT * FROM users WHERE id=" + uid
Q2
name = "x' OR '1'='1"
Q3
sql = "SELECT * FROM users WHERE id=?" cur.execute(sql, (uid,))
Q4
sql = "SELECT * FROM users WHERE id=?" cur.execute(sql, (uid,))
Q5
sql = "SELECT * FROM users WHERE id=?" cur.execute(sql, (uid,))
Section E: Spot the Error
Q1
A — eval() runs whatever the user types as Python code, which is code injection. input() already gives plain text that the parameterised query can treat as data. It should be name = input("Name: ").
Q2
B — Putting quotes around the ? turns it into the literal text '?', so no value is bound. The placeholder must stand alone: WHERE owner = ?
Q3
C — Joining the input straight into the query text lets an attacker type SQL such as x' OR '1'='1 and have it run. Use the ? placeholder and pass name separately: q += " WHERE name = ?"
Q4
B — The placeholder is missing, so there is nowhere for the input to go as data. A parameterised query needs a ? placeholder: WHERE email = ?
Q5
C — An f-string pastes the typed text straight into the SQL, so injected commands would run. Use a ? placeholder instead: q += " WHERE id = ?"