Ở bài này mình chỉ viết về 4 challenge của mình nha. (Eval ga VKL 1, Eval ga VKL 2, Baby SQL, FreeFlag).
Source tất cả các bài mình để ở đây SOURCE
Đầu tiên truy cập chall thì chúng ta được nhận 1 source code như sau.
Đầu vào là cmd
được filter khá kĩ, kiểm tra đầu vào nếu có 2 dấu chấm trở lên thì die và limit len là < 65. Nhưng chú ý thì không có system, exec hay các hàm có thể RCE.
Thử với ?cmd=system(id)
thì nhận được blank page => đời không như là mơ.
Đọc phpinfo() thì thấy các hàm có thể RCE đã bị disable.
Bây giờ quay lại xem có thể sài những kí tự hay hàm nào: chr strlen log log1p 2 1 print_r readfile end current next
-> đây là một số hàm có thể sử dụng. Bạn có thể check kĩ hơn và viết code để so disable function với function có trong php thì sẽ ra những hàm nào không bị disable nhé.
Để mọi người hiểu hơn thì mình debug ở đây nhé
Flag -> web-vkl{dm_ch4ll_3z_vllllllll_!!!}
Bài này vẫn được cung cấp source như bài 1.
Đọc thì thấy payload ở ver 1 sẽ không sài được nữa vì đã filter len 1
, nếu như sau ( là 2 và sau _ là a-q cũng bị ban. ext
và scan
chỉ được xuất hiện 1 lần. Mục đích ở đây là chặn next
và scandir
xuất hiện trong input quá 1 lần.
Ở disable function có mở thêm là array_reverse
nếu ai có check lại sẽ thấy. Nhưng trong các filter thì vẫn sót là getallheaders()
=> sử dụng nó thôi :))
Thêm header cc: /
và get lên ?cmd=print_r(next(getallheaders()))
. Tới đây thì đã tạo được /
rồi thì dùng scandir để xem file và folder thôi.
print_r(scandir(next(getallheaders())))
-> flag nằm ở phần từ thứ 2 ở cuối mảng và có tên vaday_la_flag_hahah_hihihi_hoho.txt
.
Cuối cùng là đọc flag.
Flag -> web-vkl{Wow_w0w_writ3_p4yl0ad_1n_5s_3625146215!}
Đầu tiên thử register và login account đó. Khi đăng nhâp vào thì thấy được account có 20 star và status được set là 1. Để vào được /flag
thì star phải >= 100.
Ở đây mình chỉ cần lập 1 account khác và chuyển số -100
thì account của mình đã có 120 star. (Lúc đầu mình tính check số âm và để mọi người race nhưng giảm bớt thì mình làm cách này cho lẹ :3 )
Vô được flag.php thì nhận được 1 source code như sau
Đầu tiên thì pass
là input mình sẽ được đưa thẳng vào câu query sql. dấu '
cũng không được filter => có thể sql injection.
Sau khi thực hiện câu query thì nếu có data pass
trả về thì sẽ không in gì cả => tới đây thì cúng đủ nhận thấy là time-base sqli.
Chủ yếu là đoạn filter ở preg_match
. Ở đây mình đã filter hầu như gần hết các hàm có thể blind sqli, cụ thể hơn là hàm sleep
có thể sử dụng để exploit time-base sqli. Tiếp theo đó là mình đã filter number [0-9].
Trong mysql mình cũng có thể sử dụng benchmark
giống như sleep
để làm delay server responses, nhưng vói điều kiện các tham số trong đó phải đủ lớn. Nếu bạn chưa hiểu có thể tìm hiểu về nó trên google để có thể hiểu rõ hơn.
left
cũng chưa được filter nên có thể sử dụng để thay substr
.
in
để thay cho = like > <
.
Điều khó là tạo số thì mình sử dụng INSTR()
, giải thích về hàm này sơ qua đó là nó sẽ trả về vị trí của chuỗi con mình đưa vào. VD: INSTR("a","a") sẽ là 1, INSTR("ba","a") sẽ là 2 => có thể tạo số.
Giờ là đến việc tạo số đủ lớn cho benchmark()
để có thể làm delay server responses. Ở đây mình sử dụng pow()
với pi()
để tạo ra số đủ lớn => ez time-base.
Khi chạy payload trên mọi người sẽ thấy server sẽ bị delay.
Mình để trong IN
là chữ w
vì nó là chữ cái đầu của flag và bị delay, nếu mọi người để char khác thì nó sẽ không delay lâu như vậy. Tới đây mọi người có thể viết code và brute nhé.
Flag -> web-vkl{Wow_You_Are_Hacker_Sju_Cap}
Sau khi register và login thì nhận được 1 source như sau
Chúng ta có đầu vào là id
và được filter rất nhiều hàm trong mysql, check luôn số từ 1-9 và 1 số kí tự. id
được đưa thẳng vào câu query nên chúng ta có thể sql injection ở đây. Để có thể redirect tới được flag.php
thì câu query $query1 = "SELECT * FROM numbers where id = {$id};";
phải có cột number trả về là 2050 hoặc 2051. Khi đó $_SESSION["admin"]
sẽ set bằng true, mặc định của mỗi account khi mới reg mình set là false.
Lí do mình để 2050 hoặc 2051 là ctf mình diễn ra 2 ngày đó là 21-08-2021 và 22-08-2021, cộng ngày tháng năm lại thì sẽ được 2050 và 2051. Vì vậy mình sài payload sau để có thể redirect tới flag.php
.
Khi vô được flag.php
thì mở mã nguồn lên thấy được ?source
=> access và có source.
Đầu tiên thì thấy được trong source này có 3 tham số nhận đầu vào là id, ai_di, source
. Ở source thì chỉ có chức năng là đọc file. (cho source). Ở id
thì qua preg_match để filter một số function trong mysql và 1-9 và 1 vài kí tự. 0 không được xuất hiện nhiều hơn 1 lần trong input của mình.
Ở đây sót lại mốt số thứ có thể sài được như là union select from 0 ()
và một số thứ khác, mọi người có thể tìm thêm :)).
$query = "SELECT id,flag_name,flag_fake FROM flag WHERE id={$id};";
id mình truyên vào được đưa vào query này và sau đó lấy ra các giá trị id, flag_name, flag_fake
và show ra màn hình.
Ở id
filter còn sót 0 nên mình có thể thử nhập id=0
Nhìn vào như vậy thì cũng có thể thấy được flag real không nằm trong 3 cột này mà cần phải tìm cột khác chưa flag real.
Tiếp tục đến với ai_di
thì chúng được filter các fucntion trong mysql như id
. Các kí tự cũng như thế nhưng chỉ khác number chỉ filter từ 2-9, 1 không được xuất hiện quá 1 lần và 0 không xuất hiện quá 2 lần trong input.
ai_di
sẽ được đưa vô và execute câu query trên. Nếu có lỗi thì sẽ dump ra lỗi của query đó echo mysqli_error($conn);
. Execute thánh công sẽ thì sẽ in ra nice
.
Nhìn vào code trên thì chắc ai cũng đoán được là dựa vô đây để dump ra các cột còn lại có trong flag
(Error-Based SQL Injection) và từ đó sử dụng ?id
ban đầu để đọc data column đó.
Ở preg_match filter còn sót một số hàm toán như exp power
, khi truyền vào một số đủ lớn thì 2 hàm đó sẽ trả về kết quả vượt quá range của INT và dump ra lỗi, mình sẽ chain với câu query của mình => dump được tên cột. Mọi người có thể lên google tìm hiểu về 2 hàm này và cách sử dụng nó để dump ra column có trong table.
Link bài viết mình để ở đây
Error Based SQL Injection Using EXP. Nhưng trong bài viết này người ta sử dụng ~
hoặc truyển number vào nhưng những thứ đó thì mình đã filter. Chỉ có sót lại là số 0 mà 0 thì bạn nhập bao nhiêu 0 vào cũng không thể vượt quá range của INT được.
Tới đây nếu ai vượt qua được step 1 để vô được flag.php
thì dễ rồi hehe. Ở step đó là cách tạo số và giờ sử dụng lại nó thôi.
Mình sẽ để full payload từ step 1 luôn nhé.
Ở bài này có 1 solved và sử dụng hex, mọi người có thể tìm hiểu về hex và sử dụng nó cũng được nhé. Mình đã quên hàm đó :3
Cảm ơn tất cả mọi người đã tham gia WEB-VKL CTF 2021, mong đây là 1 dịp cho mọi người luyện lại các kĩ năng mà bản thân đã học được cũng như giúp được một số bạn học được kiến thức mới. Nếu có một số sai sót gì về challenge thì mong các bạn bỏ qua ♥
THANK YOU !