2

I would like to send via network (LAN) a classic DHCP Discover package using command line, in order to trigger a response from any DHCP server listening, so I could capture it with something like (say my IP address is 192.168.0.30 ):

tcpdump -i eth0 host 192.168.0.30 -n -s 0 -vvv -w listening.pcap

I think about this as a simple method to detect rogue DHCP servers on a network.

How can I do this using Bash ?

Further data:

Sopalajo de Arrierez
  • 3,543
  • 4
  • 34
  • 52
  • Your question is better suited to [Unix & Linux Stack Exchange](http://unix.stackexchange.com/tour). This page is dedicated to questions about software development. – Cyrus May 29 '20 at 18:34
  • No problem for me on moving to http://unix.stackexchange.com , @Cyrus . But I would rather say that manually forging a bytes sequence and replicating what a program can do is a (simple, of course) programming thing. And the linked question (the WOL one) is a very close matter, and it keeps on https://stackoverflow.com as time goes by. – Sopalajo de Arrierez May 29 '20 at 18:57
  • Use `socat` with `IP-SENDTO` and `IP-RECV`. Realy, DHCPDISCOVER is a normal udp packet, so even you have linked a question that uses netcat with udp, so why didn't you try it? – KamilCuk Jun 01 '20 at 10:08
  • As long as you want to capture only DHCP traffic, I suggest adding `udp port 67` to the `tcpdump` command: `tcpdump -i eth0 udp port 67 -n -s 0 -vvv -w listening.pcap` . Note that there is no need to specify host IP (actually, it is even better to increase scope, I would say). – Sopalajo de Arrierez Jun 03 '20 at 00:39
  • Fyi, [`busybox`](https://busybox.net/) has a [`udhcpc`](https://udhcp.busybox.net/) command. Not as simple as netcat, sed, and grep. But could be useful in some situations. – mpb Jun 30 '23 at 20:29

3 Answers3

4

Full Solution

The solution is similar to 'hacker' with the difference that the UDP Discover package will be generated manually in the shell.

The code is only intended to replace the given MAC of the network card with the form of spaces instead of colons and assigning to a variable (type in Bash):

# manualy:
MAC=ab:ab:ab:ab:ab:ab; MAC=`printf "$(echo $MAC | sed 's/:/ /g')%.0s"`
# or automaticaly: 
MAC=`printf "$(echo $(ifconfig -a |awk -v RS= '/eth0/' |awk '/ether/ {print($2)}') | sed 's/:/ /g')%.0s"`
# or simply type (spaces instead of colons!):
MAC="a6 a6 a6 a6 a6 a6"

Using xxd generate a file containing the DHCPDISCOVER package ready to be sent. I use the fact that the checksum is not checked in practice by all DHCP servers. This avoids significant complications with the checksum calculation and its recording. The only element that needs to be changed is the MAC of the network card.
The site was very helpful: DHCP (in Russian)

echo -e $(echo -n -e "01 01 06 00 62 48 94 CA 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 $MAC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 35 01 01 FF") |xxd -r -p >blobfile

For the DHCPDISCOVER packet to reach the DHCP server without distortion, it must be sent as binary data. Unfortunately, Bash receives some binary sequences as control commands.

HEX codes from 00 to 1F are the range for control characters, different depending on the system. Many of them will be interpreted by BASH, e.g. 1F, 0d etc. Added to this are control sequences, e.g. 082008 or 610860.

MAC addresses are theoretically 16777216, they usually contain parts identifying the manufacturer and hardware. There are more and more producers, also computers, there is also the practice of assigning imaginary or generating random MAC addresses. The chance of using control characters is therefore considerable.

This excludes the use of echo Bash*. We will use cat.

cat blobfile | nc -w1 -u -b 255.255.255.255 67

A fragment of the result from Wireshark:

Client MAC address: ab:ab:ab:ab:ab:ab (ab:ab:ab:ab:ab:ab)
Option: (53) DHCP Message Type (Discover)

The solution boils down to 2 lines of code using only cat and xxd and netcat assuming manually entering the MAC address in the shell.

I didn't find a way to make Bash immune to binary data without breaking it. That is why I suggest excluding it from the package sending phase It may make sense to write the generator in C which will get rid of redirection to the file and the cat program and pack everything into 1 line. However, this is not the subject of the question.

EDIT:

The solution to the Bash problem is to install the rc shell from Plan 9. It is very small (96kB), fast, and most importantly, does not interpret binary characters as controlling. I checked on the standard version rc 1.7.4-1 Debian Linux available via apt. Now just follow the instructions below to send the correct DHCP Discover packet without using cat and the stub file, only shell and xxd and nc.

MAC='08 20 08 1f 0d ff'
echo -n -e "01 01 06 00 62 48 94 CA 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 $MAC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 35 01 01 FF" |xxd -r -p | nc -w1 -u -b 255.255.255.255 67
Slawomir Dziuba
  • 1,265
  • 1
  • 6
  • 13
  • Could you please explain where is the MAC `ab:ab:ab:ab:ab:ab` inserted on the `| xxd -r -p` part? – Sopalajo de Arrierez Jun 02 '20 at 22:40
  • I set it as the Bash MAC variable and then load it into position 29 in the string as $MAC. You should enter the MAC of your network adapter although the packet will be sent with any address. This is the position of the CHADDR field (MAC client) in the packet description in RFC. – Slawomir Dziuba Jun 02 '20 at 23:56
  • Tested working OK. Thanks you, Slawomir. To note (as referred here: https://stackoverflow.com/a/31588036/1461017 ) : if your NetCat version is the BSD one (search for `BSD` at top line when running `man nc`), you need to change it to Traditional package (like doing `apt remove netcat-openbsd && apt install netcat-traditional` ). – Sopalajo de Arrierez Jun 02 '20 at 23:56
  • Thank you for the information, but I don't know what it refers to. I have Debian and netcat-traditional and it works normally. I also have FreeBSD 11.3 and there nc does not have the -b option at all, it sends to broadcast without -b and works normaly. – Slawomir Dziuba Jun 03 '20 at 00:12
  • If you send several packets quickly one after the other, you may need to change 4 bytes to 5 positions to any hex so that there are no packets with the same xid at the same time. This is the XID field in RFC, the unique transaction identifier. – Slawomir Dziuba Jun 03 '20 at 01:09
  • @Sopalajo I added a solution from shell (rc) + xxd + nc – Slawomir Dziuba Jun 04 '20 at 23:06
  • No need in my case (just detecting rogue DHCP Servers) for special MAC. Just some "DD:DD:DD:DD:DD:DD" would enough, since it triggers the same detectable response on the network. But it is good to know for those interested on exactly forging the correct packet. Thanks you, @Slawomir . – Sopalajo de Arrierez Jun 05 '20 at 02:10
2

Replacement solution - in the name of convenience.

Wouldn't it be easier to scan the network for DHCP servers?

# nmap -sU -p 67 --script=dhcp-discover 192.168.43.0/24 |awk -v RS= '/dhcp-discover/'

result:

Starting Nmap 7.40 ( https://nmap.org ) at 2020-05-29 18:38 UTC
Nmap scan report for 192.168.43.1
Host is up (0.0052s latency).
PORT   STATE SERVICE
67/udp open  dhcps
| dhcp-discover: 
|   DHCP Message Type: DHCPACK
|   Server Identifier: 192.168.43.1
|   IP Address Lease Time: 47m22s
|   Subnet Mask: 255.255.255.0
|   Broadcast Address: 192.168.43.255
|   Router: 192.168.43.1
|   Domain Name Server: 192.168.43.1
|_  Vendor Specific Information: ANDROID_METERED
MAC Address: xx:xx:xx:xx:xx:xx (Chiun Mai Communication Systems)

Perhaps it would be more sensible to secure yourself with the use of "dhcp snooping" (layer 2 OSI model ) on the switch, which consists in rejecting any DHCP packets that do not come from a trusted interface.

Slawomir Dziuba
  • 1,265
  • 1
  • 6
  • 13
  • A lot easier. Thanks you for your workaround. But we should address the question itself: manually sending the bytes via NIC from command line. – Sopalajo de Arrierez May 29 '20 at 19:17
  • @Sopalajo-de-Arrierez I have added a UDP packet generator, thus solving the whole task with the note that BASH must be excluded from the packet sending phase. – Slawomir Dziuba Jun 01 '20 at 19:59
  • @Slawomr, as long as you offer different solutions, I suggest for you to split them on different answers. – Sopalajo de Arrierez Jun 02 '20 at 18:08
  • @Sopalajo You're right, I edit the answer, these are poorly documented issues and any solution may be useful to someone. You asked an excellent question about a complex issue, I learned a lot from it. – Slawomir Dziuba Jun 02 '20 at 18:30
1

"Hacker" solution

The question asked raises three issues:

  1. the use of Bash echo
  2. Shipment of the UDP DHCPDISCOVER package
  3. generating the DHCPDISCOVER package

For the DHCPDISCOVER packet to reach the DHCP server without distortion, it must be sent as binary data. Unfortunately, Bash receives some binary sequences as control commands. This excludes the use of echo Bash.

The cat command does not cause this problem as long as the input is from a file (bypassing bash). The package is shipped as follows:

cat blobfile | nc -w1 -u -b 255.255.255.255 67

The package is sent correctly, server DHCP returns the package DHCP Offer. A fragment of the log from tcpdump:

DHCP-Message Option 53, length 1: Discover

and server answer:

DHCP-Message Option 53, length 1: Offer

Where to get the shipping details is a separate matter. I got them by intercepting DHCPDISCOVER shipping using ncat in such a way:

ncat -l -p 67 --udp >blobfile

Having such a block is enough to send DHCPDISCOVER packets and thus solve the basic task.

To be precise, you would have to write the DHCPDISCOVER package generator, unfortunately RFC 2132 and other has a rather complex structure and recording format - see my "full solution".

Community
  • 1
  • 1
Slawomir Dziuba
  • 1,265
  • 1
  • 6
  • 13
  • Tested working on different computers (one sending the DHCPDISCOVER and another capturing-resending it). Same precondition as in your other answer: use `netcat-traditional` package. And (maybe due to that) the correct command to capture for me was: `nc -l -p 67 -u > blobfile` . – Sopalajo de Arrierez Jun 03 '20 at 00:13
  • On RaspBian v10 Buster the `-w1` failed, I don´t know why. Solved by issuing `-w5` . – Sopalajo de Arrierez Jun 03 '20 at 00:14
  • Raspbery is probably too slow and therefore the waiting time of 1s is too short. Maybe test ncat from nmap package, it's the latest nc with bug fixes and new functions added. – Slawomir Dziuba Jun 03 '20 at 00:22