Posts

Angular Template Injection without Quote Characters

Introduction

When you’re trying to detect XSS in an Angular application (AngularJS or Angular >2, the version doesn’t matter for this post), you’ll probably try the following possibilities:

  • You enter a basic XSS payload such as <script>alert(0);</script>
  • You find out that the developer encoded the output properly and the < > characters turn into &lt; and &gt; 
  • Your next attempt will be a client-side template injection: {{1338-1}}
  • The application displays 1337
  • From here on, it will be straight-forward: you’ll find a payload that matches the Angular version of the app and pop that alert to get a Proof of Concept.

However, in some cases, the output sanitation applies not only to characters like > and < but also encodes single and double quote characters ( ‘ will turn into &apos;, etc.)

This means that if you try to insert a payload that has quotes in it, for example:

{{constructor.constructor('alert(0)')()}}

It will turn into

{{constructor.constructor(&apos;alert(0)&apos;)()}}

At this point, your expression will trigger a syntax error and the payload will fail. 

So, what can we do about it?

When trying to avoid quotes in a payload (because it contains strings) the easiest way is to use functions that generates strings. In JavaScript, we will need to use the String object, specifically, the String.fromCharCode() method

The issue in this case (Angular applications) is that we cannot just call String.fromCharCode()in an Angular expression:

{{constructor.constructor(String.formCharCode(...))()}}

It will not work because Angular limits us to only using the properties and variables that are accessible under Angular’s scope. (More about the scope here: https://github.com/angular/angular.js/wiki/Understanding-Scopes). If Angular wasn’t stopping us from accessing objects outside the scope, we wouldn’t need to access the Stringobject. As attacker, we could just inject {{window.alert(0)}}

So what do we do when we don’t have access to the Stringobject but we still need to call fromCharCode() to generate our “alert(0)” string?

We can use this payload:

{{constructor.constructor(valueOf.name.constructor.fromCharCode(...))()}}

Let’s break it down

  • We used valueOf.name because it returns a string value. Right now, it doesn’t matter what string is returned. As long as it’s a string variable – we’re good to go. In the same way, we could use any of the following possibilities as they all generate strings:
  • Now that we have a string variable in our payload, let’s look at its constructor:
  • The constructor itself is a String object! Now, all we have to do is to add a dot character and access all of the available functions in the String object including fromCharCode

By getting to the String object in this indirect way, even though the object itself isn’t in Angular’s scope, we can create an Angular, Client-Side Template Injection payload without needing single or double quotes

And here’s our alert 🙂 without quotes.

Acknowledgements

Big shout-out goes to the folks from PortSwigger and Tomer Haddad


AliExpress hacked – the entire story

Introduction

As you may have heard it was recently advertised that AliExpress, one of the world’s largest online shopping websites, was found to have substantial security shortcomings. As one of the people who discovered the vulnerability, I would like to take this opportunity to discuss the vulnerability I detected in this blog post.

A few months ago, I purchased a few items from the AliExpress website. After the purchase, I sent a message to the seller in order to ask him a question regarding the items. From my experience as an application security expert in AppSec Labs, I had suspected that it might be vulnerable to a certain security breach, and so I started to investigate the issue locally and without, of course, harming the system or its users.

After a short investigation, I had concluded that any buyer in the website can browse to any item and can send a message to the seller using the “Contact Now” feature; this feature can be abused by a malicious buyer who could send a message to the seller containing a malicious payload.
Read more

Resident XSS – Reflected Becomes Stored Thanks to HTML5

HTML5 is the newest version of the HTML. It offers new features that enhance support for creating web applications that can interact with the user and his/her local data and servers. HTML5 successfully does this more easily and effectively than has previously been possible.

In this article we will focus on the new client storage offered by HTML5. The new HTML provides us with the Local & Session Storage, which can hold  15MB and more of client data. The differences between them is that the Local Storage can be accessed from any window, while the Session Storage can by read/modified by the same window only. Additionally, the data within the Session Storage will be automatically deleted when the window is closed, whilst deletion of the data in the Local Storage must be done manually.

Let’s say that the web application stores your account number, the SessionId, username, and some other data that will be read later on in order to display the data without sending requests to the server. The website takes the data it previously entered to the storage and displays it when the page renders. This is how the page looks normally, along with the original information stored in the sessionStorage:

ScreenShot138(Click on the image to enlarge)

Notice that the message within the speech bubble takes its information from the Session Storage, as can be seen in the above image, right below the page. You can access the page’s Resources tab using Chrome’s Developer tools (a.k.a Inspect Element).

We can assume that the page’s code behind it looks something like this when retrieving the data from the Session Storage:
<script>
   var username = window.sessionStorage.getItem(“username”);
   var speech = window.sessionStorage.getItem(“Speech-of-the-day”);
   var action = window.sessionStorage.getItem(“Random-action”);
</script>

If this website is vulnerable to a Reflected XSS (which in the regular case would be executed once on the response that includes it) and if the website does not perform client-side encoding (escaping), then this Reflected XSS can become a Stored XSS.

Read more