Understanding Security Implications of AngularJs 2023
In this article, we will have a brief overview of Understanding Security Implications of AngularJs, which mainly includes the basics of AngularJs and the inner workings of the various sandbox leaks for the various versions discovered so far.
Introduction[Understanding Security Implications of AngularJs]
AngularJs is a JavaScript framework used to build RIA applications. It allows developers to create client-side templates based on the MVC architecture pattern. It uses built-in expressions to create HTML templates. These expressions are used to load/display data in a relative HTML context.
NOTE: Credits for the exploits mentioned in this article are reserved to their respective authors. I would like to thank each of them for their amazing research, as it really helped expand my knowledge. The names of these authors along with their exploit code can be found here.
Understanding the basics of AngularJs
To understand the security implications of AngularJs, we need to understand its basic workings. To do this, let’s create one simple application and understand the code by breaking it into multiple parts. We will create a simple AngularJs application and try to make some sense out of it.
In order to create a basic application, we need to define the name of the module and its controller, which we can further use to extract data and display it in an HTML context (view). Our application takes any string as input and then places it in an AngularJs context.
Place the following code in your app.js file
file
‘use strict’;// angular.module function is used to define the application module.var exampleapp = angular.module(‘exampleapp’,[]);// Defining the controller for defined moduleexampleapp.controller(‘examplecontroller’, function examplecontroller($scope){ // Defining scope variables $scope.name = “john doe”; $scope.age = 18; $scope.sayhello = function($name){ return “Hello “+ $name + ‘!!’ } }); |
Code for index.php file look like following:
<!doctype html><!– using our module name in html attribute –><html lang=”en” ng-app=”examplemodule”><head><meta charset=”utf-8″><script src=”angular.js”></script><script src=”app.js”></script></head><!– Defining our controller data here –><body ng-controller=”examplecontroller”><form action=”index.php” method=”GET”> <p><input type=”text” name=”name”><input type=”submit” value=”submit”></p> <?php echo htmlspecialchars((isset($_GET[‘name’]) ? $_GET[‘name’] : “”),ENT_QUOTES); ?><ul> <li>{{name}}</li> <li>{{age}}</li> <li>{{sayhello(‘test’)}}</li> <li>{{alert(1)}}</li> </ul></body></html> |
As seen in the code snippet below, we use a curly brace expression to remove the data. However, there is another variable name “alert(1)” which will be displayed as is. Ideally, we can assume that if all other expressions are executed in a JS context, then our powerful JS function should also be executed, but in this case, this is not the case.
AngularJs uses the scope object to check the existence of variables defined in AngularJs expressions. As in our case there is an undefined scope variable “{{alert(1)}}, AngularJS simply checks if “alert” is a property of the scope object using the following function pointer.

var fnPtr = fn(scope, local, context) || nope
fn = Function(‘s’, ‘k’, code); // s=range, k=local
Since “notification” is not defined in the current scope, its value will evaluate to noop, meaning no operation and will be displayed, and the same will happen to any global JS functions such as document.cookie or document.domain.
Also Reaad:Everything you need to know about Ethical Hacking as a Career by Blackhat Pakistan 2023
Sandbox Bypass in AngularJs version 1.0.8
As we have seen in the previous sections, we are not able to go outside the scope object and perform any global functions. In this phase, we will look at how we can escape from an out-of-scope object and perform arbitrary JavaScript functions using the “Gareth Hayes” exploit.
The scope itself is like any other JavaScript object and has a constructor, let’s see what this constructor carries.

As you can see, the scope object constructor is the object constructor and the object constructor constructor is the function constructor. This function constructor can be used to create a function for us and we can further use parentheses around it to run our JavaScript code.
Example:
As you can see, we have created a function constructor object and it contains our JavaScript fragment. Next, we used parentheses around it to run our code.
Similarly, we’ll use the scope object’s constructor function constructor to evaluate our code and bypass the scope restrictions implied earlier.
The complete payload will look like this
{{constructor.constructor(‘alert(0)’)()}}
Since every expression in AngularJs will be evaluated against a scope object, we don’t need to specify the scope keyword. As you can see, we can bypass the scope restriction and run our JavaScript using the function constructor.
Sandbox Bypass in AngularJs version 1.2.19
To overcome workarounds found in earlier versions, this version implements some security checks before interpreting the data. This mainly includes checking various properties of the object, checking the properties of functions like CALL, APPLY, BIND, because previous bypasses abused them to run JavaScript code.
For example:
Let’s take a look at the bypass for version 1.2.18 by Jan Horn.
(_=”.sub).call.call({}[$=’constructor’].getOwnPropertyDescriptor(_.__proto__,$).value,0,’alert(1)’)() |
The following screenshot shows an equivalent breakdown of the above exploit code.
By analyzing the exploit code, we found that it uses the CALL property of the function object to execute the JavaScript code. In the following screenshot, we can see that in version 1.2.19, a new function was introduced to check various properties of a function object that were used in previous bypasses.
Now let’s look at the bypass for this version by “Mathias Karlsson”.
{{toString.constructor.prototype.toString=toString.constructor.prototype.call;[“a”,”alert(1)”].sort(toString.constructor);}}
So we mainly have two functions to bypass to get our code to run, Mathias’ exploit first changes the way the toString function is supposed to work by giving it a new “call” property, so that by the time the toString constructor is called by the sort function, toString will be equal to calling and thus will do “alert(1)”.
Sandbox Bypass in AngularJs version 1.4.7
In this version, AngularJs overcomes the previous sandbox escape by implementing a built-in compiler and uses the AST (Abstract Syntax Tree) technique to tokenize the expression and perform safety functions such as ensureSafeObject on enumeration objects.
Let’s try the exploit for version 1.2.19 in this version as seen; we are getting referencing function error.
Why is this happening or why can’t we refer to the function object anymore?
We saw that in one of the previous sandboxes, the constructor of the object constructor is the function constructor, but let’s see what the value of the constructor of the function constructor is.
As you can see, the constructor of a function constructor is again a function constructor, so the “if (obj.constructor === obj)” line in the sureSafeObject function successfully blocks our previous payload by checking that the constructor of some object is this object again. alone.

Let’s take a look at the exploit code provided by Gareth Heyes and how he was able to bypass the restrictions implemented in newer versions of angularJs.
{{‘a’.constructor.prototype.charAt=[].join;$eval(‘x=1} } };alert(1)//’);}}
The above exploit first overrides the functionality of the charAt function with the join function, which means that now when we call the charAt function, it simply appends the value to each character instead of getting the index.

The next part of the exploit then iterates through the following loop to retrieve tokens for lexical analysis.
However, this function fails to distinguish between the identifiers and the actual code and include another part of the exploit x=1} } };alert(1)//’);}} in the resulting compiled javascript code.
As can be seen, loading the token using lexical analysis treats the second part of the exploit as an identifier.

This results in arbitrary execution of JavaScript code.
Usage Summary:
The first part of the exploit overrides the charAt function and passes the lexical analysis. However, in the second part, the charAt function will now act as a join function and insert the second part of the exploit into the resulting compiled JavaScript, which will result in the execution of the JavaScript code.
References:
http://blog.portswigger.net/2016/01/xss-without-html-client-side-template.html
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype