Cyber Security Labs (Beginner → Advanced)

Lesson 5 of 6

Lab 5 — Web Exploits and Secure Coding

Reproduce SQL injection and XSS on paper, then rewrite the vulnerable code properly.

🔴 Advanced 150 XP

Learn it

Most website hacks happen because the site treats what a user typed as an instruction instead of as data.

SQL injection means typing database commands into a login box. Cross-site scripting means typing JavaScript into a comment box.

The fix is never 'ban rude words' — it is to keep code and data in separate lanes.

Key terms

SQL injection
Injecting database commands through user input that is concatenated into a query.
Parameterised query
A query where values are sent separately from the SQL, so input can never become code.
XSS
Cross-site scripting — injecting JavaScript that runs in another user's browser.
CSP
Content-Security-Policy — a header restricting which scripts a page is allowed to run.
Least privilege
Giving each account only the permissions it genuinely needs.

Break it, then fix it

This login handler is vulnerable. Follow the attack, then the repair.

  1. 11. The code: query = "SELECT * FROM users WHERE name='" + name + "' AND pass='" + pw + "'"
  2. 22. The payload: The attacker types ' OR '1'='1' -- into the name box and anything into the password box.
  3. 33. The result: SELECT * FROM users WHERE name='' OR '1'='1' --' AND pass='x' — everything after -- is a comment, and '1'='1' is always true.
  4. 44. The impact: The first row is returned, which is usually the admin account. The attacker is now logged in without any password.
  5. 55. The wrong fix: Blocking apostrophes. Attackers use hex encoding, UNION SELECT, or second-order injection — and O'Brien can no longer log in.
  6. 66. The real fix: cur.execute("SELECT * FROM users WHERE name=%s AND pass_hash=%s", (name, hashed)) — the driver never lets the value alter the query structure.
  7. 77. Then go deeper: Give the web database user SELECT/INSERT only, hash passwords with Argon2, rate-limit logins, and log failed attempts.

Vulnerable vs safe

python# VULNERABLE — string concatenation
q = f"SELECT id FROM users WHERE email = '{email}'"
cur.execute(q)

# SAFE — parameterised
cur.execute("SELECT id FROM users WHERE email = %s", (email,))

# VULNERABLE — innerHTML with user data
# el.innerHTML = comment

# SAFE — treated as text, never parsed as HTML
# el.textContent = comment

In both cases the fix is the same idea: tell the interpreter explicitly that this is data, not code.

Sandbox lab

Practise the real technique in a fully simulated environment — no live systems, no real data, nothing leaves your browser.

Web exploit lab

A pretend vulnerable app running entirely in this page. No real database, no real network requests, no scripts are ever executed.

Safe simulation

Try it

Secure-coding claims — true or false?

Escaping apostrophes is a complete defence against SQL injection.

Storing a session token in an HttpOnly cookie stops JavaScript from reading it.

Client-side validation is enough because the form checks the input first.

A strict Content-Security-Policy can block injected inline scripts even when XSS exists.

The web app's database account should have DROP TABLE rights so migrations work.

Challenge

Here is a real vulnerable endpoint: @app.get('/search') def search(): q = request.args['q'] rows = db.execute("SELECT title FROM posts WHERE title LIKE '%" + q + "%'").fetchall() return f"<h2>Results for {q}</h2>" + "".join(f"<li>{r[0]}</li>" for r in rows) Find BOTH vulnerabilities, give a working proof-of-concept input for each, rewrite the endpoint securely, and list two additional defence-in-depth controls.

Pick whichever way suits you — every mode earns the same bonus XP.

Write at least 40 more characters to submit.

Mark your own work

Guided walkthrough — 0/7 clues revealed

  1. Clue 1 locked — reveal it only if you get stuck.
  2. Clue 2 locked — reveal it only if you get stuck.
  3. Clue 3 locked — reveal it only if you get stuck.
  4. Clue 4 locked — reveal it only if you get stuck.
  5. Clue 5 locked — reveal it only if you get stuck.
  6. Clue 6 locked — reveal it only if you get stuck.
  7. Clue 7 locked — reveal it only if you get stuck.

Each clue costs 8 XP (never below 38 XP). You'd earn 75 XP right now.

Extension: Explain how an attacker could chain the XSS with a CSRF request to change an admin's email address.

Quiz time

Question 1 of 4Score 0

The strongest fix for SQL injection is: