[Web]picoMini by redpwn
Last updated
Was this helpful?
Last updated
Was this helpful?
Link chall:
View source -> vào file index.js
-> beauty code:
Username và password có trong đây nhưng đang ở dưới dạng base64 encoded. Decode themm!!!
Flag: picoCTF{53rv3r_53rv3r_53rv3r_53rv3r_53rv3r}
Bài này ta có nhận 1 file source:
Bài này truy cập endpoint /cowsay/:message
, message
request sẽ được truyền hàm vào exec
và đồng thời là input thực thi bởi command cowsay
của linux. Kết quả trả về sẽ là lỗi (nếu :message
rỗng) hoặc text được in ra màn hình.
Dzô dziệc, command injection: /cowsay/hi;ls -a
.
Đọc file falg.txt
:
FLAG: picoCTF{moooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0o}
Ta nhận được 1 source code với 1 route nhận request như sau:
content
gửi lên không được chứa _
và /
. Độ dài không quá 512 ký tự. Ngược lại sẽ render render lên index.html với param error
như sau:
Mình thử gửi content
lỗi và phát hiện ra cái thú dzị:
Mình truyền cho param error
gì thì index cũng sẽ render ra màn hình. Nhưng tên file error mình truyền vào không tồn tại nên không include nội dung được.
Đọc trong source kỹ 1 tí thì thấy content
của mình truyền vào sẽ được lấy 128 ký tự đầu + token để làm tên file (sau khi url encode). Sau đó content
được ghi vào file này và lưu vào static/file_name.html
.
Ý tưởng: kết hợp 2 phát hiện trên, content
nhập vào sẽ dẫn ra folder error để tạo file ở đây và tại index mình truyền tên file vừa tạo vào để index render nội dung file error khai thác server side template injection.
Thử nghiệm:
Payload: ..\templates\errors\{{7*7}}
(ký tự \
khi qua hàm url_fix
sẽ thành /
bypass filter)
404 vì folder này không có quyền access. Nhưng ta có thể access tại index như đã nói trên.
"Khoan, dừng khoảng chừng 2s". Tên file của mình (khoảng trước token) vừa tạo cần phải đem đi url encode 1 lần trước khi truyền vào param error
bởi vì tên file sẽ bị decode trước khi include gây ra chuyện sai tên file.
%7B%7B7*7%7D%7D
--> %257B%257B7%2A7%257D%257D
Như vậy là đã thành công template injection!
Nhưng để tránh khá cực cho việc phải đi encode trước khi gọi thì mình có thể truyền vào đó 1 chuỗi ký tự độ dài khá dài (cho là 128 đi) để không vướng các ký tự đặc biệt bị encode.
Thực hiện exploit:
Tạo content
<path error> + 128 ký tự + "payload SSTI"
Dán tên file (without .html
) vào param error
.
Không lưu flag ở biến môi trường, vậy phải rce. Khó khăn ở đây là phải bypass ký tự _
, trong lúc exploit SSTI không thể tránh call attribute có chứa các ký tự _
.
Nhưng có cách khác để call attribute (ví dụ __class__
) là gọi attribute theo kiểu mảng và truyền vào key theo phương thức truyền get request, ví dụ:
{{''.__class__.__mro__}}
--> {{''[request.args.get('class')].mro()}}
Như vậy thành công, mro trỏ index 1 và call subclasses để list classes có thể access và dùng.
Class mà mình cần để có thể rce server là subprocess.Popen
có tồn tại (ước gì nếu là subprocess.check_output
tuyệt vời biết mấy). Tiếp theo, call class này (call bằng index) và truyền arg command.
Việc khó khăn là tìm index của class này =)) nhưng Ctr+F tí xíu là ra: 273
Vì muốn in ra màn hình nhưng popen
chỉ chỉ thực hiện chứ không in ra, mình tìm solution có vấn đề này khá lâu. Nhưng trong document có đề cập đại loại là flag stdout
là số âm thì sẽ trả về buffer mặc định chuẩn io có thể đọc được (0: không trả về, 1: trả về byte,...)
Sau một tỉ tỉ lần tìm và đọc thì payload chốt cuối cùng:
Cat flag:
FLAG: picoCTF{styl1ng_susp1c10usly_s1m1l4r_t0_p4steb1n}
Link chall:
Link chall: