My observations while working this target:
· Enumeration: CTF-like
· Vulnerabilities: CTF-like
· Exploitation: CTF-like/ Life-like
· Difficulty: Medium/Hard
· Community Notes: CTF-like
The recommended tools for this lab were:
· gdb w/peda
· gdb server
· Hashcat or John
The following vulnerabilities were found:
· Buffer Overflow
First things first, I used Nmap to perform a scan for service version detection, OS detection, script scanning, and traceroute.
After identifying TCP Port 80 as being open, I used Nikto for a base scan of the web site.
With the initial scans completed, I decided to open a web browser to further investigate the web site. Nothing interesting other than a default Apach2 page.
After some review of the /manual directory, I returned to the default Apache2 to review the source. To my surprise, I found a comment about TCP Port 1337 and a hidden binary that could be downloaded.
Note: I ran another Nmap scan with the following flags and discovered the TCP port (-sn -sSVC -p-).
Testing for Buffer Overflow:
This was the toughest part of the entire challenge for me. I have had very little knowledge with registers and how things work. I had to watch many…many…many videos and read lots…lots…lots of articles to get the basics; which I barely comprehend.
So, I am going to go at this from a no nothing point of view. For those that a wiz’s, please don’t laugh, much.
After downloading the myapp, I launched the binary to see what it did.
Next, I decided to use Python to create 200 A’s and used those to create a buffer overflow.
With the A’s generated, I relaunched myapp and input the 200 A’s.
Obtaining the Offset:
I decided to launch gdb with the peda extension pack. Before continuing any further insvestigation, I needed to understand the security implemented on the binary. So, I issued the checksec command within gdb.
With NX (no execute) bit enabled, this makes this portion of the memory read-only. The processor will refuse to run code within this memory area; which helps prevent certain types of malicious code from running.
With regards to RELRO, data sections are reordered so that they can come after the ELF internal data sections; thus, making exploitation possible.
Knowing my options, I would have to use a ROP chain to be able bypass the NX and inject a shell into the buffer overflow.
Obtaining the Offset:
Continuing with gdb, I added the set follow-fork-mode parent so that the debugger would continue to debug the parent process if a fork occurred within the binary.
I then issued the r command to run the binary and then I entered in the 200 A’s to overflow the buffer.
Reviewing the buffer overflow, I could see the 200 A’s within the stack. In addition, I could see that the RSP register had the A’s repeated 80 times when the overflow occurred.
Doing a quick calculation of the comment for RSP, the offset should be 120. However, I wanted to get an accurate calculation by displaying the 64bit memory address of the RSP register.
To do that, I needed a cyclic pattern to rerun the binary and overflow it with that pattern.
Using the newly created cyclic pattern, I ran the binary and then entered the pattern after the question.
Note: when entering the cyclic pattern after the questions, do not include the single quotes. If they are included, the offset may not calculate correctly.
At this point, I needed the memory address for the RSP register. So, I issued the x/xg $rsp command to retrieve the memory location.
With that memory address, I then used the pattern offset with the memory location found for the RSP register to obtain the required offset to be used.
Next, I needed help to understand what was going on. So, I separated the contents returned from the segmentation fault.
Reviewing the registers, it was worth noting that the cyclic entry could be viewed in the RSP register; which was the current stack pointer during the crash.
Reviewing the stack, RSP being the current pointer, the cyclic entry was within the memory addresses. In addition, the fault happened within the main function.
Next, I wanted to review the binary code to gather more information. So, I launched radare2 with the aaaa command, followed by the afl command to analyse the flags, files, and directories.
Reviewing the main function, I determined that the lea rdi, qword was utilizing /usr/bin/uptime (to display the uptime and connection to the console) and then made a call to system. Another lea rdi, qword was utilized to as the question (\nWhat do you want me to echo back? “), followed by a mov eax, 0 and the a call to printf.
At first, reviewing the test function was not all that exciting to me. It added data to the stack, preformed a few register moves and then jumped to register 13. However, reviewing the top half of the main function, there were similar routines that were occurring. So, maybe I could use the test function as a gadget as part of the buffer overflow to inject a /bin/sh command?
To get a complete view of the test function, I returned to gdb and issued the disassemble command. I then took note of the nop, pop, and ret commands.
In order to determine if I could use the test function as a ROP gadget, I needed to use ROPgadget to review the binary for listed mov, pop, and ret entries.
Reviewing the results of ROPgadget, it would appear that I could use the pop, pop, pop, ret for registers 13, 14, and 15. However, I did not have any data to place into registers 14 and 15.
After a little research and a few discussions, I learned that I could use a null string to enter data into those registers. So, I gathered the following information:
This left the need to find an entry for register 13. Since the goal was to execute /bin/sh, I would need the system function for the register. So, I returned to radar2 and issued the pdf @ sym.imp.system command to review the memory. An alternative method in with gdb was to issue the info functions command. But, that has more information than required. Another alternative was to use objdump -D myapp | grep system.
At this point, I tried to build and test my exploit script, but a segmentation fault was still occurring. After inspecting the main function, a little closer, I noticed that rsp had a sub instruction of 0x70. So, this needed to be calculated as part of the offset.
Reviewing the registers again in gdb, I found the entries within the RBP and RSP registers.
Next, I issued the command to display the 64bit memory address of the RSP register. With that memory address, I then used the pattern offset with the string found within the RBP register to obtain the required offset to be used.
Final Local Exploit:
Since I had a local copy of the binary, I decided to build my exploit to test against it. So, I gathered all of the data needed to build the exploit.
After some testing and tweaking, I came up with my final code.
Final Remote Exploit:
With the local exploit complete, I modified it and connected to the remote target.
With connectivity established, I was able to locate the user flag within the /home/user directory.
I tried the standard methods to exfiltrating the KeePass file found within the /home/user directory, but nothing was working. So, I converted the file to Base64 and then copied the text to my attacker system.
On my attacker system, I then converted the Base64 file back to the original .kdbx file.
I was looking to do the same procedure for the found JPG files. However, once encoded, it took a little bit of effort to copy all of the contents to my attacker system.
So, I decided to create a public and private key to enable the ability to scp files to my system without the user’s password. With that, I used ssh-keygen to create the keys in a file other than /root/etc/ssh.
With the keys created, I copied the contents of the rsa.pub file and then pasted it to the target user’s ~/.ssh/authorized_keys directory.
With the keys created and the public key copied to the target, I launched scp with the identity_file flag (for the private key location) followed by the target user and then the JPG files.
After downloading and review the options for keepass2john, I treated each one of the JPG files as a key file for the KeePass database. So, I ran keepass2john against the MyPasswords.kdbx and each one of the JPG files to produce a hash.
With the hashes created, I used my cracking rig to run Hashcat against the hashes. I read an article that the database name needed to be removed from the hash prior to cracking. In addition, I noticed that Hashcat would only crack one hashed entry from the input file.
Since I already had a copy of KeyPassXC on my OSX system, I used it to open the database and entered the cracked password. I then selected the IMG_0547.JPG file as the Key File.
Once in the database, the first entry present was Root pass for root.
Next, I used ssh to try to connect with root. However, I was not able to establish the connection. So, I used ssh with the identity_file flag to connect to the target as the user. I then issued a switch to root and logged in with the credentials from the KeePass database.
All that was left was to find the Root Flag.
This article is made available for educational purposes only!!! In addition, this article provides general information on cyber security topics used for “Ethical Hacking”.
Persons accessing this information assume full responsibility for the use and agree to not use this content for any illegal purpose. Furthermore, the author is not liable for any direct or indirect damages or expense incurred which may result from the use of the information covered within this article.
Information within this article is “as is”, without warranty of any sort.