TetCTF 2019
1/File
Ở index là 1 đoạn chat về chủ đề chính là MacOS hay Windows ngon hơn :))), và người nói MacOS ngon hơn là anh tsu (author của challenge này) nên mình nghĩ bài này liên quan gì đó tới MacOS
Mình scan thử web này có gì lạ k thì scan dc /logs, /icons,… nhưng cái làm mình chú ý là /.DS_Store (nếu bạn nào chưa biết về file này có thể đọc writeup cũ của mình về DS_Store https://medium.com/@anhkhoafto/35c3ctf-junior-2018-writeups-be9b74ccaa2f)
Đây là toàn bộ source của challenge, lấy flag thôi
TetCTF{DS_Store__seems_sad}
2/ IQTEST
Trước khi viết wu bài này thì mình khá buồn và cay vì bài này
và do mình ngu + cùi bắp nên bài này tất cả là công của
PeterJson từ gợi ý mình về Hash Length
Extension tới nói cho mình hiểu Hash Length Extension nó hoạt động ra làm sao
Giao diện bài này thế này
Source Code :
Cookie:
Bài này có 13 câu hỏi mình trả lời đúng 13 câu hỏi thì sẽ có được flag, với mỗi câu hỏi sẽ có 2 cookie là Hash và Saved
Saved = b64(seed)
Hash = md5(concat(secrect,seed))
6 câu đầu thì dễ dàng pass vì là câu hỏi multiple choice hoặc là mấy câu đơn giản, tới câu thứ 7 thì là thế này
Có đoán cũng tới mai :))) nên quay trở lại source code của bài này, thì có 1 đoạn cần chú ý
Nếu level = NULL (không có 1 cookie nào hoặc cookie không có nghĩa) thì level sẽ được dựa vào đoạn code này, đây là phần code mình debug thử để pass tới level 13
https://repl.it/@Bui_Duc_AnhDuc/ShinyNeedyDesktopenvironment
Vấn đề là làm sao để tạo ra 1 cookie mà có md5 hash có thể gửi lên và chạy thẳng tới level 13, đây là vấn đề của Hash Length Extension
Các bạn có thể đọc qua 2 wu của PeterJson để hiểu thêm về HLE, hoặc có thể cmt bên dưới mình có thể giải đáp những cái trong giới hạn kiến thức mình học được qua đọc 2 wu này:
https://medium.com/@peterjson/matesctf-round-5-qualification-crypto-writeup-a5e287838e69 (ViettelStore — Crypto100)
https://medium.com/@peterjson/uit-hacking-contest-2018-crypto-writeup-8bf32267e93b (Crypto400-SuperSecureServer)
Mình dùng Hash Extender để giải quyết bài này
Sau đó mình dùng new signature để làm cookie hash
new string thì mình dùng b64(‘seed=’+hexdecode(newstring)) để làm cookie saved
3/ phplimit revenge
về các filter của bài này thì mọi người có thể dùng https://regex101.com/ để đọc hiểu (ban đầu khá là khó hiểu nhưng có 1 số trợ giúp từ ae bạn dì nên mình cũng hiểu 😤)
If 1 chặn không cho mình truyền argument (string) vào các hàm để đọc flag , nên chỉ có thể truyền boolean vào đây thôi
If 2 thì chặn 1 số hàm dùng để đọc flag
PeterJson lại gợi ý mình 1 hàm có thể show ra được path hiện tại + có thể truyền boolean argument vào là realpath()
Cụ thể là mình có thể sử dụng realpath(false) hoặc realpath(NULL)
mà NULL thì đã có assert() => với realpath(assert()) thì mình có được path hiện tại
Mình cần đọc những file ở path đó thì có scandir()
với scandir(realpath(assert())) thì mình có được toàn bộ những file ở path đó
scandir sẽ trả về array, mình chỉ biết mỗi hàm print_r() để in ra array nhưng bị filter mất :((
Ok vậy thôi mình làm thủ công
sau 1 hồi mò thì tới được path này
[http://139.180.219.222/?code=echo(next(next(scandir(realpath(assert()))));](http://139.180.219.222/?code=echo(next(next(scandir(realpath(assert()))));)
Là file index, nên thôi mình quyết định coi file cuối cùng tên gì luôn
http://139.180.219.222/?code=echo(end(scandir(realpath(assert()))));
dùng readfile() để đọc file này
view-source:http://139.180.219.222/?code=readfile(end(scandir(realpath(assert()))));
4/ phplimit revenge v2
Phải nói là PHP khá là ảo diệu khi mình làm đc bài này :3 mình ko hiểu tác giả
chặn strlen rồi rand làm gì nhưng sau 1 thời gian đọc các hàm trên w3schools thì
thấy có 4 hàm là dirname, basename, realpath, pathinfo
thì đều bị blacklisted
theo như web này nói
search đi search lại cũng thấy web nào nói là dùng glob()
kèm vs pattern
đắn đo mãi thì thử vs php online thì mình thấy là glob() trả về array theo pattern *, mỗi phần tử là các file trong thư mục 😆
'*'
thì nó là string, làm sao để tạo *? booom, 1 idea khá là xịn cũng lầy vc,
là tính ra số 42 r chr() để thành *
bắt đầu đi từ exp(assert())
, lý do mình gọi assert()
vì nó là mặc định là
TRUE == 1, thực hiện các phép tính toán (làm đại) thì may thật ra dc số 42 😖
mình cũng ko hiểu tại sao local tính ra số khác server tính số khác
dc 42 r thì biến nó thành * và glob :3
như trên glob trả về array, nhưng trước tiên coi thử có bn file hay folder con trong folder này (/var/www/html/)
hên vl :))) là có 3 file (ko biết có folder hay ko). Tiện vl, mình dùng các hàm này để di chuyển con trỏ tới các element trong array. Hên là vì tác giả để chỉ có 3 file, chứ 4 files mà flag nằm ở vị trí thứ 3 mình cũng chả biết trỏ kiểu gì =))
đoán bừa flag nằm cuối nên mình dùng end(…)
Coi thử có cái gì trong này
:)))) classic trick từ a tsu, ok mọi chuyện từ giờ còn khó hơn
okay, mình cần bây giờ là ..
để có thể view các file trong parrent folder
ok, got it, ko dùng glob()
nữa mà mình sẽ dùng scandir('.')
thay cho glob() vì
như hình bên trên glob('*')
ko return về . hoặc ..
Hay quá có rồi :))) bây giờ là công đoạn làm cách nào tính cho ra được số 46 (decimal của .)
Bằng các biện pháp nghiệp vụ kết hợp vs kĩ năng toán học mà mình có với 1 ít tâm linh nào đó đã cho mình sức mạnh tính ra dc 64 =))) thử xem sao
có . rồi thì scandir hiện tại là (.) lấy next() là (..), rồi scandir(..), lấy end là có real flag
Mà flag của mình đâu rồi
Suy nghĩ 1 chút thì mình nó chỉ show content của parent dir thôi chứ mình chưa ở parent dir
dùng chdir() thì chắc được vì mình đã có ..
rồi nên nhưng làm sao đọc flag?
thế lực siêu nhiên nào đó lại giúp mình khi chdir() return về boolean và nó là
true == 1
. Thì sao nhỉ :3 nghĩa là mình đang có mặt ở ..
và chỉ cần dùng
phép toán mà thần linh đã ban cho tính từ exp(assert()) == chdir(‘..’)
http://45.76.181.81/?code=readfile(end(scandir(chr(strrev(floor(rad2deg(tan(sin(round(chdir(next(scandir(chr(strrev(floor(rad2deg(tan(sin(round(exp(assert())))))))))))))))))))));