Home / Knowledge hub / Second-order injection
Knowledge hub
Second-order injection
Malicious input stored safely at first, then run later when another part reads it.
What it means
In a normal injection, the attacker's input does harm in the same request. Second-order injection splits it into two steps. First the input is saved, and it is handled safely at that moment. Later, a different part of the app reads it back and uses it in a way that treats it as code or a command.
The input is trusted the second time because it came from your own database. That is the mistake. Data is only as safe as the place it originally came from, and that was a visitor. That is why the flaw hides so well.
Why it matters
It defeats the usual checks. Testing the form that stores the value shows nothing wrong, and the part that runs it may be an admin screen, a nightly report or an export that nobody linked to the original form. Damage lands somewhere unexpected, often with higher privileges than the visitor ever had.
A classic case is a name saved with a quote and SQL fragment in it, stored using a safe query, then pasted into a string-built query by a report job. It is the same family as SQL injection and stored XSS.
How it shows up
You meet it wherever stored data is reused: profile names, addresses, comments, ticket subjects, file names, and values copied into logs, emails, PDFs or batch jobs. Look for places where a saved value is concatenated into a query, a command, a template or a page.
The fix is the same as for any injection, applied to every read as well as every write. Use parameterised queries everywhere, encode output for the place it lands, and treat database content as untrusted input. Testing needs a long path: store a harmless marker, then follow it to every place it shows up.
Questions people ask
Second-order injection, answered
Why do scanners miss second-order injection?
Because the response to the request that stores the value looks normal. The effect shows later, on another page or job, and a tool that only reads the immediate response never connects the two.
Following the stored value is the key.
Is stored XSS second-order too?
In a sense, yes. Stored XSS saves the payload and runs it later when another person views the page. The term second-order is more often used for SQL and other back-end injection.
The pattern is the same: store now, run later.
Does escaping on input fix it?
No. Escaping when you save protects only that one use. Stored data will be used in many places, each needing its own treatment.
Handle it at the point of use.
Which parts of an app are most exposed?
Admin tools, reports, exports, search indexing, email templates and background jobs. They read stored data and often run with more power than the public pages.
They are also less often tested.
How do we test for it?
Store a harmless, unique marker in each field, then trace where it reappears. In each place, check whether special characters are handled safely.
With the code available, tracing is much quicker.
Sources
Where this comes from
Related
Terms that sit next to this one
SQL injection
Input a database ends up running as part of a query.
Stored XSS
Malicious script saved by your app and then served to other people who view it.
Parameterised queries
Sending the query and the data separately so input can never become code.
Untrusted input
Anything that arrived from outside your own code, and is therefore suspect.
Blind SQL injection
Injection where no data comes back, so answers are read from timing or behaviour.
Where does your stored data end up?
In white-box mode we read the code to follow stored values to the places that reuse them, then prove the ones that run. Each finding shows the request and the line. Book a pilot on one app.
Or start with a $199 pilot on one application: thirty days, success criteria agreed before day one, credited against the annual if you convert.