ebCTF 2013: Network challenges: NET100, NET200, NET300
NET100: index.php?-s: Post-attack network log analysis
OMG, Eindbazen got hacked. Can you figure out what this evil hacker did?
http://ebctf.nl/files/da021f41e137fa42501586915d677752/net-100.pcap
For this first networking exercise, we will analyse network logs of an attack against Eindbazen to find what the attacker could do! We are given a clean pcap of the whole attack.
First thing we can notice, is a long UDP “stream” between the attacker and the target. Just before the attack, a POST was done on the web server hosted by the target. You can find the uploaded php script here. We didn’t spend too much time on it since it looked like a “command receiver on UDP”, which was enough information to continue analysing the logs.
Apart from the UDP stream, we could notice kerberos and ssh traffic, not that
interesting, and a GET from the target to the attacker, of a file named
rootkit.zip
, quite interesting! We fetched the file but it was password
protected. Let’s continue digging.
Back at the UDP stream, we searched for commands related to rootkit.zip and
found this interesting part of the stream where we can see the zip file being
unzip’ed. Follows what looks like commands to send the password to unzip
command, letter by letter: alongpassword1234
.
This password unlocked the zip file, in which we found a file flag.txt,
containing “Instead of a rootkit we will just give you a flag:
ebCTF{b78dc61ce895a3856f3520e41c07b1be}
”.
Done!
NET200: Who’s there
We found this strange website.
http://54.216.81.14/
This website only contains:
112 + 386 + 712 + 1398 + 8771 + 11982 + 15397 + 23984 = 51037
After wondering a while what this addition was supposed to mean (especially since it was wrong and should give the result 62742), we noticed that all these numbers were in the valid port range. That’s when the semantic of this operation struck us: a collection of 8 ports giving a final port, this is exactly the principle of port-knocking.
The idea of this technique is to open a port only for a given client after he knockes to a pre-defined number of ports in the right order, which is only known by the server and the trusted users of the protected service.
So we can execute this first series with a simple netcat:
$ for port in 112 386 712 1398 8771 11982 15397 23984; do
> netcat -v 54.216.81.14 $port
> done
netcat: unable to connect to address 54.216.81.14, service 112
netcat: unable to connect to address 54.216.81.14, service 386
[...]
netcat: ec2-54-216-81-14.eu-west-1.compute.amazonaws.com (54.216.81.14) 51037 [51037] open
So you are knocking me, how about I return the favor?
Repeat after me and I will open the last port...
Is it knocking us back and expecting we mimic it? We can confirm that with
tcpdump
:
# tcpdump -n -i eth0 'src host 54.216.81.14'
16:25:22.867635 IP 54.216.81.14.1337 > 163.5.55.17.8112: Flags [S], seq 0, win 8192, length 0
16:25:23.869346 IP 54.216.81.14.1337 > 163.5.55.17.33386: Flags [S], seq 0, win 8192, length 0
16:25:24.874334 IP 54.216.81.14.1337 > 163.5.55.17.14712: Flags [S], seq 0, win 8192, length 0
16:25:25.882108 IP 54.216.81.14.1337 > 163.5.55.17.4398: Flags [S], seq 0, win 8192, length 0
16:25:26.885593 IP 54.216.81.14.1337 > 163.5.55.17.1771: Flags [S], seq 0, win 8192, length 0
16:25:27.889869 IP 54.216.81.14.1337 > 163.5.55.17.52313: Flags [S], seq 0, win 8192, length 0
16:25:28.894443 IP 54.216.81.14.1337 > 163.5.55.17.25697: Flags [S], seq 0, win 8192, length 0
16:25:29.900296 IP 54.216.81.14.1337 > 163.5.55.17.932: Flags [S], seq 0, win 8192, length 0
16:25:30.905643 IP 54.216.81.14.1337 > 163.5.55.17.22222: Flags [S], seq 0, win 8192, length 0
OK, so let’s ping it on these exact same ports in that order. But this time,
while the service was rejecting instantly all of our SYN
TCP packets in the
first series with a RST
, for this new series, it seems to drop half of the
packets and to reject the other half with RST
. Thus, our previous super cool
for-loop got stuck in the middle and caused the whole series to fail. So we just
changed it to launch the netcat in background and it worked perfectly. This
time the 22222 port replied with this message:
[Advanced]
sequence = 234,781,983,2411,9781,14954,23112,63991
seq_timeout = 15
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 32154 -j ACCEPT
tcpflags = fin,urg,!ack
cmd_timeout = 30
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 32154 -j ACCEPT
We recognized it was a chunk of configuration for the knockd
daemon,
which can be used to setup port-knocking on a UNIX host. It is easy to read, we
just have to knock to another series of ports given by the sequence
option
with the appropriate TCP flags, specified by the tcpflags
option, and we will
be given access to the port 32154.
This time, we could not use netcat
because it does not allow us to specify
arbitrary TCP flags, but, since we already had a script ready for the NET300
challenge using Scapy, we also used it for this new series:
from scapy.all import *
ports = [234,781,983,2411,9781,14954,23112,63991]
for p in ports:
print(send(IP(dst="54.216.81.14")/TCP(dport=p,flags="FU")))
And just connected normally to the final port which gave us the flag of this challenge:
$ netcat -v 54.216.81.14 32154
netcat: ec2-54-216-81-14.eu-west-1.compute.amazonaws.com (54.216.81.14) 32154 [32154] open
ebCTF{32c64f2542ba4566acff750196ca2e13}
NET300: Hop on a plane!
We found this website which uses a location based access control system.
Hop on a plane and hit all target zones!
http://54.212.115.245/
What we understood was that this service tries to locate us by pinging our IP from three servers located in the US, in Brazil and in Japan and display our approximate location on the map. The goal is to make that location change by delaying the ping replies we send back to these three servers and make it hop in each of the three circles on the map.
A few of us tried to look for ways to do that using iptables
or the traffic
control in the kernel but it was impossible with the first one and it took them
a long time with the second one.
Meanwhile, we tried to use the scapy
Python module to reply to the pings
instead of the kernel. We first tried to prevent the kernel from answering,
but dropping the ICMP packets with iptables
didn’t work, apparently because
the answering part is lower than iptables
in the network stack of the Linux
kernel in order to make these replies fast. So we decided to disable these
replies globally by enabling the net.ipv4.icmp_echo_ignore_all
.
Then, we wrote the Scapy script to respond to ping requests with fine
adjustment of time.sleep()
before our replies in function of which of the
three servers we were replying. This script did work great but the results were
really random due to network latency and probably our strange solution of
replying to pings in userland. So now we had a plane that randomly wandered all
over the map… ok great…
We tried to adjust the time.sleep
parameter but the result was just too
random to be useful. Another problem was that the sleeps accumulated over our
replies because scapy
queues the requests so we were accumulating requests too
much and, after a while, were answering with more than one minute of delay.
So to fix these problems, we decided to modify the script to spawn threads for the replies, to avoid the accumulation of sleeps, so we could have big delay time (30 seconds or so) that would allow us to compensate the random network delay and finely tune the delays to reach exactly the appropriate locations. But we first modified the first script to make the delays totally random and launched it in background, just in case…
from scapy.all import *
import time, random
SRC = ["54.212.115.245", "54.232.216.98", "54.250.176.246"]
def callback(pkt):
if pkt[IP].proto == 1 and pkt[IP].src in SRC:
if pkt[IP].src in SRC:
time.sleep(random.randint(0,400)/1000.0)
send(IP(dst=pkt[IP].src)/ICMP(type=0, id=0, seq=0)/Raw(load=pkt[Raw].load))
sniff(prn=callback, filter="(src host 54.212.115.245 or src host 54.232.216.98 or src host 54.250.176.246) and icmp", store=0)
And it worked, before we could finish the new script, the first one made us
reach the three circles successfully, giving us the flag:
ebCTF{9bd26cbffa30c0ea32c425df220f06b9}
.