Cybersecurity Contributions
  • CyberSec
  • Zixem Challenges
  • TryHackMe write-ups
  • TryHackMe SQL Injection Lab
  • SQLi Collected Cheat Sheets & write-ups
  • Portswigger - SQLi Labs
  • Riddler CTF Challenges
  • Cyber Apocalypse CTF 2022 Web Challenges
  • CyberStarters CTF Challenges
  • SQLi Filter Bypass 101
  • Order By SQL Injection
  • Black Hat CTF Web Challenges (2022)
  • TJCTF 2023 writeup (Code Review)
  • CAT CTF 2023 Web Challenges
  • Arab Regional CTF 2023 (Cyber Talents)
  • BugHunting
    • Google dorking to SQL injection
Powered by GitBook
On this page
  • Web / Swill-Squill
  • Web / Outdated
  • Web / ez-sql
  • Web / back-to-the-past

TJCTF 2023 writeup (Code Review)

Greetings hackers, back again with another CTF which mainly focuses on code review. I've enjoyed solving these challenges with my teammate Abdulhameed Ghazy.

PreviousRiddler CTF ChallengesNextCAT CTF 2023 Web Challenges

Last updated 2 years ago

Web / Swill-Squill

The challenge has a description of ezsql so we know previously what we gonna do. Let's start by trying the web application without the code first :

We can see a simple register form that takes username and grade , When I type the username admin nothing happens like the application refuses this name but when registering with another one :

Now let's check the important code snippets.

Here the code creates the DB and then insert the user admin within it , It also inserts some notes for the admin ... one of this notes contains the flag .

The next part , the code here creates a JWT token. For the first glance we can think that the challenge is based upon jwt but the secret here is too long to be brute-forced / guessed

For the last part we can see that the code gets the notes of a user using a sql query upon his name , here we can notice that there is no sanitization applied to the user input (his name) leaving it vulnerable to SQLi

But not any kind of SQLi .... Second Order SQLi , because if we provided our username as follow : guest' or 1=1-- then the query will resolve to : SELECT description FROM notes WHERE owner == 'guest' or 1=1 --; so it will basically select my notes and any other user notes ( which is the admin ) .

This is second order sqli because our payload wasn't executed directly instead it was stored and executed in another portion of the application.

Web / Outdated

In this challenge we face a python web application which will accept from us python files to run it , so if I have a file named test.py with the content : print("Hello World") the result will be:

However if we checked the code we notice that our file should not contain the following:

Not only this , but also:

So we can't use typical open nor exac, eval and we cannot use the import keyword . These types of challenges usually called Python Jails so by searching for Escaping Python Jails I found some good articles and I found this payload : ().__class__.__bases[0]__.__subclasses__() This will show us python classes which is useful for exploitation, so we could see os or subprocess :

So I took it's index and used this payload : ().__class__.__bases__.[0].__subclasses__()[84].load_module("os").system("ls").read()

Now we can easily read the flag❤

Web / ez-sql

Again we know what to do before we start, Let's check the code directly.

The first thing caught my attention was this snippet :

we see that it creates 2 tables : jokes table and flag table, but the flag table has random characters appended to it, the flag table has a column called flag which obviously contains the flag. What about the serialize word in the beginning? This basically ensures that the statements are executed one by one not in parallel way.

I searched for any other SQL statements and I found this:

The name parameter is directly passed to the SQL query without any sanitization leaving it vulnerable to SQLi , to test this I will use burp:

When adding another quote as follow : ?name=''

So this is confirmation of SQLi , but the main problem here from the last snippet is that the payload is only limited to 6 characters which is very short for our payload.

Checking the code again I saw this line :

Since I don't know what this line means I asked chatGPT:

hmmmm, so this means I can pass the name parameter as an array ?

This actually worked, Now we can pass name as an array instead of string then this will pass the condition assigned to it:

Now we passed the condition and we can write more than 6 characters we can enumerate for the table name:

This is the flag table, we can then select the flag column from it and the challenge is solved.

For enumerating the database I used payloadAllTheThings repo.

Web / back-to-the-past

We have in the code three main endpoints 1- Register Endpoint

It starts first by rendering the html template then takes 2 parameters username & year

2- Retro Endpoint

To access this endpoint we should be logged in first, It also checks for the year if it was lesser then 1970 then it will render the flag. But the main problem here is that when registering we can see that the minimum year to choose is 1971

3- Login Endpoint

When we login , the code generates a token using generate_token function.

4- JWT Tokens

the generate_token function basically generates jwt token with RS256 algorithm and a private key. When it comes to the verification of the token it uses the public key ( which was included in the challenge files ) and uses list of algorithms not only RS256 as in the generation.

1- Base64 encode the public key. 2- In the jwt editor tab, generate a new symmetric key and update the k value to be the base64 encoded text. 3- Update the algorithm to be HS256 . 4- Now we can update the token and set the year to be 1969 ( < 1970 ) and then sign the token with the key.

Now let's request /retro path to get the flag:

And that's it , hope you enjoyed and learned something .... good luck❤

There were many classes but I saw none of which I know, this was new to me. I searched in many blogs until I found this one: which says that I can import modules using _frozen_importlib.BuiltinImporter class , to my luck it was in the class list:

What we can do here is to force the sever to use the HS256 algorithm instead of the RS256 and use the public key key.pem as the passphrase .... This kind of attack is called algorithm confusion and you can read about it more . I'm going to use JWT Editor Keys burp plugin and the steps are as follow:

Blog Link
here
Simple note taking app
Request
Response