Second Order Injection
Second‑Order Injection is an injection pattern where untrusted input is accepted and stored by an application (for example in a database, log, or file) and later—at a different point in time or in a different context—this stored data is used in a way that allows it to be interpreted as code or commands. The key characteristic is that the initial input may appear harmless when stored (it is not executed immediately), but when the stored value is later read and used in a different execution context without proper output encoding or re-validation, it becomes an active vector for injection.
Examples of second‑order injection:
- A user submits a profile field that contains a payload which is saved to the database. Later, an administrative tool displays that field inside an admin panel and uses it inside a dynamically constructed SQL statement or shell command — allowing the payload to execute.
- Application stores a template fragment or formatting string supplied by a user; later another component evaluates or renders that fragment (e.g., via
eval(), template engines, or dynamic SQL), resulting in code execution. - Data written to logs by one component is later read and included by another component into an HTML page using
innerHTMLor into a SQL statement without parameterization.
Why it happens:
- Assumption that storing data is safe because it is not executed at the time of input.
- Lack of contextual output encoding when stored data is later placed into a different sink (HTML, JavaScript, SQL, OS command, XML, template engine).
- Missing or inconsistent validation across components: input validated at submission but not revalidated at consumption.
- Use of flexible features (dynamic evaluation, string templating, ad-hoc SQL building) that accept runtime data as code.
Typical attack consequences:
- Cross‑Site Scripting (XSS) when stored values are later injected into web pages without proper encoding.
- SQL Injection or Command Injection when stored values are later concatenated into SQL queries or shell commands.
- Server‑Side Template Injection (SSTI) when stored template fragments are later rendered by a template engine.
- Privilege escalation, data exfiltration, loss of integrity or confidentiality, and full system compromise depending on the sink and privileges.
Detection challenges:
- The injection point and the execution point are separated in time and possibly by different application components, which makes static or simple dynamic scans less likely to detect the issue.
- Behavior appears benign during submission and may only trigger when an administrator or a particular workflow processes the stored content.
- Automated scanners that only test immediate reflections will miss second‑order paths.
Remediation
Preventing second‑order injection requires a clear separation of responsibilities, context‑aware output handling, and secure design for both storage and consumption of user data.
Treat Stored Data as Untrusted at Every Use
Always assume data retrieved from storage is untrusted. Apply the same protections at consumption time as you would at input time.Context‑Aware Output Encoding
Encode or escape stored values according to the sink/context where they will be used:- HTML body → HTML entity encoding.
- HTML attribute → attribute encoding and quoting.
- JavaScript context → JS string/JSON encoding.
- URL context → percent‑encoding.
- SQL → use parameterized queries (bind variables).
- Shell → avoid the shell; if unavoidable, use argument arrays and proper escaping.
- Template engines → avoid evaluating user‑supplied templates; if evaluation is needed, use strict sandboxing and whitelists.
Avoid Dynamic Evaluation of Stored Content
Nevereval()or otherwise directly execute stored strings. Avoid building code or SQL by concatenating stored values.Re‑validate and Canonicalize at Use
If stored data must be used in a restricted way (e.g., as an identifier or filename), canonicalize and validate it again at the point of use against a strict whitelist or pattern.Use Parameterized APIs and Safe Framework Features
Use prepared statements for database access, safe libraries for template rendering (that escape by default), and OS APIs that accept arguments separately from command names.Apply the Principle of Least Privilege
Reduce the impact of a successful second‑order injection by limiting privileges of processes and accounts that consume stored data.Design for Separation of Concerns
Keep storage, rendering, and administrative functions in distinct components with clear contracts about allowed data formats and strict validation on crossing boundaries.Logging and Monitoring
Monitor for suspicious patterns when stored content is accessed or executed (unexpected templates being rendered, database queries containing unusual tokens, outbound connections triggered by stored values).Secure Development Practices
- Code reviews should specifically search for places where stored data is later used in risky sinks.
- Threat modeling to identify flows where stored input travels to execution points.
- Unit/integration tests that simulate stored payloads being processed by downstream components.
Use Sandboxing When Execution Is Required
If a design requires the execution of stored scripts or templates (for example, user‑provided automation), run them in a strong sandbox or isolated service with strict resource limits and no access to sensitive host resources.