19
Dec
2011

PHD CTF Quals 2011 – Port knocking

This was the challenge which scored us the last couple of points and put us on the second place. We thought a write up would be nice. This challenge gave us some headache, and if you see the final solution it looks so easy, but it was a long way to get there.

The server involved was the 192.168.0.5. After a nmap scan we noticed the server was listening on port 21/tcp, or ftp. The service info also gives us the first clue of the challenge, it was a port knocking exercise.

This is how we solved it.

$ sudo nmap -sS -sV --top-ports 5 192.168.0.5

Starting Nmap 5.21 ( http://nmap.org ) at 2011-12-15 10:16 CET
Nmap scan report for 192.168.0.5
Host is up (0.086s latency).
PORT    STATE  SERVICE VERSION
21/tcp  open   ftp     WU-FTPD or MIT Kerberos ftpd 6.00LS
22/tcp  closed ssh
23/tcp  closed telnet
80/tcp  closed http
443/tcp closed https
Service Info: Host: PKNOCKING; OS: Unix

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 24.37 seconds

The ftp service allowed anonymous login en provided us with a traffic.zip file, which contains a traffic.pcap file. The traffic.pcap file contains traffic of an example connection and how to get the flag. We saw a lot of SYN packages on a lot of ports and then a connection to port 1407 which gave the flag. Our first approach was to replay the pcap file, connect to port 1407 and get the flag. But whatever we tried, this didn’t really work.

During the contest we most of time made some wrong assumptions:

  • All packages sent are part of the port knocking sequence
  • The port to connect to after the sequence is port 1407

This approach didn’t really work out. We took a step back and watch the data again and made an overview of which ports the example session was connecting to.

$ egrep -o '> 192.168.0.5.[0-9]*' traffic.txt | sed -e 's/.*\.//' | sort -n
100
100
235
235
443
443
951
951
1024
1024
1025
1025
1026
...
2047
2047
2048
2048
4826
4826
9402
9402
16821
16821

Here we see that a SYN packet is sent to all ports between 1024 and 2048. Then it occurred to us that these connections probably aren’t part of the port knocking sequence, but just an ordinary port-scan. This made sense, the only port replying with a TCP handshake during the scan was port 1407. So we don’t need to connect to port 1407, but scan for an open port between 1024 and 2048.

With that out of the way, the knocking sequence became also clear, this is the first part of the traffic file:

16:25:46.363289 IP (tos 0x0, ttl 37, id 45164, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.36295 > 192.168.0.5.951: Flags [S], cksum 0x8495 (correct), seq 2209903749, win 2048, options [mss 1460], length 0
16:25:46.765305 IP (tos 0x0, ttl 47, id 30944, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.36296 > 192.168.0.5.951: Flags [S], cksum 0x7c94 (correct), seq 2209969284, win 4096, options [mss 1460], length 0
16:26:04.726031 IP (tos 0x0, ttl 54, id 15617, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.46808 > 192.168.0.5.4826: Flags [S], cksum 0xc152 (correct), seq 4183524848, win 3072, options [mss 1460], length 0
16:26:05.128021 IP (tos 0x0, ttl 49, id 1875, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.46809 > 192.168.0.5.4826: Flags [S], cksum 0xc551 (correct), seq 4183459313, win 2048, options [mss 1460], length 0
16:26:16.690509 IP (tos 0x0, ttl 55, id 54721, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.43720 > 192.168.0.5.9402: Flags [S], cksum 0x7be7 (correct), seq 4265720997, win 4096, options [mss 1460], length 0
16:26:17.092532 IP (tos 0x0, ttl 43, id 11242, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.43721 > 192.168.0.5.9402: Flags [S], cksum 0x7be8 (correct), seq 4265655460, win 4096, options [mss 1460], length 0
16:26:25.225870 IP (tos 0x0, ttl 54, id 11415, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.61466 > 192.168.0.5.235: Flags [S], cksum 0xfa70 (correct), seq 1353764394, win 3072, options [mss 1460], length 0
16:26:25.628217 IP (tos 0x0, ttl 55, id 28462, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.61467 > 192.168.0.5.235: Flags [S], cksum 0xf66d (correct), seq 1353829931, win 4096, options [mss 1460], length 0
16:26:31.487235 IP (tos 0x0, ttl 46, id 24071, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.62859 > 192.168.0.5.16821: Flags [S], cksum 0x825c (correct), seq 3044383550, win 3072, options [mss 1460], length 0
16:26:31.889205 IP (tos 0x0, ttl 42, id 38274, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.62860 > 192.168.0.5.16821: Flags [S], cksum 0x825b (correct), seq 3044318015, win 3072, options [mss 1460], length 0
16:26:38.863503 IP (tos 0x0, ttl 43, id 41207, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.54191 > 192.168.0.5.443: Flags [S], cksum 0x69b8 (correct), seq 1594714145, win 4096, options [mss 1460], length 0
16:26:39.265517 IP (tos 0x0, ttl 38, id 980, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.54192 > 192.168.0.5.443: Flags [S], cksum 0x6db9 (correct), seq 1594648608, win 3072, options [mss 1460], length 0
16:26:46.208820 IP (tos 0x0, ttl 40, id 26933, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.61810 > 192.168.0.5.100: Flags [S], cksum 0x94ce (correct), seq 3723210176, win 1024, options [mss 1460], length 0
16:26:46.610842 IP (tos 0x0, ttl 53, id 60876, offset 0, flags [none], proto TCP (6), length 44)
    192.168.0.127.61811 > 192.168.0.5.100: Flags [S], cksum 0x90cd (correct), seq 3723144641, win 2048, options [mss 1460], length 0
16:27:27.472840 IP (tos 0x0, ttl 39, id 56738, offset 0, flags [none], proto TCP (6), length 44)

So the solution would be:

  • Knock twice on ports 951, 4826, 9402, 235, 16821, 443, 100
  • Scan for an open port between 1024 and 2048
  • Connect to this port and get the flag

We used this fancy script to do exactly that:

#!/usr/bin/python
# sheldon.py
# EINDBAZEN solution to port knocking challenge PHD CTF Quals 2011

# Import scapy
from scapy.all import *
conf.verb = 0
# Ports
ports = [951, 4826, 9402, 235, 16821, 443, 100]
# Knock twice on every port
for dport in range(0, len(ports)):
    print "[*] Knocking on 192.168.0.5: " , ports[dport]
    ip = IP(dst="192.168.0.5")
    port = 39367
    SYN = ip/TCP(sport=port, dport=ports[dport], flags="S", window=2048, options=[('MSS',1460)], seq=0)
    send(SYN) ; print "*KNOCK*"
    port = 39368
    SYN = ip/TCP(sport=port, dport=ports[dport], flags="S", window=2048, options=[('MSS',1460)], seq=0)
    send(SYN) ; print "*KNOCK*"
    print "PENNY"
# Use NMAP for scanning for open ports
# We also use -sV, so nmap connects to the port and get the flag
print "[*] Scanning for open ports using nmap"
subprocess.call("nmap -sS -sV -T4 -p 1024-2048 192.168.0.5", shell=True)

And the output of this script:

$ sudo ./sheldon.py 
[*] Knocking on 192.168.0.5:  951
*KNOCK*
*KNOCK*
PENNY
[*] Knocking on 192.168.0.5:  4826
*KNOCK*
*KNOCK*
PENNY
[*] Knocking on 192.168.0.5:  9402
*KNOCK*
*KNOCK*
PENNY
[*] Knocking on 192.168.0.5:  235
*KNOCK*
*KNOCK*
PENNY
[*] Knocking on 192.168.0.5:  16821
*KNOCK*
*KNOCK*
PENNY
[*] Knocking on 192.168.0.5:  443
*KNOCK*
*KNOCK*
PENNY
[*] Knocking on 192.168.0.5:  100
*KNOCK*
*KNOCK*
PENNY
[*] Scanning for open ports using nmap
Starting Nmap 5.21 ( http://nmap.org ) at 2011-12-13 15:37 CET
Warning: 192.168.0.5 giving up on port because retransmission cap hit (6).
Nmap scan report for 192.168.0.5
Host is up (0.088s latency).
Not shown: 1023 closed ports
PORT     STATE    SERVICE VERSION
1142/tcp open     unknown
2036/tcp filtered unknown
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port1142-TCP:V=5.21%I=7%D=12/13%Time=4EE7635D%P=x86_64-unknown-linux-gnu%r(NULL,28,"flag\x20-\x204c4c22fccb4163fdd7b604809e13b030\n");
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 92.07 seconds

And in the Version check we see “flag – 4c4c22fccb4163fdd7b604809e13b030” as string.

{2 Responses to “PHD CTF Quals 2011 – Port knocking”}

  1. Thank you for this wonderful writeup!
    I’m eager to read others.
    /* can i contact you? */
    Cheers.

    Freezer
  2. sheldon.py, KNOCK-KNOCK, PENNY!

    Haha! good one. 🙂