The course final. Five challenges against fresh endpoints - easy, medium, hard, with a second-order SQLi to keep things honest. There is no hand-holding, no auto-complete, and no oracle to lean on. The same five patterns from lessons 1 to 19.
- L1Lesson 1
- L2Lesson 2
- L3Lesson 3
- L4Lesson 4
- L5Lesson 5
- L6Lesson 6
- L7Lesson 7
- L8Lesson 8
- L9Lesson 9
- L10Lesson 10
- L11Lesson 11
- L12Lesson 12
- L13Lesson 13
- L14Lesson 14
- L15Lesson 15
- L16Lesson 16
- L17Lesson 17
- L18Lesson 18
- L19Lesson 19
- Apply the canonical patterns from lessons 4–17 to fresh endpoints.
- Distinguish a UNION-based, time-based, and second-order SQLi.
- Write a payload that solves a novel problem in under 60 seconds.
- Recognise the same bug in five different shapes.
- Practice range
- A sandboxed environment for trying payloads against known-vulnerable endpoints. The training wheels; the same techniques on a real bug bounty target are not legal without authorisation.
- Authorisation
- Written permission from the asset owner to test for vulnerabilities. Required for any real-world testing; never assumed. Bug bounty programmes grant authorisation through their scope.
- Pattern matching
- The skill of recognising a SQLi in a novel endpoint by the same shape - a string-concat query, a parameterised endpoint that is actually string-concat, a value that travels through multiple hops before reaching the database.
- Time pressure
- The constraint in a real penetration test or bug bounty. The technique that takes five payloads to solve a challenge is the technique that costs you the bounty. Practice until the canonical patterns are reflex.
The course final
Five challenges. Pick one, write the payload, and submit. The simulator checks for the keywords in the canonical payload; partial credit is not given. The hints are there; the solutions are in the explanations on success.
Pick a challenge, write the payload, and press Submit. The simulator checks for the keywords in the canonical payload; partial credit is not given.
The application builds the query with string concatenation. Get past the login form. The username field is `victim`, the password is whatever you type.
SELECT * FROM users WHERE username = 'victim' AND password = '…'
Hint: Close the string literal, add a tautology, comment out the rest with -- and a trailing space.
From the range to a real bug bounty
The techniques are the same; the legal framework is not. A real-world SQLi hunt requires written authorisation from the asset owner. Bug bounty programmes (HackerOne, Bugcrowd, the platform's own scope) grant that authorisation for the in-scope targets. Testing a target without authorisation is illegal in most jurisdictions - even if the bug is real and even if the disclosure is responsible.
The 60-second pattern-recognition reflex that practice ranges build is the difference between a $5,000 bounty and a $50,000 one. A hunter who can read a novel endpoint and see a SQLi in under a minute finds more findings per hour. The same techniques, practiced until they are reflex, are what separate a productive hunter from a hobbyist.
What to take with you
Three things. First, the bug is a string-concat query; the fix is a bound parameter. That sentence is the entire course. Second, the surface evolves; the fix does not. GraphQL, serverless, AI-generated code - all reduce to the same bug, and all are closed by the same fix. Third, defence-in-depth matters. Parameterised queries, allowlist identifiers, least-privilege database users, and generic production errors are the four layers that survive a single layer failing.
// The course, in five lines
const query = 'SELECT * FROM users WHERE id = $1';
const result = await db.query(query, [id]);
// Defence-in-depth: allowlist identifiers
if (!SAFE_TABLES.has(table)) throw new Error('invalid table');
// Defence-in-depth: least-privilege
// GRANT SELECT ON app.users TO app_user; -- no information_schema
// Defence-in-depth: generic production errors
catch (e) { log.error(e); res.status(500).send('oops'); }What to remember
- The bug is a string-concat query. The fix is a bound parameter. That sentence is the entire course.
- The surface evolves; the fix does not. The fix works on every modern RDBMS, regardless of the framework or the API style.
- Defence-in-depth matters: parameterise, allowlist identifiers, least-privilege DB user, generic production errors.
- Real-world testing requires written authorisation. Bug bounty programmes grant it for in-scope targets.
Knowledge check
0/3 answered · 0 correct1.A new endpoint you have never seen before has a search field. What is the first probe?
2.You have found a SQLi in a JSON path filter. The keys (column names) are allowlisted. The values are concatenated. What is the safe replacement?
3.Why is the reflex of "string-concat → bound parameter" the most important skill from this course?