diff --git a/.github/readme/update-readme.yaml b/.github/readme/update-readme.yaml new file mode 100644 index 0000000..2939d8b --- /dev/null +++ b/.github/readme/update-readme.yaml @@ -0,0 +1,24 @@ +name: Update README + +on: + push: + branches: [main] + +jobs: + run-script: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + - name: Run Python script + run: python .github/scripts/update_readme.py + - name: Commit changes + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add README.md + git commit -m "docs: update total count" + git push \ No newline at end of file diff --git a/.github/scripts/readme.py b/.github/scripts/readme.py new file mode 100644 index 0000000..31e4edd --- /dev/null +++ b/.github/scripts/readme.py @@ -0,0 +1,27 @@ +import os +import re + +folder_path = "." + +if os.path.exists(folder_path) and os.path.isdir(folder_path): + first_level_subfolders = [name for name in os.listdir(folder_path) if os.path.isdir(os.path.join(folder_path, name))] + total_second_level_subfolder_count = 0 + + for subfolder in first_level_subfolders: + subfolder_path = os.path.join(folder_path, subfolder) + second_level_subfolders = [name for name in os.listdir(subfolder_path) if os.path.isdir(os.path.join(subfolder_path, name))] + total_second_level_subfolder_count += len(second_level_subfolders) + + # Update the README.md file + readme_file = os.path.join(folder_path, "README.md") + if os.path.isfile(readme_file): + with open(readme_file, 'r') as file: + content = file.read() + + pattern = r"(There are __)(\d+)(__ CTF writeups that have been made in this repository)" + + replacement = f"There are __{total_second_level_subfolder_count}__ CTF writeups that have been made in this repository" + content = re.sub(pattern, replacement, content) + + with open(readme_file, 'w') as file: + file.write(content) diff --git a/README.md b/README.md index c4039b0..0c002c4 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This repository shall comprise writeups concerning Capture The Flag (CTF) compet This is a list of wins we have achieved while participating in several CTF competitions ### Total Writeups -There are __396__ writeups that have been made in this repository +There are __461__ CTF writeups that have been made in this repository ### CTF Competitions @@ -13,12 +13,19 @@ There are __396__ writeups that have been made in this repository | ---------- | ---- | ------- | | DeconstruCT.F 2023 | aseng_fans_club | 1 | | The Odyssey CTF | aseng_fans_club | 1 | -| Pointer Overflow CTF 2023 | HCS | 1 | -| BDSec CTF 2023 | HCS | 1 | +| Pointer Overflow CTF 2023 | Heroes Cyber Security | 1 | +| BDSec CTF 2023 | Heroes Cyber Security | 1 | | h4ckc0n 2023 | TCP1P | 2 | | 0xLaugh CTF 2023 | TCP1P | 2 | | 0byteCTF 2023 | - | 3 | -| N45HTCTF2023 | HCS | 3 | +| N45HTCTF2023 | Heroes Cyber Security | 3 | + +### Finalists CTF Competitions +| Event Name | +| ---------- | +| ASEAN Student Contest on Information Security Qualification 2023 | +| Infinity 2023 | +| UNITY 2023 | ### Writeup Competitions @@ -111,6 +118,10 @@ List of CTF events that i have joined before | Buckeye CTF 2023 | Yes | [Link](/Buckeye%20CTF%202023/) | | SunshineCTF 2023 | Yes | [Link](/SunshineCTF%202023/) | | DefCamp Capture the Flag (D-CTF) 2023 Quals | Yes | [Link](/DefCamp%20Capture%20the%20Flag%20(D-CTF)%202023%20Quals/) | +| ASEAN Student Contest on Information Security Qualification 2023 | No | - | +| ASEAN Student Contest on Information Security Semi-Final 2023 | No | - | +| Srdnlen CTF 2023 | Yes | [Link](/Srdnlen%20CTF%202023/) | +| BlueHens CTF 2023 | Yes | [Link](/BlueHens%20CTF%202023/) | ### Local Events | Event Name | Writeup Available? | Writeup Link | diff --git a/Srdnlen CTF 2023/README.md b/Srdnlen CTF 2023/README.md new file mode 100644 index 0000000..f11c776 --- /dev/null +++ b/Srdnlen CTF 2023/README.md @@ -0,0 +1,9 @@ +# Srdnlen CTF 2023 +CTF writeup for The Srdnlen CTF 2023. I took part in this CTF competition with the HCS team and secured the 12th place out of 200 teams + +| Category | Challenge | +| --- | --- | +| Cryptography | [RSA](/Srdnlen%20CTF%202023/RSA/) +| Web | [Spongeweb](/Srdnlen%20CTF%202023/RSA/) +| Forensic | [stego WarmUp](/Srdnlen%20CTF%202023/RSA/) +| Forensic | [Urban Odissey](/Srdnlen%20CTF%202023/RSA/) \ No newline at end of file diff --git a/Srdnlen CTF 2023/RSA/README.md b/Srdnlen CTF 2023/RSA/README.md new file mode 100644 index 0000000..80beace --- /dev/null +++ b/Srdnlen CTF 2023/RSA/README.md @@ -0,0 +1,91 @@ +# RSA +> Was this the RSA that Rivest, Shamir and Adleman intended? + +## About the Challenge +We were given 2 files, `chall.py` and `output.txt`. + +```python +from Crypto.Util.number import getStrongPrime, bytes_to_long + +flag = b"srdnlen{?????????????????????????????????????????????}" + +nbits = 512 +e = 0x10001 +r, s, a = [getStrongPrime(nbits, e=e) for _ in range(3)] + +rsa = r * s * a +r_s_a = r + s + a +rs_ra_sa = r * s + r * a + s * a + +flag_enc = pow(bytes_to_long(flag), e, rsa) + +print(f"{flag_enc = }") +print(f"{rsa = }") +print(f"{r_s_a = }") +print(f"{rs_ra_sa = }") +``` + +And here is the content of `output.txt` + +``` +flag_enc = 305937389913644124353521541203896228228100287771861952787632778203429862580034717045066213644670515924479613687491939585830621428606122810529254111370561855825281351383357838797183961382377911872273999422767788459585486508291858004728424594963981121345786835801425225173392185659177549728175043848142863492498517163562979790708452839236670186147527086692854011149422111289175223857001786765717200535670927989091747867031255628205430286900180120411568566496158971 +rsa = 1119331088426445652049073632117678292260141007738261628482440105143508952011573006283470657320593796414881427458009128790416915606096677817107740886320364054596186677319992672873286602387978243613748908293131886639783664921319212446265594496808690114453810308016153697587841315391448735148763753254685350707203658119669859336306387287389740797917206580085557660754531433662772769500638270585975839989101964379252278187400491260154753705688029268027175812419696619 +r_s_a = 31196151692240769482413434933384534303517111654835402273777788758876797999084042595072311282209063135918012172776936704542482749883925277357875720477370629 +rs_ra_sa = 323898748110304540012077200920876791739827672187962956210824080913877019158151191999812688624496191774476169968522325251822258958226152196451875769781319538093983441577632922600197853360682904318047081576168252854038158315592880232574502453976052364135250887912532391068132536589210795343836920404808340626031 +``` + +In order to decrypt the flag, we need to find the value of r, s, and a + +## How to Solve? +I made a Python script that uses `z3` to find the value of r, s, and a. Here is the full script + +```python +from z3 import * +from Crypto.Util.number import long_to_bytes + +flag_enc = 305937389913644124353521541203896228228100287771861952787632778203429862580034717045066213644670515924479613687491939585830621428606122810529254111370561855825281351383357838797183961382377911872273999422767788459585486508291858004728424594963981121345786835801425225173392185659177549728175043848142863492498517163562979790708452839236670186147527086692854011149422111289175223857001786765717200535670927989091747867031255628205430286900180120411568566496158971 +rsa = 1119331088426445652049073632117678292260141007738261628482440105143508952011573006283470657320593796414881427458009128790416915606096677817107740886320364054596186677319992672873286602387978243613748908293131886639783664921319212446265594496808690114453810308016153697587841315391448735148763753254685350707203658119669859336306387287389740797917206580085557660754531433662772769500638270585975839989101964379252278187400491260154753705688029268027175812419696619 +r_s_a = 31196151692240769482413434933384534303517111654835402273777788758876797999084042595072311282209063135918012172776936704542482749883925277357875720477370629 +rs_ra_sa = 323898748110304540012077200920876791739827672187962956210824080913877019158151191999812688624496191774476169968522325251822258958226152196451875769781319538093983441577632922600197853360682904318047081576168252854038158315592880232574502453976052364135250887912532391068132536589210795343836920404808340626031 + +e = 0x10001 + +r = Int('r') +s = Int('s') +a = Int('a') + +eq1 = r * s * a == rsa +eq2 = r + s + a == r_s_a +eq3 = r * s + r * a + s * a == rs_ra_sa + +solver = Solver() + +solver.add(eq1) +solver.add(eq2) +solver.add(eq3) + +if solver.check() == sat: + # Get the solution + model = solver.model() + + # Get the values of r, s, and a + r_value = model[r].as_long() + s_value = model[s].as_long() + a_value = model[a].as_long() + + phi_rsa = (r_value - 1) * (s_value - 1) * (a_value - 1) + + d = pow(e, -1, phi_rsa) + flag_dec = pow(flag_enc, d, r_value * s_value * a_value) + flag_bytes = long_to_bytes(flag_dec) + print(flag_bytes) + +else: + print("Nah") +``` + +Run the program and you will obtain the flag + +``` +srdnlen{W3lc0m3_t0_srdnlen_ctf_2023_crypt0_ch4ll3ng3s} +``` \ No newline at end of file diff --git a/Srdnlen CTF 2023/Spongeweb/README.md b/Srdnlen CTF 2023/Spongeweb/README.md new file mode 100644 index 0000000..721b243 --- /dev/null +++ b/Srdnlen CTF 2023/Spongeweb/README.md @@ -0,0 +1,58 @@ +# Spongeweb +> I really like hacking. +> I really like privacy. +> And I really like spongebob. +> I combined all of them and created an anonymous sharing platform with HTML support. Feel free to share payloads, malware, and stolen credit cards ;). +> Btw it's called spongeweb, but it has nothing to do with [this](https://trollpasta.com/wiki/SpongeWeb). + +## About the Challenge +We were given a source code that you can download the source code [here](spongeweb.zip) + +## How to Solve? +This is a combination between Cross-Site Scripting (XSS) and SQL Injection (SQLi). The flag was located in the admin password (You can check in the `users` table). Instead of stealing the cookie, we can exploit the website using SQL Injection because of there is no filter in `/admin` endpoint + +```python +@app.route('/admin', methods=['GET', 'POST']) +def admin(): + if 'username' not in session: + return redirect(url_for('login')) + #view analytics + if 'query' in request.args: + query = request.args.get('query') + try: + cur = get_db().execute("SELECT count(*) FROM {0}".format(query)) + except: + return render_template('adminPanel.html') , 500 + result = cur.fetchall() + cur.close() + return render_template('adminPanel.html', result=result, param=query) + else: + return render_template('adminPanel.html') +``` + +And we need to print the flag by using `users union select (select password from users)--` payload. Example: + +``` +GET /admin?query=users union select (select password from users)-- +Host: xxxxx +User-Agent: xxxx +... +``` + +And because we can't access `/admin` endpoint directly, we need to exploit the website using XSS to trick the admin to execute SQL injection and then send the result into our webhook. Here is the final payload I used to obtain the flag + +``` + +``` + +Create the thread and then report the URL to admin. My webhook: + +![webhook](images/webhook.png) + +Decode the `Base64` encoded string to obtain the flag + +![flag](images/flag.png) + +``` +srdnlen{XSSS_cr0Ss_S1T3_sP0nG3wEb_SQLi} +``` \ No newline at end of file diff --git a/Srdnlen CTF 2023/Spongeweb/images/flag.png b/Srdnlen CTF 2023/Spongeweb/images/flag.png new file mode 100644 index 0000000..dc97836 Binary files /dev/null and b/Srdnlen CTF 2023/Spongeweb/images/flag.png differ diff --git a/Srdnlen CTF 2023/Spongeweb/images/webhook.png b/Srdnlen CTF 2023/Spongeweb/images/webhook.png new file mode 100644 index 0000000..a9acca5 Binary files /dev/null and b/Srdnlen CTF 2023/Spongeweb/images/webhook.png differ diff --git a/Srdnlen CTF 2023/Spongeweb/spongeweb.zip b/Srdnlen CTF 2023/Spongeweb/spongeweb.zip new file mode 100644 index 0000000..02769ef Binary files /dev/null and b/Srdnlen CTF 2023/Spongeweb/spongeweb.zip differ diff --git a/Srdnlen CTF 2023/Urban Odissey/README.md b/Srdnlen CTF 2023/Urban Odissey/README.md new file mode 100644 index 0000000..d029b4a --- /dev/null +++ b/Srdnlen CTF 2023/Urban Odissey/README.md @@ -0,0 +1,24 @@ +# Urban Odissey +> I can't remember the city where I lost my trail. Can you help me find my secret map of the treasure? + +## About the Challenge +We were given a `pcapng` file that contains a lot of requests about city (You can download the file [here](urban_odissey.pcapng)) + +## How to Solve? +When I analyzed the file, there is 1 unusual HTTP request like the image below: + +![flag](images/s3cr3t.png) + +When I tried to decode the string, the result was the latitude and longitude of a location + +![flag](images/location.png) + +Now, let's find `Mumbai` inside the `pcapng` file and there is 1 HTTP request that contains that string + +![flag](images/flag.png) + +Decode the body response using `Base64` encoding + +``` +srdnlen{1t_w4snt_t00_d1ff1cult_but_Mumb41_1s_c4h0tic_30100} +``` \ No newline at end of file diff --git a/Srdnlen CTF 2023/Urban Odissey/images/flag.png b/Srdnlen CTF 2023/Urban Odissey/images/flag.png new file mode 100644 index 0000000..8819d1a Binary files /dev/null and b/Srdnlen CTF 2023/Urban Odissey/images/flag.png differ diff --git a/Srdnlen CTF 2023/Urban Odissey/images/location.png b/Srdnlen CTF 2023/Urban Odissey/images/location.png new file mode 100644 index 0000000..bc887e1 Binary files /dev/null and b/Srdnlen CTF 2023/Urban Odissey/images/location.png differ diff --git a/Srdnlen CTF 2023/Urban Odissey/images/s3cr3t.png b/Srdnlen CTF 2023/Urban Odissey/images/s3cr3t.png new file mode 100644 index 0000000..e0a2b82 Binary files /dev/null and b/Srdnlen CTF 2023/Urban Odissey/images/s3cr3t.png differ diff --git a/Srdnlen CTF 2023/Urban Odissey/urban_odissey.pcapng b/Srdnlen CTF 2023/Urban Odissey/urban_odissey.pcapng new file mode 100644 index 0000000..6fa1752 Binary files /dev/null and b/Srdnlen CTF 2023/Urban Odissey/urban_odissey.pcapng differ diff --git a/Srdnlen CTF 2023/stego WarmUp/README.md b/Srdnlen CTF 2023/stego WarmUp/README.md new file mode 100644 index 0000000..1f62483 --- /dev/null +++ b/Srdnlen CTF 2023/stego WarmUp/README.md @@ -0,0 +1,16 @@ +# stego WarmUp +> Welcome to the challenges of misc, forensic, and osint! Can you find the flag in this beautiful blank sheet? Good luck! + +> Flag must be submitted in srdnlen{} format: wrap the found flag in srdnlen{} + +## About the Challenge +We need to find the flag inside this blank photo (You can download the file [here](stegoWarmUp.png)) + +## How to Solve? +You can use `zsteg` or you can use AperiSolve website to obtain the flag + +![flag](images/flag.png) + +``` +srdnlen{w3lc0m3_t0_0s1nt_f0r3n_mi2c!} +``` \ No newline at end of file diff --git a/Srdnlen CTF 2023/stego WarmUp/images/flag.png b/Srdnlen CTF 2023/stego WarmUp/images/flag.png new file mode 100644 index 0000000..24ffe9f Binary files /dev/null and b/Srdnlen CTF 2023/stego WarmUp/images/flag.png differ diff --git a/Srdnlen CTF 2023/stego WarmUp/stegoWarmUp.png b/Srdnlen CTF 2023/stego WarmUp/stegoWarmUp.png new file mode 100644 index 0000000..8f55773 Binary files /dev/null and b/Srdnlen CTF 2023/stego WarmUp/stegoWarmUp.png differ