Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement native DNS for Msf Namespace #6611

Merged
merged 43 commits into from
Jan 23, 2018

Conversation

sempervictus
Copy link
Contributor

Built atop the Rex::Proto::DNS work to implement mixins for client
and server functionality, providing common interfaces for querying
domain name servers, and providing domain name services to clients
across Rex sockets. Fully functional native DNS server module is
included to demonstrate functionality, serve as a spoofing DNS
server, a collecting proxy, or any other number of DNS functions.


At the core of this work is a Rex::Proto::DNS::Resolver object
descended from Net::DNS::Resolver with overrides and alterations
for using Rex sockets. The sockets implementation has been in use
internally for a number of years and is well tested. Changes have
been made to provider better interface for higher level components.

The resolver provides forward lookup capability for the server
(Rex::Proto::DNS::Server) which also implements a self-pruning
Cache subclass capable of holding static entries. The server can
operate in TCP or UDP mode, and provides a common abstraction for
addressing TCP and UDP clients by passing a Rex::Socket::Udp
mock client around with the data object to higher level consumers.
Finally, as is standard practice when building full service objects
from Rex to Msf, the server allows consumers to efficiently take
execution control at the request and response handlers by passing
Procs into the constructor (or manually assigning at runtime) for
execution instead of the default call chain.

The service, lookup, and caching functionality is encapsulated and
stands on its own to be used by consumers other than the standard
Msf::Exploit::Remote namespaces. It is intended to serve as the
driver and transport handler for pending DNS tunnel transports,
and can be used by exploit and auxiliary modules directly.


The Msf::Exploit::Remote namespace receives DNS, DNS::Client, and
DNS::Server mixins providing common interfaces for Rex::Proto::DNS
objects. These mixins create convenience methods for executing
queries, serving requests, and configuring the Rex providers.

DNS::Client mixin attempts to "intelligently" configure the client
resolver's name servers and options from the data store. Accessor,
query, and configuration methods are provided in this mixin. Of
note are the wildcard and switchdns methods which were adapted
from prior work by others (likely Carlos Perez) which can be used
by numerous consumer modules. Consumers should use setup_client
during their run call to ensure the resolver is appropriately
configured.

DNS::Server mixin creates common service wrappers for modules to
utilize along with a configuration mechanism analagous to the
one used by the Client mixin, called setup_server, and calling
the setup_client method if present. Note that when setup_server
is called, the consumer does not need to call setup_resolver.


At the framework module level, a native dns server is provided
to showcase the mixin functionality and provide everything from
normal DNS services, to tunneling proxies (with cache disabled),
spoofing services, and MITM functionality via the handler Procs
for requests and responses.

Use auxiliary/server/dns/native_server to get started.


Testing:
Basic local testing completed.
Needs to be checked for info leaks - we used to leak a lot.
Needs to be checked for functionality under varying configs.

Notes:
We have a serious problem with the datastore somewhere in the
Msf namespace. Datastore options must be validated with
options.validate(datastore) or they are all Strings, which
completely destroys any type-dependent logic consuming
datastore values. This must be addressed separately and all
calls to options.validate(datastore) should be removed (other
work has included such calls as well, this just proved that
the problem exists upstream).

Future work:
Implement sessions transports atop the DNS infrastructure in
order to provide native DNS tunneling.

@waffleio-r7 waffleio-r7 changed the title Implement native DNS for Msf Namespace Implement native DNS for Msf Namespace Feb 25, 2016
@sempervictus
Copy link
Contributor Author

Here's a basic RC script for others wishing to test functionality:

<ruby binding="test">
def test
  `nslookup metasploit.com localhost`
  `nslookup rapid7.com localhost`
  `nslookup metasploit.com localhost`
  `nslookup rapid7.com localhost`
  framework.jobs.values.select {|v| v.name == "Auxiliary: server/dns/native_server" }.map &:stop
end
</ruby>
use auxiliary/server/dns/native_server
set VERBOSE true
show options
exploit -j
<ruby binding="test">
test
</ruby>
# Stop caching
set DISABLE_NS_CACHE true
exploit -j
<ruby binding="test">
test
</ruby>
# Set static entries
set STATIC_ENTRIES 1.1.1.1 rapid7.com; 1.1.1.2 metasploit.com
exploit -j
<ruby binding="test">
test
</ruby>
# Stop resolving upstream
set DISABLE_RESOLVER true
exploit -j
<ruby binding="test">
test
</ruby>

It uses block binding functionality in the RC handler to carry the method defined from the beginning, in case anyone missed that feature.
Far as results go, you should see something along the lines of:

msf > resource dns.rc 
[*] Processing /tmp/dns.rc for ERB directives.
resource (/tmp/dns.rc)> use auxiliary/server/dns/native_server
resource (/tmp/dns.rc)> set VERBOSE true
VERBOSE => true
resource (/tmp/dns.rc)> show options

Module options (auxiliary/server/dns/native_server):

   Name              Current Setting  Required  Description
   ----              ---------------  --------  -----------
   DISABLE_NS_CACHE  false            no        Disable DNS response caching
   DISABLE_RESOLVER  false            no        Disable DNS request forwarding
   DOMAIN                             no        The target domain name
   NS                                 no        Specify the nameservers to use for queries, space separated
   Proxies                            no        A proxy chain of format type:host:port[,type:host:port][...]
   RPORT             53               yes       The target port
   SEARCHLIST                         no        DNS domain search list, comma separated
   SRVHOST           0.0.0.0          yes       The local host to listen on.
   SRVPORT           53               yes       The local port to listen on.
   STATIC_ENTRIES                     no        DNS domain search list (hosts file or space/semicolon separate entries)
   THREADS           1                yes       Number of threads to use in threaded queries

resource (/tmp/dns.rc)> exploit -j
[*] Auxiliary module running as background job
[*] resource (/tmp/dns.rc)> Ruby Code (260 bytes)

[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:33601
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.235 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.219 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.66 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.166 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.143 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.80 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.244 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.185 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Sending response for metasploit.com. to 127.0.0.1:33601
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:46256
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Caching response rapid7.com.:204.246.169.38 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Sending response for rapid7.com. to 127.0.0.1:46256
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:58639
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.235 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.219 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.66 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.166 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.143 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.80 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.244 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for metasploit.com.:54.230.38.185 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Sending response for  to 127.0.0.1:58639
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:57578
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Cache hit for rapid7.com.:204.246.169.38 A
[*] [2016.02.26-00:42:51] 10.218.2.102:53 - Sending response for  to 127.0.0.1:57578
resource (/tmp/dns.rc)> set DISABLE_NS_CACHE true
DISABLE_NS_CACHE => true
resource (/tmp/dns.rc)> exploit -j
[*] Auxiliary module running as background job
[*] resource (/tmp/dns.rc)> Ruby Code (5 bytes)
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:55497
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.80 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.166 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.219 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.185 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.235 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.66 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.244 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.143 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Sending response for metasploit.com. to 127.0.0.1:55497
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:55446
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response rapid7.com.:204.246.169.38 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Sending response for rapid7.com. to 127.0.0.1:55446
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:41065
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.185 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.166 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.219 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.80 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.235 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.244 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.143 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response metasploit.com.:54.230.38.66 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Sending response for metasploit.com. to 127.0.0.1:41065
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:33979
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Caching response rapid7.com.:204.246.169.38 A
[*] [2016.02.26-00:42:56] 10.218.2.102:53 - Sending response for rapid7.com. to 127.0.0.1:33979
resource (/tmp/dns.rc)> set STATIC_ENTRIES 1.1.1.1 rapid7.com; 1.1.1.2 metasploit.com
STATIC_ENTRIES => 1.1.1.1 rapid7.com; 1.1.1.2 metasploit.com
resource (/tmp/dns.rc)> exploit -j
[*] Auxiliary module running as background job
[*] resource (/tmp/dns.rc)> Ruby Code (5 bytes)
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:36367
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Cache hit for metasploit.com.:1.1.1.2 A
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Sending response for  to 127.0.0.1:36367
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:47183
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Cache hit for rapid7.com.:1.1.1.1 A
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Sending response for  to 127.0.0.1:47183
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:53208
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Cache hit for metasploit.com.:1.1.1.2 A
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Sending response for  to 127.0.0.1:53208
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:48289
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Cache hit for rapid7.com.:1.1.1.1 A
[*] [2016.02.26-00:43:01] 10.218.2.102:53 - Sending response for  to 127.0.0.1:48289
resource (/tmp/dns.rc)> set DISABLE_RESOLVER true
DISABLE_RESOLVER => true
resource (/tmp/dns.rc)> exploit -j
[*] Auxiliary module running as background job
[*] resource (/tmp/dns.rc)> Ruby Code (5 bytes)
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:47647
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Cache hit for metasploit.com.:1.1.1.2 A
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Sending response for  to 127.0.0.1:47647
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:56248
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Cache hit for rapid7.com.:1.1.1.1 A
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Sending response for  to 127.0.0.1:56248
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Received request for metasploit.com. from 127.0.0.1:56246
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Cache hit for metasploit.com.:1.1.1.2 A
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Sending response for  to 127.0.0.1:56246
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Received request for rapid7.com. from 127.0.0.1:55802
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Cache hit for rapid7.com.:1.1.1.1 A
[*] [2016.02.26-00:43:06] 10.218.2.102:53 - Sending response for  to 127.0.0.1:55802

@sempervictus
Copy link
Contributor Author

@hdm: i've addressed some of the concerns you brought up regarding interface and caller convention. Procs are sane now, and comm and context should be getting properly interpreted. SocketServer mixin seems a healthy way to address the Msf::Exploit side of things (thoughts welcome).

I am having trouble mapping the sockets to a remote host though - have a system meterp shell on a 2k8r2 host and i can't seem to bind either by setting the ListenerComm or by adding an explicit route and trying to let the switchboard figure it out. Could use a few more eyeballs on the parts of the code handling that. Here's what i'm seeing now:

(2016-02-28)18:35 (S:1 J:4)msf  auxiliary(native_server) > exploit 

[-] [2016.02.28-18:35:04] 10.218.2.102:53 - Auxiliary failed: TypeError no implicit conversion of Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::UdpChannel into IO
[-] [2016.02.28-18:35:04] 10.218.2.102:53 - Call stack:
[-] [2016.02.28-18:35:04] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/rex/proto/dns/server.rb:307:in `select'
[-] [2016.02.28-18:35:04] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/rex/proto/dns/server.rb:307:in `monitor_listener'
[-] [2016.02.28-18:35:04] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/rex/proto/dns/server.rb:193:in `block in start'
[-] [2016.02.28-18:35:04] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/rex/thread_factory.rb:22:in `call'
[-] [2016.02.28-18:35:04] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/rex/thread_factory.rb:22:in `block in spawn'
[-] [2016.02.28-18:35:04] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/msf/core/thread_manager.rb:100:in `call'
[-] [2016.02.28-18:35:04] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/msf/core/thread_manager.rb:100:in `block in spawn'
[*] Auxiliary module execution completed
(2016-02-28)18:35 (S:1 J:4)msf  auxiliary(native_server) > set DNS_SERVER_TCP true
DNS_SERVER_TCP => true
(2016-02-28)18:35 (S:1 J:4)msf  auxiliary(native_server) > set DNS_SERVER_UDP false
DNS_SERVER_UDP => false
(2016-02-28)18:35 (S:1 J:4)msf  auxiliary(native_server) > exploit 

[-] [2016.02.28-18:35:18] 10.218.2.102:53 - Auxiliary failed: NoMethodError undefined method `on_client_data_proc=' for #<Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel:0x007f766da8f350>
[-] [2016.02.28-18:35:18] 10.218.2.102:53 - Call stack:
[-] [2016.02.28-18:35:18] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/rex/proto/dns/server.rb:199:in `start'
[-] [2016.02.28-18:35:18] 10.218.2.102:53 -   /opt/metasploit4/msf4/lib/msf/core/exploit/dns/server.rb:132:in `start_service'
[-] [2016.02.28-18:35:18] 10.218.2.102:53 -   /opt/metasploit4/msf4/modules/auxiliary/server/dns/native_server.rb:37:in `run'
[*] Auxiliary module execution completed

In pry:

service.tcp_sock
=> #<Rex::Post::Meterpreter::Extensions::Stdapi::Net::SocketSubsystem::TcpServerChannel:0x000000042329a0
 @cid=3,
 @client=#<Session:meterpreter 99.99.99.99:52303 (10.218.2.102) "NT AUTHORITY\SYSTEM @ WIN-GNQRPNM5AIH">,
 @flags=1,
 @params=
  #<Rex::Socket::Parameters:0x00000004255770
   @bare=false,
   @comm=#<Session:meterpreter 99.99.99.99:52303 (10.218.2.102) "NT AUTHORITY\SYSTEM @ WIN-GNQRPNM5AIH">,
   @context=
    {"Msf"=>#<Framework (1 sessions, 4 jobs, 9 plugins, postgresql database active)>,
     "MsfExploit"=>
      #<Module:auxiliary/server/dns/native_server datastore=[{"VERBOSE"=>true, "SSL"=>false, "SSLVersion"=>"TLS1", "SSLVerifyMode"=>"PEER", "ConnectTimeout"=>10, "TCP::max_send_size"=>0, "TCP::send_delay"=>0, "RPORT"=>53, "THREADS"=>1, "DNS_CLIENT_DEFAULT_NS"=>"8.8.8.8 8.8.4.4", "DNS_CLIENT_RETRY"=>2, "DNS_CLIENT_RETRY_INTERVAL"=>2, "DNS_CLIENT_REPORT_A_RECORDS"=>true, "DNS_CLIENT_RVL_EXISTING_ONLY"=>true, "DNS_CLIENT_TCP_DNS"=>false, "DNS_CLIENT_RESOLVCONF"=>"/dev/null", "SRVHOST"=>"10.218.2.102", "SRVPORT"=>8085, "DISABLE_RESOLVER"=>true, "DISABLE_NS_CACHE"=>true, "DNS_SERVER_UDP"=>false, "DNS_SERVER_TCP"=>true, "STATIC_ENTRIES"=>"1.1.1.1 rapid7.com; 1.1.1.2 metasploit.com", "CPORT"=>0}]>},
   @localhost="10.218.2.102",
   @localport=8085,
   @peerhost=nil,
   @peerport=0,
   @proto="tcp",
   @retries=0,
   @server=true,
   @ssl=false,
   @timeout=5,
   @v6=false>,
 @type="stdapi_net_tcp_server">

raise ::EOFError if data.empty?
from = [cli.peerhost, cli.peerport]
dispatch_request(cli, data)
rescue EOFError => e
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main purpose of handling EOFError is to close the client? Would this be better?

ensure
  close_client(cli) if cli

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, its actually self.tcp_sock.close_client(cli) if cli, addressing.

while !queries.empty?
domain, type = queries.shift
running << framework.threads.spawn("Module(#{self.refname})-#{domain} #{type}", false) do |qat|
if block
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there ever a reason to run async without a block? Maybe if you just want to populate the cache?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, lots of queries can be issued, and since the cache, server, and resolver components can all be shimmed to do "other things," its useful to have the async behavior in each tier.

@sempervictus
Copy link
Contributor Author

Rebased off current master for ease of testing.

A bit confused about what CI wants from me, the prior fail said:

[*] Running msftidy.rb in ./.git/hooks/post-merge mode
--- Checking new and changed module syntax with tools/dev/msftidy.rb ---
modules/auxiliary/server/dns/native_server.rb - [WARNING] Please use Metasploit as a class name (you used Metasploit3)
------------------------------------------------------------------------
------------------------------------------------------------------------
[*] This merge contains modules failing msftidy.rb
[*] Please fix this if you intend to publish these
[*] modules to a popular metasploit-framework repo
------------------------------------------------------------------------

and accordingly, i changed the class name to Metasploit.
My repo has all the modules as MetasploitModule so i've changed it here as well, and re-pushed for CI. If this works, we may want to update that warning message.

@sempervictus
Copy link
Contributor Author

Msftidy error message was broken, should be fixed now.

@bcook-r7
Copy link
Contributor

You might want to pull again, the msftidy message was fixed in master a few hours ago.

@sempervictus
Copy link
Contributor Author

Rolled back to pre-msftidy commit, rebased, repushed.
I'd love to see this merged as being open is a blocker for use in #6187 unless we want the arduous task of adding commits to that line of work atop this stuff.

RageLtMan added 8 commits June 23, 2017 19:58
In order to handle TCP and UDP clients in a common manner, the
DNS server created a Rex::Socket::Udp object to represent the
client object allowing for a client.write(response) approach to
returning results for both TCP and UDP clients. During work on
the common socket abstractions (rapid7#6692) it became apparent that
remote pivoted sockets cannot be created with the same exact param
set used on the server socket - sockets dont reuse with localhost
and localport params being the same, an exception is raised from
the Windows side of the pivot abstraction. Creating a new socket
for every request is also needless overhead and noise.

Create the MockDnsClient class to  consume peerhost, peerport, and
the DNS server's UDP socket as arguments in order to execute a
sendto() from the existing socket when sending a response. A write
method is provided in the class for common interface between the
UDP and TCP request handlers.

This has been tested in conjunction with rapid7#6692 and shown to be
successful as serving remote requests from the IO.select polled
pivot socket running on a Windows host via Meterpreter.
Add convenience method for using the @dns_resolver instance var
via call to :client, which also performs resolver setup if none
exists when called.
Import PCAP-based DNS spoofing server module:
This module uses the Capture mixin to sniff and parse packets off
the wire, then match answers to sniffed requests from static
entries in the server's cache. If answers are found, they are
appended to a cloned packet with reverse saddr/daddr pairs at
layers 2-4, the qr bit is set, and it is injected back into the
interface from where it came.

Minor cleanup in the Rex::Proto::DNS::Server::Cache class to allow
multiple address->name pairs and fix issues when adding multiple
static entries.
Allow retrieval of '*' from stored static entries for spoofing
all domains to any IP using wildcard names. Replace the wildcard
response with the name submitted to the search in the response.

Fix improper checks in DNS::Packet for Resolv objects from decode
to encode.

Misc cleanup for records not responding to :address, convenience
methods, and packet structure.
Move all output lines out of the execution path in order to reduce
execution time and help win the race against the real response.

Update the IP header ID for responses so as not to return the sent
header value on the wire and alert clever IDS.
DNS spoofing module should be feature complete, with forwarding of
requests which do not have cached answers (can be disabled same as
the native server module), empty replies to reduce client wait on
outstanding DNS requests, and post-send output in verbose mode
to reduce garbage and execution time in the critical/racy path.

This module is best used in conditions where MITM is achieved by
way of MAC spoofing, route interception, or compromise of an inline
host on the datapath. The attacker should avoid forwarding
original requests to the intended destination, or if this is not
possible, prevent replies from traversing the MITM space in order
to avoid race conditions between the spoofer and victim.

Example iptables configuration on MITM host:
 iptables -t nat -A POSTROUTING -o eth0 -p udp ! --dport 53 -j ...

Testing:
  Internal testing in Virtualbox local network, atop 802.11, and
mostly in Neutron (with port security disabled on the VIFs) atop
OpenStack Liberty ML2+OVS.
Conversion between packet formats can create empty additional
answers fields, which net-dns cannot handle.

Update net-dns' packet parser to be able to deal with empty arrays
such that it doesn't try to call :data on a nil, which is the only
element of an empty array.

Props to mubix for identifying this issues.
@sempervictus
Copy link
Contributor Author

@mubix discovered that this PR uses a call into Rex::Socket which was previously not available upstream. The change required (and a couple other additions) is in #5 of the socket repo.

Rex' sockets gem now includes the methods used in this PR for
determining if a string represents an IP address, whether it's v4
or 6.

Bump the version contained in Gemfile.lock to permit more testing
@bwatters-r7
Copy link
Contributor

Just leaving this here...... rapid7/metasploit-payloads@master...defcon-russia:master

@sempervictus
Copy link
Contributor Author

sempervictus commented Nov 27, 2017 via email

Dnsruby provides advanced options like DNSSEC in its data format
and is a current and well supported library.
The infrastructure services - resolver, server, etc, were designed
for a standalone configuration, and carry entirely too much weight
and redundancy to implement for this context. Instead of porting
over their native resolver, update the Net::DNS subclassed Rex
Resolver to use Dnsruby data formats and method calls.
Update the Msf namespace infrastructure mixins and native server
module with new method calls and workarounds for some instance
variables having only readers without writers. Implement the Rex
ServerManager to start and stop the DNS service adding relevant
alias methods to the Rex::Proto::DNS::Server class.

Rex services are designed to be modular and lightweight, as well
as implement the sockets, threads, and other low-level interfaces.
Dnsruby's operations classes implement their own threading and
socket semantics, and do not fit with the modular mixin workflow
used throughout Framework. So while the updated resolver can be
seen as adding rubber to the tire fire, converting to dnsruby's
native classes for resolvers, servers, and caches, would be more
like adding oxy acetylene and heavy metals.

Testing:
  Internal tests for resolution of different record types locally
and over pivot sessions.
@sempervictus
Copy link
Contributor Author

@bwatters-r7: could you take another look at this? Probably added some corner case breakage, but it's dnsruby now (data fmt only).

@sempervictus
Copy link
Contributor Author

Did Travis give up on me, or is this just old enough that its config laughs and ignores the updates?

@busterb
Copy link
Member

busterb commented Jan 18, 2018

Looks like you simply have gemfile conflicts

@busterb busterb self-assigned this Jan 18, 2018
@busterb busterb merged commit de411e7 into rapid7:master Jan 23, 2018
@busterb
Copy link
Member

busterb commented Jan 23, 2018

Added these following commits to the merge:

afaf832 - remove verbose error from library, bubble consistent exceptions to the module instead (3 minutes ago)
a6e5944 - fix msftidy, add nicer errors on bind failure (17 minutes ago)
84b463f - dnsruby is already a dependency (18 minutes ago)

@busterb
Copy link
Member

busterb commented Jan 23, 2018

Release Notes

Native DNS support is now available as a Rex protocol library that proxies for the dnsruby gem, module mixins, and a pair of sample auxiliary modules. You can store static entries, resolve names over pivots, serve DNS requests across routed session comms, and perform DNS spoofing attacks.

@busterb
Copy link
Member

busterb commented Jan 23, 2018

Thanks @sempervictus!

@sempervictus
Copy link
Contributor Author

Its like watching your kids go off to college. Thanks for getting this in.
Max and Alex of defconrussia found a fun fact - dnsruby doesn't encap ALL message functionality in the Message class, so expect PRs porting dnssec code from their resolver class to our packet class.

jmartin-tech pushed a commit to jmartin-tech/metasploit-framework that referenced this pull request Jan 24, 2018
jmartin-tech pushed a commit to jmartin-tech/metasploit-framework that referenced this pull request Jan 24, 2018
@allrosenthal-r7 allrosenthal-r7 added the rn-enhancement release notes enhancement label Feb 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants