Lesson pack 11 · Core · 120 minutes
Injection: SQL and everything after it
One bug class, five parsers. Break out of a SQL string, a shell argument, an XML document, a NoSQL query and an LDAP filter, and read the response for confirmation.
Print this page for a paper plan - the navigation and links drop out.Student-facing version
Before the session
- Nothing to install. Students need a browser and https://ctfpal.com. Confirm the room can reach it once; after that it works offline.
- Read the lesson yourself first - about 25 minutes.
- Have one worked example ready to paste. The classroom link builder on the instructor page turns it into a URL that opens preloaded.
Objectives
Written as things a student can do afterwards, so they can be assessed rather than asserted.
- Confirm an injection point with a detection payload before attempting exploitation
- Move from a broken quote to a UNION select, and from a blind boolean to an extracted string
- Recognise NoSQL, LDAP, XPath and CRLF injection from the sink rather than from the payload
- Turn an XXE into a file read, and know which parsers stopped allowing that
- Chain a command injection into an out-of-band confirmation when nothing is echoed back
- Explain why every one of these is the same bug: data crossing into a parser as code
Running order (120 min)
| Time | What happens |
|---|---|
| 0:00-0:12 | Frame the problemWhat the category looks like when you meet it cold, and why the naive approach fails. |
| 0:12-0:36 | Teach the methodThe technique itself, on the board or from the lesson. No tools open yet. |
| 0:36-1:06 | Demonstrate liveSame technique, in the workspace, on your worked example. Narrate every choice. |
| 1:06-1:48 | Practice setStudents work the challenges. Circulate rather than present. |
| 1:48-2:00 | Checkpoint and wrapCollect the artefact, name what comes next. |
Tools used
- Web attack payload catalog - Curated payloads for SQL injection, XSS, SSTI, SSRF, GraphQL, and deserialization, organised by what you are trying to establish.https://ctfpal.com/?tool=payload-catalog
- HTTP request replayer - Craft and replay HTTP requests with arbitrary methods, headers, and bodies, and read the raw response - a Repeater that runs in your browser.https://ctfpal.com/?tool=http-request-replayer
- URL decoder and encoder - Percent-decode and encode URL components, including double-encoded payloads and `+`-as-space form encoding.https://ctfpal.com/?tool=url-decoder
- Regex tester with match offsets and capture groups - Test regular expressions live against sample text, with every match’s offset, capture groups, and named groups broken out.https://ctfpal.com/?tool=regex-tester
- Reverse shell generator - Generate reverse shell one-liners for bash, nc, Python, Perl, Ruby, PHP, Node, and PowerShell, plus listeners and TTY stabilisation commands.https://ctfpal.com/?tool=reverse-shell-generator
Reading
- SQL injection: from a broken quote to the whole database - 5 min. SQLi challenges reward a systematic climb: confirm the injection, work out the query shape, pull data with UNION, and fall back to boolean and time oracles when the output is hidden. Plus the auth-bypass one-liners and how to beat basic filters.
- Injection beyond SQL: NoSQL, LDAP, XPath, CRLF and SSI - 6 min. Every query language is injectable, and each one has a different syntax for always-true. Mongo operator injection, LDAP filter injection, XPath blind extraction, header injection through CRLF, and the server-side includes nobody remembers exist.
- Command injection: making the shell run your half of the string - 7 min. Where a shell gets invoked, the separators that split one command into two, how to confirm a blind injection you cannot see, and the argument-injection variant that needs no shell metacharacters at all.
- XXE: turning an XML parser into a file reader - 7 min. Any feature that parses XML - and that includes SVG, DOCX, and SOAP - can be told to fetch files and URLs of your choosing. How to confirm it, read files with a classic payload, and exfiltrate through an external DTD when nothing comes back.
Practice set
Real picoCTF challenges tagged with this module’s techniques, easiest first. Assign the first three in class and the rest as homework.
- Crack the Gate 1 - picoMini by CMU-Africa, easy
- n0s4n1ty 1 - picoCTF 2025, easy
- ping-cmd - picoCTF 2026, easy
- 3v@l - picoCTF 2025, medium
- Apriti sesamo - picoCTF 2025, medium
- caas - picoMini by redpwn, medium
- Crack the Gate 2 - picoMini by CMU-Africa, medium
- Irish-Name-Repo 1 - picoCTF 2019, medium
- Irish-Name-Repo 2 - picoCTF 2019, medium
- cancri-sp - picoCTF 2023, hard
- ORDER ORDER - picoCTF 2026, hard
- paper-2 - picoCTF 2026, hard
Checkpoint (gradeable)
Extract one row from a database through a blind boolean injection and state, per character, which comparison confirmed it - then do the same extraction through a time-based channel.
Deliberately a produced artefact rather than a quiz question: it is either there or it is not, which makes it fast to mark and hard to bluff. Every tool in ctfpal is deterministic, so two students who did the work correctly hand in the same value.
Where the room gets stuck
Teach the sink, not the payload list. A student who can name the parser on the other side derives the escape sequence; a student with a payload list is stuck the first time the challenge uses MSSQL instead of MySQL.
- Pasting a long exploit payload first. A single quote and a timing payload tell you whether there is a bug at all, and the response to them tells you which parser you are in.
- Concluding 'not vulnerable' from an unchanged page. Blind and second-order injections change nothing visible; time and out-of-band channels are the detector.
- Escaping quotes and calling it fixed. Numeric contexts, identifiers, ORDER BY clauses and LIKE patterns all inject without a quote.
- Treating the error message as the whole oracle. Once an application swallows errors the extraction still runs over a boolean, a delay or a DNS lookup, and a student who has only seen the verbose case stops at the first generic 500.
- Sending a payload the transport mangles. A + in a form body is a space, a # truncates the query string, and a comment sequence that worked in a database console fails over HTTP for reasons that have nothing to do with the injection.
If a student wants the subject, not the answer
Chapter-level references, so a student can be pointed at twenty pages rather than at a book. Nothing here is required to complete the module.
- Bug Bounty Bootcamp, Vickie Li. Chapter 11, SQL Injection. The clearest progression from detection to UNION to blind extraction, with the reasoning at each step.
- Bug Bounty Bootcamp, Vickie Li. Chapter 15, XML External Entity. XXE end to end, including the blind out-of-band variant that CTFs favour.
- Hunting Security Bugs, Tom Gallagher, Bryan Jeffries, and Lawrence Landauer. Chapter 16, SQL Injection. Written from the tester's side: how to find the injectable parameter rather than how to exploit a known one.
- Hacking APIs, Corey Ball. Chapter 12, Injection. The same bug where the input is JSON and the error handling is a stack trace in a response body.
If you finish early
- Hand out a challenge from the cross-CTF index in this category - each one has published solutions to compare afterwards.
- Run the same input through Identify and let the class argue with the ranking. Disagreeing with a confidence score is where the technique actually lands.
- Ask a student to break their own example - construct an input that defeats the tool, and explain why.
Take this into a room
Markdown files, built here in your browser. They print, they open in anything, and they carry the challenge text - so the session works with no network in the room.