## # 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::Scanner include Msf::Exploit::Capture def initialize super( 'Name' => 'BNAT Scanner', 'Description' => %q{ This module is a scanner which can detect Broken NAT (network address translation) implementations, which could result in a inability to reach ports on remote machines. Typically, these ports will appear in nmap scans as 'filtered'/'closed'. }, 'Author' => [ 'bannedit', 'Jonathan Claudius ', ], 'License' => MSF_LICENSE, 'References' => [ [ 'URL', 'https://github.com/claudijd/bnat'], [ 'URL', 'http://www.slideshare.net/claudijd/dc-skytalk-bnat-hijacking-repairing-broken-communication-channels'] ] ) register_options( [ OptString.new('PORTS', [true, "Ports to scan (e.g. 22-25,80,110-900)", "21,22,23,80,443"]), OptString.new('INTERFACE', [true, "The name of the interface", "eth0"]), OptInt.new('TIMEOUT', [true, "The reply read timeout in milliseconds", 500]) ],self.class) deregister_options('FILTER','PCAPFILE','RHOST','SNAPLEN') end def probe_reply(pcap, to) reply = nil begin Timeout.timeout(to) do pcap.each do |r| pkt = PacketFu::Packet.parse(r) next unless pkt.is_tcp? reply = pkt break end end rescue Timeout::Error end return reply end def generate_probe(ip) ftypes = %w{windows, linux, freebsd} @flavor = ftypes[rand(ftypes.length)] config = PacketFu::Utils.whoami?(:iface => datastore['INTERFACE']) p = PacketFu::TCPPacket.new(:config => config) p.ip_daddr = ip p.tcp_flags.syn = 1 return p end def run_host(ip) open_pcap to = (datastore['TIMEOUT'] || 500).to_f / 1000.0 p = generate_probe(ip) pcap = self.capture ports = Rex::Socket.portspec_crack(datastore['PORTS']) if ports.empty? raise Msf::OptionValidateError.new(['PORTS']) end ports.each_with_index do |port,i| p.tcp_dst = port p.tcp_src = rand(64511)+1024 p.tcp_seq = rand(64511)+1024 p.recalc ackbpf = "tcp [8:4] == 0x#{(p.tcp_seq + 1).to_s(16)}" pcap.setfilter("tcp and tcp[13] == 18 and not host #{ip} and src port #{p.tcp_dst} and dst port #{p.tcp_src} and #{ackbpf}") break unless capture_sendto(p, ip) reply = probe_reply(pcap, to) next if reply.nil? print_status("[BNAT RESPONSE] Requested IP: #{ip} Responding IP: #{reply.ip_saddr} Port: #{reply.tcp_src}") end close_pcap end end