Reputation: 1432
I have some odd behavior here that I'm trying to understand.
I'm using MVC 5 with AngularJS version 1.4.5. This version of Angular is vulnerable to some XSS attacks since you can escape the sandbox.
The following string will give a alert with the text "5":
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(5)//');}}
I have a razor page, Index.cshtml with the following razor code and HTML:
<div ng-app="">
<div>
@{
var breakAngular = "{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(5)//');}}";
}
@breakAngular
</div>
</div>
Now, the razor engine will always encode html on rendering the page, thus "{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(5)//');}}
" is translated to a harmless "{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(5)//');}}
"
However, the alert still executes when I load the page.
I would expect the server-side razor engine encoding the string with the attack vector before outputting it would mean that the string is made safe, yet the alert still executes when the page is loaded.
It's like the angular sandbox can somehow access the string and intepret it before the razor angine gets the chance to sanitize the string which makes no sense.
What am I missing here and is there any way to protect against this type of vulnerabilities?
Unfortunately, updating angularJS is not a possibility at this point!
Update
Apparently this works in protecting against the angularjs sandbox escape.
@Html.Raw(Html.Encode(breakAngular))
Upvotes: 0
Views: 228
Reputation: 4416
The Angular documentation has traditionally been pretty clear on the dangers of mixing client and server side templating. Razors default encoding is meant to mitigate XSS under certain conditions, but of course cannot fix all kinds, as different client-side templating frameworks introduce different templating mechanisms.
I would not put user provided data inside of an angular templating like this. If you need to provide data from the server, one way to fix this, could be to put it outside of ng-app, and rather use javascript to fetch the values from the DOM.
Upvotes: 1