Đây là một challenge whitebox, cung cấp cho mình source code, cung cấp một cách khá hay để khai thác SSTI
Challenge sử dụng Springboot để build web, với 1 route duy nhất tại index, tại phương thức POST nhận đầu vào là data và xử lý để in ra chuỗi hello tên người dùng và thời gian:
data
được base64 decode, sau đó chuyển từ dạng hex sang bytes array và được deserialize (sus)#
không, nếu không có ký tự này ta sẽ không thể dùng được các syntax của tempalte như #set
,…Không những vậy, tại class SecureObjectInputStream
khi invoke method resolveClass
thì class sẽ kiểm tra xem class đầu tiên phải là Users thì mới cho phép tiếu tục vào method resolveClass để tiếp tục deserialize
Nhưng trước hết thì mình cũng cần phải code lại script để gen ra được data đã, object Users sẽ đi theo flow sau:
Resource từ source code gốc đã có gần như đủ cả, mình tạo thêm method bytesToHex tại class Encode:
Main method của mình như sau:
Ta có base64 value của giá trị serialize là YWNlZDAwMDU3MzcyMDAxNjYzNmY2ZDJlNjk3MzY5NzQ2NDc0NzUyZTY4Njk2ODY5MmU1NTczNjU3MjczNzA4NTI1ZDliYTNiZWZiMzAyMDAwMTRjMDAwNDZlNjE2ZDY1NzQwMDEyNGM2YTYxNzY2MTJmNmM2MTZlNjcyZjUzNzQ3MjY5NmU2NzNiNzg3MDc0MDAwODc1NzM2NTcyMzEzMzMzMzc=
Giờ mình cần tìm cách để exploit SSTI, với việc không thể sử dụng dấu #
thì mình không thể tạo được biến nào để gọi method từ biến đó ra vì không dùng được #set()
Mình chuyển qua việc sử dụng những gì mình có, cụ thể là biến $date
được khai báo đồng thời trong templateString, với kiểu dữ liệu là String. Đây là một variable hoàn hảo mình có thể lợi dụng để có thể invoke đến Runtime.exec.
Payload mình tìm kiếm và tham khảo tại: https://blog.csdn.net/weixin_39190897/article/details/139707252
Ban đầu mình confirm bug bằng việc tạo file tại /tmp:
Đưa nó vào script và gửi, mình thấy câu lệnh được thực thi thành công vì kết quả trả về là pid của tiến trình thực hiện tạo file:
File /tmp/1337 đã xuất hiện, confirm payload RCE thành công:
Tuy đã RCE, nhưng challenge config iptables để chặn connection qua chain DROP (cũng na ná chall niceray), nên mình không reverse shell mà đi tìm cách lấy nội dung file flag qua webroot.
Trong Springboot thì để xuất hiện webroot, ta cần đưa file vào thư mục: /tmp/tomcat-docbase.8080....
, mỗi lần deploy thì giá trị đằng sau sẽ là các ký tự khác, nhưng prefix đằng trước sẽ luôn là tomcat-docbase.8080.
.
Mình thử echo nội dung vào 1 file trong đó:
Nội dung file được hiện lên webroot:
Như vậy thì mình có thể lấy nội dung flag thông qua folder này, và trong Runtime.exec vì tại method này Java sẽ coi các argument của command cách nhau bởi dấu cách, nên để thuận lợi trong việc sử command thì mình sử dụng:
Flag được đưa vào thư mục /app, nên mình sẽ ls để lấy tên file trước:
Mình cd vào thư mục đó trước rồi lấy oputput vào file 13373269.txt
Ốp vào đoạn code gen của mình và send, kết quả mình có flag tên là eg5mhk3q9yp3
:
Giờ thì chỉ việc làm điều tương tự với cat file thôi là mình có flag trên local:
Áp dụng lên server, mình có tên flag là m62dyeu1gr3t
:
Solve
ISITDTU{We1come_t0_1s1tDTU_CTF}
Một challenge blackbox mà khi truy cập đến có độc mỗi chức năng đăng kỹ và đăng nhập:
Mình login với credential a:a
, thì có 3 endpoint trang web cung cấp:
Đầu tiên mình nghĩ có thể SQLi tại /genZ nhưng fuzz một hồi không có gì tiến triển ngoài or 1=1 thì mình chuyển qua endpoint /old_heroes, tại đây có param name mà khi truyền chuỗi thông thường sẽ thông báo lỗi: Invalid object name 'OldHeroDB..'
Khá lạ với kiểu response này, mình tiếp tục fuzzing và truyền dấu nháy các kiểu thì nhận được kiểu lỗi khác nhau, mỗi lỗi lại văng ra một ít phần câu lệnh SQL:
Từ đó thì mình thấy payload đang được truyền vào nhiều hơn 1 chỗ trong câu lệnh SQL, nôm na câu lệnh SQL sẽ dạng dạng như này (mình đoán vậy):
Mình đã cố thử stacked query hoặc declare thêm biến để chạy xp_cmdshell vào phần WHERE cuối nhưng làm như vậy sẽ lỗi ở phần payload trên, kết quả đều không giòn
Đi tìm kiếm các tài liệu về mssql injection, mình tìm thấy một blog khai thác với cái kiểu db với 2 dấu chấm đằng sau rất giống với challenge: https://cyku.tw/no-database-mssql-injection/
Từ blog trên mình rút ra được vài thứ:
select 1 as [ ]
Như vậy, ta đã có thể craft thành payload SQL Injection, để tránh gặp lỗi call methods on int ta sẽ dùng các properties và objects có sẵn trong MSSQL, mà trong blogs sử dụng là STY của data type geometry
-> trả về kiểu float
Từ response của server, ta có được 3 cột của bảng là id, hero_name và hero_power. Đặc biệt trong đó cột hero_name có thể chứa chuỗi.
Theo blog thì payload có thể attack kiểu Union based nên mình cũng nhóm thêm union select và kết quả show ra thông tin, tiện cho mình để dump db:
Công việc gần như đã xong, giờ mình sẽ đi mò xem flag ở đâu, nếu như không cho dùng xp_cmdshell để RCE thì chắc flag sẽ nằm ở 1 bảng nào đó.
Xác định được bảng flags
:
Xác định cột của bảng flags
là flag_value
:
Solve
ISITDTU{R3g4in_m0t1vation_w1th_s1mpl3_SQL1}