Posted by Sander ‘dsc’ Ferdinand under HiTB 2016 CTF with tag(s) CTF

Introduction

This is a write-up for the for100 challenge of the HiTB 2016 CTF.

Some customers complained over the phone over not being able to access the Culinary Tour de Force’s website. They got a strange message and couldn’t make a reservation.

We think the sever might be hacked, but we are not sure, we are chef’s not investigators. You have access to this image .

The chef stored his secret recipe encrypted on this server, we don’t know if the attacker stole the recipe. Could you check if his secrets are safe?

Image file here. Pcap file here

Analysis

The pcap provided contains a combination of HTTPs and SSH traffic.

The image provided is a complete dump of a hard disk, which fdisk identified as OpenBSD.

$ fdisk -lu recipe.img
Disk recipe.img: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders, total 10485760 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

     Device    Boot  Start  End       Blocks   Id  System
recipe.img4    *     64     10474379  5237158  a6  OpenBSD

Mounting

We proceeded by mounting the image with an offset of 32768 (sectors are 512 bytes, 512*64)

mount -o ro,loop,offset=32768,ufstype=44bsd recipe.img mnt1

And got ourselves a partition to gasp at:

$ cd mnt1
$ ls -al mnt1
total 17752
drwxr-xr-x 13 root root  512 Apr 30 13:39 .
drwxr-xr-x  3 dsc  dsc  4096 Jun  2 19:47 ..
-rw-r--r--  1 root root  578 Feb 26 09:07 .cshrc
-rw-r--r--  1 root root  468 Feb 26 09:07 .profile
drwxr-xr-x  2 root root  512 Feb 26 09:07 altroot
drwxr-xr-x  2 root root 1024 Feb 26 09:07 bin
-rw-r--r--  1 root root70964 Apr 30 13:39 boot
-rw-r--r--  1 root root 10245097 Apr 30 15:38 bsd
-rw-r--r--  1 root root  7763412 Apr 30 15:38 bsd.rd
drwxr-xr-x  3 root root19456 May 21 16:15 dev
drwxr-xr-x 26 root root 1536 May 21 16:15 etc
drwxr-xr-x  2 root root  512 Apr 30 15:38 home
drwxr-xr-x  2 root root  512 Feb 26 09:07 mnt
drwx------  3 root root  512 May 21 16:15 root
drwxr-xr-x  2 root root 1536 Feb 26 09:08 sbin
lrwxr-xr-x  1 root root   11 Feb 26 09:07 sys -> usr/src/sys
drwxrwxrwt  6 root root  512 May 21 16:15 tmp
drwxr-xr-x  2 root root  512 Apr 30 15:38 usr
drwxr-xr-x 23 root root  512 Apr 30 14:56 var

First thing we noticed is that /home is empty which confused us. Perhaps this was removed by the attacker. Fortunately the /root folder has some files:

$ ls -al root/
total 24
drwx------  3 root root  512 May 21 16:15 .
drwxr-xr-x 13 root root  512 Apr 30 13:39 ..
-rw-r--r--  1 root root   87 Feb 26 09:07 .Xdefaults
-rw-r--r--  1 root root  578 Feb 26 09:07 .cshrc
-rw-r--r--  1 root root   94 Feb 26 09:07 .cvsrc
-rw-r--r--  1 root root5 Apr 30 13:39 .forward
drwx------  4 root root  512 Apr 30 16:31 .gnupg
-rw-r--r--  1 root root  328 Feb 26 09:07 .login
-rw-------  1 root root 2267 May 21 16:08 .mysql_history
-rw-r--r--  1 root root  536 Apr 30 13:50 .profile
-rwxr-xr-x  1 root root   78 Apr 30 13:46 source.sh

Of which 2 entries are interesting: .gnupg and .mysql_history

Looking at ~/root/.mysql_history we can notice:

show tables;
select * from recipe;
INSERT INTO recipe (id, name,difficulty,FLAG) VALUES (1, 'whipped cream',1,'HITBCTF{FAKEFAKE}');

Unfortunately no easy flag to be found here :-) It does give an impression that perhaps a flag was once stored in the MySQL database.

Looking at ~/root/.gnupg/ we can see 2 private keys, in a legacy format that was unknown to us (and still is). We tried loading these 2 private keys into a local gpg configuration but it wouldn’t load them:

$ gpg --allow-secret-key-import --import 433A76576CCB381536E5602AFF8FAF9DF7CD6F93.key 
gpg: no valid OpenPGP data found.
gpg: Total number processed: 0

I was stuck.

Disk Labels

Our oldest team member doskop most certainly knows about the existence of disk labels but I sure did not, and as such missed the fact OpenBSD disks are quite different from traditional partitions.

Lets see what Wikipedia has to say:

a disklabel is a record stored on a data storage device such 
as a hard disk that contains information about the location 
of the partitions on the disk

We gave the tool Sleuthkit a try, as it claims to have UFS support.

We found our image having multiple disk labels:

$ apt-get install sleuthkit
$ mmls -o 64 recipe.img 
BSD Disk Label
Offset Sector: 64
Units are in 512-byte sectors

     Slot    Start        End          Length       Description
00:  02      0000000000   0010485759   0010485760   Unused (0x00)
01:  Meta    0000000001   0000000001   0000000001   Partition Table
02:  00      0000000064   0001953663   0001953600   4.2BSD (0x07)
03:  01      0001953664   0002477951   0000524288   Swap (0x01)
04:  03      0002477952   0008769407   0006291456   4.2BSD (0x07)
05:  04      0008769408   0010474335   0001704928   4.2BSD (0x07)
06:  -----   0010474336   0010485759   0000011424   Unallocated

Calculate the offsets for the starting point of the 2 remaining disk labels and mount them:

# Slot 03: 2477952 * 512 = 1268711424
# Slot 04: 8769408 * 512 = 4489936896

mount -o ro,loop,offset=1268711424,ufstype=44bsd recipe.img mnt2
mount -o ro,loop,offset=4489936896,ufstype=44bsd recipe.img mnt3

Getting somewhere

We spot a directory called chef in the last disk label. This probably is the home folder we were missing in our first attempt at mounting the disk.

$ ls -LR mnt3/
mnt3:
chef

mnt3/chef:
recipe.txt

mnt3/chef/recipe.txt:
recipe.txt  secret.txt

/chef/recipe.txt/secret.txt and /chef/recipe.txt/recipe.txt sure do look interesting…

$ cat recipe.txt 
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1

hQEMA3j1+8PfYUh9AQf/aUOPv6hY3kSWgCzfibmluHwupA8TSw3UcM+nw35wpmKR
kHl6fNQh0cXW1OncAAYAKIGdoa2x1mdVAlhy0RZ8wbi4z1TIqntrkVTjSmriUqAD
G9E+0WGzhcS3P0Sw7+Y8+AJC6LJB/K2EyUbOyZvxhJ2uM/vinhD/6m0FwUg1lwFy
I4Z4iabYrv5U7bEOb3upWVAleDIA2aUydHdFw89bV8TWaPpIvuZYpYXxW7h5Krqt
mzEwAOuBUrVH+IYqEeOfH5JXr8Oucx5w3TqbDXpZ13hOBqxb2VDS8B6qywocp4vQ
awMhjO9KEFZZFq6/nC6jw3I5f/jmCEvZQ2RMr62mF9JsAcI02uzQnTvWx7EAaKnk
l7MshpbzLUO7uOtg5ZXZzYX3oOIjKHErI8Wovx7DxDSQnxmASQAtVIwYbWmhykbO
uNVBI8xxuH283Q0RFcPNKcWsbqYPZPf8nFBXA5eh3rXXX4TZL/ar5+bV3ty+
=BvJc
-----END PGP MESSAGE-----

$ cat secret.txt 
-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v2

lQPGBFckny0BCADAakIt0wLzRbpOH4u7Fl0vIk4c7XS4l5T6cx7uVvUl+yUyxo3Y
2mdZDKma+NN2YDHHX3jORkURim4ikMEMTorfeTTiMsoNDeEgPHRofCkyziW6c5FY
[truncated]
-----END PGP PRIVATE KEY BLOCK-----

An encrypted message and a private key, how convenient! We import the private key into our local gpg instance.

$ gpg --allow-secret-key-import --import secret.txt 
gpg: key 30B0AAD3: secret key imported
gpg: key 30B0AAD3: public key "chef1 (secret_recipe)" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

And try to decrypt the message.

$ gpg recipe.txt

You need a passphrase to unlock the secret key for
user: "chef1 (secret_recipe)"
2048-bit RSA key, ID DF61487D, created 2016-04-30 (main key ID 30B0AAD3)

Oh god. The key is password protected. Well, lets try to bruteforce it.

# fetch random password list
$ wget "https://github.com/danielmiessler/SecLists/raw/master/Passwords/rockyou.txt.tar.gz"
$ tar zxvf rockyou.txt.tar.gz

# fetch/install john-the-ripper community edition
$ wget "http://www.openwall.com/john/j/john-1.8.0-jumbo-1.tar.gz"
$ tar zxvf john-1.8.0-jumbo-1.tar.gz
$ cd $_/src
$ ./configure
$ make
$ cd ../run

# crack
$ ./gpg2john ../../mnt3/chef/recipe.txt/secret.txt > secret.hash
$ ./john --wordlist=../../rockyou.txt secret.hash
Loaded 1 password hash (gpg, OpenPGP / GnuPG Secret Key [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
footycake123     (chef1)
1g 0:00:00:49 DONE (2016-06-02 21:25) 0.02022g/s 36354p/s 36354c/s 36354C/s ford1043..foot67

Password footycake123 has been recovered. Lets try it on recipe.txt.

$ gpg recipe.txt

You need a passphrase to unlock the secret key for
user: "chef1 (secret_recipe)"
2048-bit RSA key, ID DF61487D, created 2016-04-30 (main key ID 30B0AAD3)

gpg: encrypted with 2048-bit RSA key, ID DF61487D, created 2016-04-30
      "chef1 (secret_recipe)"
gpg: recipe.txt: unknown suffix
Enter new filename [recipe.txt]: /tmp/flag.txt

And we cat the flag.

$ cat /tmp/flag.txt
HITB{41af1026de8e38de54830b0583d7ca08}