Metasploit DNS
Background
Most applications that need to handle hostname to IP address lookups rely on the host operating system, either by passing the hostname directly to the socket-creation function or by calling a purpose built API such as getaddrinfo
. This was also how Metasploit handled name lookups and would only directly communicate with a DNS server when the request was more involved than mapping a hostname to an IPv4 or IPv6 address.
One flaw in this approach is that when pivoting connections over a session, the DNS lookups would occur through the host on which Metasploit was running instead of the compromised host from which the connection would originate. This lead to two issues, the first being the aforementioned DNS leaks and the second that Metasploit could not always resolve hostnames that the compromised system could.
Starting in Metasploit 6.4, Metasploit uses an internal DNS resolution system that grants the user a high degree of control over the process of DNS queries.
The DNS command
Metasploit’s DNS configuration is controlled by the dns
command which has multiple subcommands.
The current configuration can be printed by running dns print
:
msf6 > dns print
Default search domain: N/A
Default search list: lab.lan
Current cache size: 0
Resolver rule entries
=====================
# Rule Resolver Comm channel
- ---- -------- ------------
1 *
. \_ static N/A
. \_ 127.0.0.53
Static hostnames
================
Hostname IPv4 Address IPv6 Address
-------- ------------ ------------
localhost 127.0.0.1 ::1
\_ 127.1.1.1
localhost.localdomain 127.0.0.1 ::1
localhost4 127.0.0.1
localhost4.localdomain4 127.0.0.1
localhost6 ::1
localhost6.localdomain6 ::1
The help
subcommand can be used to display the available subcommands. The name of a subcommand can also be specified as an argument to help
to display additional information about that subcommand, for example dns help add
.
Metasploit’s DNS system is composed of the following major components: resolver rules, static entries and the cache.
DNS Resolver Rules
DNS resolver rules are a single wildcard that is associated with zero or more resolver types. When a query name matches the wildcard expression, the associated resolvers are used in succession until one is capable of fulfilling the request. For example, a wildcard pattern of *.lab.lan
would match www.lab.lan
and _ldap._tcp.lab.lan
, but not lab.lan
or msflab.lan
. Furthermore, the *
wildcard pattern matches everything and should be used as a default rule.
Once a rule that matches the query name is found, the specified resolvers will be tried in order until one is capable of handling the request. Different resolver types can be specified to handle queries in different ways. Rules are listed in numeric order starting at position 1. Rules can be added to or removed from specific positions in a similar manner to how iptables rules can be added to and removed from a specific chain.
The Black Hole Resolver
The black hole resolver can be used to prevent queries from being resolved. It handles all query types and will prevent resolvers defined after it from being used. The black hole resolver is specified by using the black-hole
keyword.
The Upstream Resolver
An upstream resolver can be used by specifying either an IPv4 or IPv6 address. When Metasploit uses this resolver, the defined host will be contacted over the network. A session can optionally be defined through which network traffic will be sent.
The System Resolver
The system resolver can be used for hostname resolution to either IPv4 or IPv6 addresses by invoking the host operating system’s API. This is particularly useful in cases where the system’s API is expected to be hooked by an external entity such as proxychains. The system resolver is specified by using the system
keyword. Queries that can not be fulfilled by simply translating the query name to an IP address (e.g. PTR, TXT and SRV queries) will use the next resolver that is configured in the rule.
The Static Resolver
The static resolver can be used for hostname resolution to either IPv4 or IPv6 addresses through a static mapping that is configured within Metasploit. This functionality is analogous to the hosts
file found on many systems which defines static hostname to IP address associations. The static resolver is specified by using the static
keyword. Queries that can not be fulfilled by simply translating the query name to an IP address (e.g. PTR, TXT and SRV queries) will use the next resolver that is configured in the rule.
See Static DNS Entries for configuring static entries.
Example Rules
Define a single rule in the first position to handle all queries through three resolvers, first checking if there is a static entry in Metasploit then using the system resolver and finally specifying an upstream DNS server to handle any other query type.
dns add --index 1 --rule * static system 192.0.2.1
Append a rule to the end that will handle all queries for *.lab.lan
using an upstream server contacted through session 1.
dns add --rule *.lab.lan --session 1 192.0.2.1
Append a rule to drop all queries for *.noresolve.lan
using the black hole resolver.
dns add --rule *.noresolve.lan black-hole
Static DNS Entries
Static entries used by the static resolver are configured through the add-static
and remove-static
subcommands. The currently configured entries can be viewed in the dns print
output and all entries can be flushed with the flush-static
subcommand. Static entries that are configured are shared across all rules in which a static resolver is specified. In order for the static entry to be used, at least one rule must match the hostname, and that rule must be configured to use the static resolver. A single hostname can be associated with multiple IP addresses and the same IP address can be associated with multiple hostnames.
Example Static Entries
Define static entries for localhost
and common variations.
dns add-static localhost 127.0.0.1 ::1
dns add-static localhost4 127.0.0.1
dns add-static localhost6 ::1
Remove all static entries for localhost
.
dns remove-static localhost
Remove all static entries.
dns flush-static
The DNS Cache
DNS query replies are cached internally by Metasploit based on their TTL. This intends to minimize the amount of network traffic required to perform the necessary lookups. The number of query replies that are currently cached is available in the dns print
output and all replies can be flushed with the flush-cache
subcommand.
Configuration Management
The DNS configuration can be saved using the save
command from the msfconsole
command context. Once saved, the settings will be automatically restored the next time Metasploit starts up. Any changes that are made at runtime will be lost when Metasploit exits, unless the save
command is used.
Resetting the Configuration
The DNS configuration can be restored to the default state by using the reset-config
subcommand. The default configuration:
- Populates the static entries from the host operating system’s
hosts
file - Defines a single rule that matches all query names whose first resolver is the
static
resolver and the remaining resolvers are set from the host operating systems’ resolv.conf file
Resolving hostnames
The resolve
subcommand can be used to resolve a hostname to either an IPv4 or IPv6 address. In doing so, the rule that was used to define the resolvers will be printed allowing the wildcard matching logic to be tested.