Skip to content

Instantly share code, notes, and snippets.

@yeukhon
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yeukhon/22f2a21cd376c002c270 to your computer and use it in GitHub Desktop.
Save yeukhon/22f2a21cd376c002c270 to your computer and use it in GitHub Desktop.
Security TODO

XSS escape effectiveness in popular template render engine

In the Python ecosystem, there are three popular template render engines: Django's built-in template engine, Jinja2 and Mako.

How good are these render engines against XSS. Is {{ foo }} enough? Under what sitations do {{ foo }} fail? The importance of this research is to understand (1) the context-awareness of template engine, if at all, (2) understand the challenge of encoding in the HTML world, and (3) and best practices when using template render engine.

  • understand quotes, innerHTML injection
  • insert script via innerHTML method is blocked by HTML spec. See 1.
  • escape <, >, &, ', and ". See 2.
  • escape characters inside quoted attributes.
  • http://jsfiddle.net/hQ6y5/3/, http://jsfiddle.net/ckdM4/
  • input = escape(input) --> output = unescape(input); escape is a deprecated API.
  • innerHTML is bad. use textContent except in the case of <script> element.

Inline script defense in Content Security Policy

Content Security Policy (CSP) 1.1 draft introduces script hash and script nouce to help developers to maintain script integrity, espeically for inline scripts. Since most applications today still run with inline scripts, and migrating away from inline script is not not always feasible, how can we defend XSS while enable CSP for the rest of the content?

Most importantly, some inline scripts "reflect" user input and maybe vulnerable to XSS:

<a href={{ foo }}>{{ bar }}</a>

or DOM-based XSS

<script>
// Use hash as id to load resource in a vanilla single-page app
var resId = window.location.href.split("#")[1];
// load content in the next few lines, if error we output an error message (404 sort of)
// ....
// ....
</script>

Is the problem above worthwhile to defend?

XSS test cases for testing template engine

<a href="http://localhost:8000">{{ url }}</a>
<div>{{url}}>/div>
<a href="{{ url }}">{{ url }}</a>
<script>
var userId = {{ userId }};
</script>

payloads:

http://google.com
http://localhost:8000
http://username:password@localhost:8000/
http://localhost:8000/home?username=<script>alert('xss');</script>
http://localhost:8000/?&lt;script&gt;alert(0)&lt;/&gt;
<script>alert(0)</script>
"><script>alert(0)</script>
"></a><script>alert(0)</script>
<script><script>alert(0)</script>
<script>eval('a\u006cert(1)');</script>
<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41));</script>
foo\'; alert(0);//
<img/somejunk/onerror=alert() src=a>
<audio src=1 onerror=alert(1)>
\'foo\'; alert(0);//

Testing:

  • candidates: django's template engine, Jinja2, Mako
  • launch slimerjs and phamtonjs, plus verify the render templates with an expected string

Cross-site scripting can occur in a few ways.

  1. concatenate HTML strings with user input
  • insert HTML elements via +
  • insert HTML elements or event handlers by breaking out quotes, or using space (for unquoted attributes).
  1. using innerHTML without escaping

  2. using user input in <script> (even using .textContent)

  • using untrust JSON data to write data into HTML element (via document.write, or .innerHTML)
  • embed untrust user data directly into the <script> body with template engine
  1. non-text/html resource returns text/html as content-type (e.g. visit .json page)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment