Network forensics challenge.

Information

  • category : forensics
  • points : 838

Description

Alpha team’s whistleblower captured a packet that leaked internal information to the outside using ftp internal confidential data.

Analyze the packet and flag the password and information obtained for the ftp connection!

Flag format : KorNewbie{password_yougetinformation}

If there is a hash value, it will be md5.

File : vithim.pcap

Writeup

The pcap contains a lot of tcp and http traffics, however we’re interested in the ftp stream (description).

This is the only ftp connection on the pcap:

FTP Stream

We can see that an user inserted as password : root, and uploaded a file badguy.txt.

Why can’t we see the content of the file?

Because ftp send controls over the port 21, and data over the port 20. In fact in wireshark to check the data transmitted with ftp there is another display filter.

FTP-Data Stream

The data is a simple base64 encoded file, let’s decode it :

$ cat evidence.base64 | base64 -d
이보게 알파팀의 신상정보는 밑의 주소에 모두 담아놓았네. 건투를 빌지워터.. 
https://pastebin.com/70yDGiRS

Ok there is some korean text and a pastebin link.

Let’s download the pastebin:

$ curl https://pastebin.com/raw/70yDGiRS --output raw; cat raw
k459iki6m5j094m2lmkhjmi9527l81ml

According to the description we need an md5 password. We can try to ROT the string until it becomes an md5.

#!/usr/bin/env python3

import string

def rot(string, shift):
    cipher = ''
    for char in string: 
        if ord(char) <= 0x41 or (ord(char) >= 0x5b and ord(char) <= 0x60) \
            or ord(char) >= 0x7a:
          cipher = cipher + char
        elif  char.isupper():
            cipher = cipher + chr((ord(char) + shift - 65) % 26 + 65)
        else:
            cipher = cipher + chr((ord(char) + shift - 97) % 26 + 97)
    return cipher

charlist = string.hexdigits.lower()
for i in range(1, 26):
    value = rot(raw, i)
    flag = 0
    for v in value:
        if v not in charlist:
            flag = 1
            break
    if flag == 0:
        print("Is it md5 ? : " + value + "\trot" + str(i) + "\n")

Output:

Is it md5 ? : d459bdb6f5c094f2efdacfb9527e81fe rot19

With rot19 the string is a valid md5. Let’s try to crack it on md5decrypt.

So the information we need is IronDragon.

Let’s try to resume what we did using a python script.

# Stage 0 using a shell:
# tshark -r vithim.pcapng -z follow,tcp,ascii,7 | tail -n 2 | head -n 1 > evidence.base64
#!/usr/bin/env python3

from base64 import b64decode
import string
import os

def rot(string, shift):
    cipher = ''
    for char in string: 
        if ord(char) <= 0x41 or (ord(char) >= 0x5b and ord(char) <= 0x60) \
            or ord(char) >= 0x7a:
          cipher = cipher + char
        elif  char.isupper():
            cipher = cipher + chr((ord(char) + shift - 65) % 26 + 65)
        else:
            cipher = cipher + chr((ord(char) + shift - 97) % 26 + 97)
    return cipher

# Stage 1 read base64 string 
with open("./evidence.base64", "r") as f:
    content = f.read()

# Stage2 decode string and download raw
website = b64decode(content.encode()).decode().replace('.com', '.com/raw')
print("evidence decoded : " + str(website))
website = website.split('\n')[1]
os.system('curl ' + website + ' --output raw.txt')

# Stage 3 rot possible values
with open("./raw.txt", "r") as f:
    raw = f.read()
print("raw downloaded : " + str(raw))
charlist = string.hexdigits.lower()
for i in range(1, 26):
    value = rot(raw, i)
    flag = 0
    for v in value:
        if v not in charlist:
            flag = 1
            break
    if flag == 0:
        print("Is it md5 ? : " + value + "\trot" + str(i) + "\n")

Flag

KorNewbie{root_IronDragon}