Web - Intergalactic Bounty
The Galactic Bounty Exchange—a system where hunters and hunted collide, controlled by the ruthless Frontier Board. Hidden within its encrypted core lies a prize of untold power: the bounty for the Starry Spur. To ignite rebellion, Jack Colt must infiltrate this fortress of contracts, manipulate its algorithms, and claim the Spur’s bounty for himself. A race against time, a battle against the galaxy’s deadliest system—Jack’s mission will decide the fate of the Frontier.
Analaysis
We are given nodejs application and email service with address of test@email.htb
. The setup were pretty much like Armaxis.
Based on the flag location in the source code, we need to obtain at least arbitrary file read or command execution in the application.
|
|
Bot
Bot was found within the source code. It means there’s probably a client side vulnerability such as CSRF, XSS, and others.
using bot is the intended way to solve the challenge, however i’m using unintended solution to solve the problem
Email Discrepancy & Privilege Escalation
In order to log in to the application, users need to register with the interstellar.htb
domain. However, our accessible email domain is email.htb
.
|
|
If email whitelist can be bypassed, we can register as admin
due to parameter pollution in request parser.
|
|
privilege escalation can be achieved using following request data upon registration.
|
|
in order to beat the email parser, i try to read the documentation and source code of email-addresses
, which i found several test cases of parseOneAddress
successfull email format.
one of the interesting format is "Françoise Lefèvre"@example.com
.
After playing with the format for a while, "test@email.htb test"@interstellar.htb
was working perfectly!
This is because email parsing disrepancy between email-address
and nodemailer
. nodemailer will convert the email to following format, which will interpret test@interstellar.htb
as a alias, and set test@email.htb
as the email address.
Code can be retrieved in the email
Prototype Pollution
in one of the admin feature, it uses mergedeep
function. Usually, function related with merge
in javascript environment is vulnerable to prototype pollution.
|
|
if we take a look at the source code, it was clear that the library doesn’t prevent for prototype pollution and assign value directly into the target object.
simple payload such as {"__proto__": {"test":"yey"}}
can be used to trigger the vulnerability.
Finding Gadget
Usually, prototype pollution in CTF are combined with child_process
function such as fork
, execSync
, exec
, etc. However there’s none of them in the current application.
In order to find gadget to obtain either arbitrary file read or command execution, i decided to explore all library used in the application.
One of the interesting library is needle
|
|
The library is used to fetch data from web service. The usage is definitely eye catching because most of nodejs application uses axios
to fetch pages from internet. So there must be something in the needle
library.
|
|
After reviewing the documentation and source code of needle, i found that output
options is being used to save fetched content into system files.
|
|
so if we managed to pollute output
options and call the fetchURL
function, then we can perform arbitrary file write on the system.
This can be performed by calling /api/transmit
using admin credentials after polluting the output
options.
after obtaining arbitrary file write, we can try to
- Overwrite javascript files (need restart)
- Overwrite template files (without restart)
DOS
Additional bug, if we try to provide invalid url within fetchURL
function, aparently the server will shut down.
Because the application using supervisord
with autorestart=true
, then this vulnerability can be used to restart the server after overwriting javascript files.
|
|
Exploitation
in order to perform full attack, we need to:
bypass email protection & privilege escalation
perform prototype pollution to pollute
output
optionsoverwrite either javascript or html files
here i used following payload, stored in
index.html
files. The payload are obtained from Hacktricks1
{{range.constructor("return global.process.mainModule.require('child_process').execSync('cat /flag.txt')")()}}
trigger the updated code to gain code execution
perform the same step for remote, and flag can be obtained :D
Flag: HTB{f1nd1ng_0d4y_15_345Y_r1gh7!!?_970db3ce5022cd532606efeca829916c}