Skip to content

Commit 02f395f

Browse files
Add qhelp
1 parent cea196e commit 02f395f

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
2+
<qhelp>
3+
<overview>
4+
<p>
5+
A template from a server templating engine such as Jinja constructed from user input can allow the user to execute arbitrary code using certain template features. It can also allow for cross-site scripting.
6+
</p>
7+
</overview>
8+
<recommendation>
9+
<p>
10+
Ensure that an untrusted value is not used to directly construct a template.
11+
Jinja also provides a <code>SandboxedEnvironment</code> that prohibits access to unsafe methods and attributes, that can be used if constructing a template from user input is absolutely necessary.
12+
</p>
13+
</recommendation>
14+
<example>
15+
<p>In the following case <code>template<code> is used to generate a Jinja2 template string. This can lead to remote code execution. </p>
16+
<sample src="examples/JinjaBad.py" />
17+
18+
<p>The following is an example of a string that could be used to cause remote code execution when interpreted as a template:</p>
19+
<sample src="examples/template_exploit" />
20+
21+
<p>In the following case, user input is not used to construct the template; rather is only used for as the parameters to render the template, which is safe.</p>
22+
<sample scr="examples/JinjaGoodParam" />
23+
24+
<p>In the following case, a <code>SandboxedEnvironment</code> is used, preventing remote code execution.</p>
25+
<sample src="examples/JinjaGoodSandbox.py" />
26+
</example>
27+
<references>
28+
<li>Portswigger : [Server Side Template Injection](https://portswigger.net/web-security/server-side-template-injection)</li>
29+
</references>
30+
</qhelp>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from django.urls import path
2+
from django.http import HttpResponse
3+
from jinja2 import Template, escape
4+
5+
6+
def a(request):
7+
template = request.GET['template']
8+
9+
# BAD: Template is constructed from user input.
10+
t = Template(template)
11+
12+
name = request.GET['name']
13+
html = t.render(name=escape(name))
14+
return HttpResponse(html)
15+
16+
17+
urlpatterns = [
18+
path('a', a),
19+
]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from django.urls import path
2+
from django.http import HttpResponse
3+
from jinja2 import Template, escape
4+
5+
6+
def a(request):
7+
# GOOD: Template is a constant, not constructed from user input
8+
t = Template("Hello, {{name}}!")
9+
10+
name = request.GET['name']
11+
html = t.render(name=escape(name))
12+
return HttpResponse(html)
13+
14+
15+
urlpatterns = [
16+
path('a', a),
17+
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from django.urls import path
2+
from django.http import HttpResponse
3+
from jinja2 import escape
4+
from jinja2.sandbox import SandboxedEnvironment
5+
6+
7+
def a(request):
8+
env = SandboxedEnvironment()
9+
template = request.GET['template']
10+
11+
# GOOD: A sandboxed environment is used to construct the template.
12+
t = env.from_string(template)
13+
14+
name = request.GET['name']
15+
html = t.render(name=escape(name))
16+
return HttpResponse(html)
17+
18+
19+
urlpatterns = [
20+
path('a', a),
21+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{% for s in ().__class__.__base__.__subclasses__() %}{% if "warning" in s.__name__ %}{{s()._module.__builtins__['__import__']('os').system('cat /etc/passwd') }}{% endif %}{% endfor %}

0 commit comments

Comments
 (0)