Truy cập web ta thấy 1 trang login đi kèm với trang
register:
Thử tạo 1 account rồi login với account đó là thấy như
sau:
Vậy là flag bị chia làm 2 phần, ta sẽ tìm phần 1 ở page này.
Part1: CodeBattle{un1c0d3_st3g44
Tìm tiếp phần 2, sử dụng hint đề cho ta có được file
backup của web gồm 3 file:
login.txt, register.txt và schema.sql. Sau khi quan sát 3 file này ta rút
ra được đó là:
-
Có 2 bảng là Account và privilege
-
Khi người dùng đăng kí thì sẽ thực thi 2
câu truy vấn (trong file register.txt)
-
Như vậy, bất kì người dùng nào đăng kí mới
sẽ bị gán isrestricted = True với
tham chiếu qua uid ở bảng privilege. Và với isrestricted = true
thì account đó sẽ không lấy được flag(hình dưới)
Đầu tiên, khi nhìn đến đoạn này mình nghĩ ngay đến việc
sử dụng multi insert trong SQL để insert vào bảng privilege với cặp giá trị
(uid,isrestricted) với isrestricted = False nhưng thất bại, và lúc này mình thấy có hàm mysqli_real_escape_string() các bạn gg sẽ thấy cách dùng chi tiết của nó, đại khái là nó giúp ngăn ngừa SQL
injection.
Đến đây ta phải đi theo hướng khác! Sau khi nhờ sự trợ
giúp của Luân đại ca thì mình biết đến lỗi SQL
truncation. Các bạn gg để biết rõ
hơn về lỗi này. Ví dụ độ dài cột username trong bảng Account tối đa được phép
100 ký tự, thì khi ta gửi lên 1 chuỗi có độ dài lớn hơn 100 ký tự thì
Mysql sẽ tự động truncate và giữ lại 100
ký tự đầu mà thôi.
Quay lại bài này. Chúng ta để ý thấy trong file
schema.sql không đặt giới hạn cho trường username nên mặc định sẽ là 65535 ký tự
với Mysql. Như vậy chúng ta sẽ gửi lên server với độ dài username > 65535 ký
tự.
Sau khi truncate , câu query thứ hai trong file register
sẽ không có kết quả bởi vì uid của nó tham chiếu đến username vừa bị truncate.
Điều đó nghĩa là trường restricted không được đặt giá trị true, do đó ta có thể
tiến hành login với account vừa tạo và nhận part2 của flag. Sau đây là script
giải quyết:
Part2: _4nd_4_f4m1l14r_ch4l}
Flag: CodeBattle{un1c0d3_st3g44_4nd_4_f4m1l14r_ch4l}