[Reverse] Kaspersky Industrial CTF Quals 2017 - Backdoor Pi


We are doing an project for a school competition in which we need to use a Raspberry Pi to make an IOT prototype. We received SD cards from the professor, and because we lost ours we asked another group to give us a copy of their card, I know it’s been modified because the original hash doesn’t match. Could you please investigate and tell me if everything is ok? Here is some parts of the file system:

FLAG FORMAT: KLCTF{flag}

download this file: https://s3.eu-central-1.amazonaws.com/klctf/fs.zip

By reading the description we know the attacker added some kind of backdoor our first intuition was to check the crontab files:

1
2
$ ls var/spool/cron/crontabs/
b4ckd00r_us3r pi

By checking the b4ckd00r_us3r we found out the backdoor is running in this cron task:

1
2
3
4
5
6
cat var/spool/cron/crontabs/b4ckd00r_us3r 
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.80NKS4/crontab installed on Wed Oct 4 19:28:12 2017)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
# m h dom mon dow command
@reboot python /bin/back

By checking what kind of file /bin/back is:

1
2
$ file bin/back
bin/back: python 2.7 byte-compiled

It’s a python compiled file we used https://github.com/wibiti/uncompyle2 to uncompyle and we got this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# uncompyle6 version 2.12.0
# Python bytecode 2.7 (62211)
# [GCC 6.3.0 20170118]
# Embedded file name: back.py
# Compiled at: 2017-10-05 09:09:10
import sys
import os
import time
from flask import Flask
from flask import request
from flask import abort
import hashlib

def check_creds(user, pincode):
if len(pincode) <= 8 and pincode.isdigit():
val = '{}:{}'.format(user, pincode)
key = hashlib.sha256(val).hexdigest()
if key == '34c05015de48ef10309963543b4a347b5d3d20bbe2ed462cf226b1cc8fff222e':
return 'Congr4ts, you found the b@ckd00r. The fl4g is simply : {}:{}'.format(user, pincode)
return abort(404)


app = Flask(__name__)

@app.route('/')
def hello():
return '<h1>HOME</h1>'


@app.route('/backdoor')
def backdoor():
user = request.args.get('user')
pincode = request.args.get('pincode')
return check_creds(user, pincode)


if __name__ == '__main__':
app.run(threaded=True, host='0.0.0.0', port=3333)
# okay decompiling back.pyc

We have a hash and we know it is composed in the following format:

1
user:pincode

Checking the user in /etc/passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
pi:x:1000:1000:,,,:/home/pi:/bin/bash
sshd:x:101:65534::/var/run/sshd:/usr/sbin/nologin
ntp:x:102:104::/home/ntp:/bin/false
statd:x:103:65534::/var/lib/nfs:/bin/false
messagebus:x:104:106::/var/run/dbus:/bin/false
usbmux:x:105:46:usbmux daemon,,,:/home/usbmux:/bin/false
lightdm:x:106:109:Light Display Manager:/var/lib/lightdm:/bin/false
avahi:x:107:110:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
b4ckd00r_us3r:x:1001:1004::/home/b4ckd00r_us3r:/bin/bash

The user is b4ckd00r_us3r we just need to bruteforce the pincode by looking at the code we know the pincode must be between 1 and 8 numbers using hashcat to crack the hash:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ cat kasperskyhash 
34c05015de48ef10309963543b4a347b5d3d20bbe2ed462cf226b1cc8fff222e
$ cat example.dict
b4ckd00r_us3r:
$ hashcat -D 1,2 -m 1400 -a 6 -i --increment-min 1 --increment-max 8 kasperskyhash example.dict "?d?d?d?d?d?d?d?d"
Session..........: hashcat
Status...........: Exhausted
Hash.Type........: SHA-256
Hash.Target......: 34c05015de48ef10309963543b4a347b5d3d20bbe2ed462cf22...ff222e
Time.Started.....: Sun Oct 8 16:23:46 2017 (3 mins, 27 secs)
Time.Estimated...: Sun Oct 8 16:27:13 2017 (0 secs)
Guess.Base.......: File (example.dict), Left Side
Guess.Mod........: Mask (?d?d?d?d?d?d?d) [7], Right Side
Guess.Queue.Base.: 1/1 (100.00%)
Guess.Queue.Mod..: 7/8 (87.50%)
Speed.Dev.#1.....: 45759 H/s (0.29ms)
Speed.Dev.#2.....: 0 H/s (0.00ms)
Speed.Dev.#*.....: 45759 H/s
Recovered........: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.........: 10000000/10000000 (100.00%)
Rejected.........: 0/10000000 (0.00%)
Restore.Point....: 0/1 (0.00%)
Candidates.#1....: b4ckd00r_us3r:8939393 -> b4ckd00r_us3r:9579393
Candidates.#2....: [Copying]
HWMon.Dev.#1.....: Temp: 64c Fan: 46%
HWMon.Dev.#2.....: N/A

Dictionary cache hit:
* Filename..: example.dict
* Passwords.: 1
* Bytes.....: 15
* Keyspace..: 100000000

- Device #2: autotuned kernel-accel to 160
- Device #2: autotuned kernel-loops to 204
- Device #1: autotuned kernel-accel to 22
- Device #1: autotuned kernel-loops to 23
[s]tatus [p]ause [r]esume [b]ypass [c]heckpoint [q]uit => The wordlist or mask that you are using is too small.
This means that hashcat cannot use the full parallel power of your device(s).
Unless you supply more work, your cracking speed will drop.
For tips on supplying more work, see: https://hashcat.net/faq/morework

Approaching final keyspace - workload adjusted.

34c05015de48ef10309963543b4a347b5d3d20bbe2ed462cf226b1cc8fff222e:$HEX[6234636b643030725f757333723a3132313731333337]
$ cat ~/.hashcat/hashcat.potfile | tail -1
34c05015de48ef10309963543b4a347b5d3d20bbe2ed462cf226b1cc8fff222e:$HEX[6234636b643030725f757333723a3132313731333337]

After a while it cracks, hashcat outputs the password in hex so lets decode it with bash:

1
2
$ echo '6234636b643030725f757333723a3132313731333337' | xxd -r -p
b4ckd00r_us3r:12171337

The flag was

1
KLCTF{b4ckd00r_us3r:12171337}