dựa vào source code mình tìm thấy 2 manh mối quan trọng để thực hiện tấn công sqli:
- sqli_filter = [‘[’, ‘]’, ‘,’, ‘admin’, ‘select’, ‘'’, ‘"’, ‘\t’, ‘\n’, ‘\r’, ‘\x08’, ‘\x09’, ‘\x00’, ‘\x0b’, ‘\x0d’, ’ ']
- query = f"SELECT uid FROM users WHERE uid=‘{uid}’ and upw=‘{upw}’ and level={level};"
để query trả về admin thì mình phải làm cho giá trị của cột uid sau khi select trả về duy nhất 1 giá trị admin. để làm vậy mình có thể sử dụng union:
SELECT uid FROM users WHERE uid=‘{uid}’ and upw=‘{upw}’ and level=1 union select ‘admin’
do khoảng trống , admin , select đã bị filter nên phải tìm cách khác.
khoảng trống có thể thay thế bẳng comment /**/
còn select thì sao? mình tự hỏi liệu có lệnh nào có thể thay thế được không?
vì biết website sử dụng sqlite nên thử vào trang sqlite.org tìm thì mình thấy 2 manh mối về cấu trúc 1 câu lệnh
đi sau UNION sẽ là 1 select-core
vậy select-core là gì? dựa vào sơ đồ mình có thể đoán được đấy là cấu trúc 1 lệnh select. Ngoài select, sơ đồ còn phần ra 1 hướng khác nữa là VALUES
UNION VALUES ? liệu VALUES có thể thay thế cho SELECT không? đoạn này mình sẽ hỏi chat gpt cho nhanh
nhờ chatgpt mình đã biết sqlite có thể dùng VALUES để trả về dữ liệu bảng ngoài SELECT
bây giờ vấn đề cuối cùng là ‘admin’. làm sao để bypass được filter này?
lúc này mình nhớ đến bảng mã ASCII.
liệu mình có thể chuyển từng ký tự mã hoá trong bảng mã hoá thành ký tự thường, rồi sau đó kết hợp chúng lại với nhau không? có hàm nào trong sqlite làm được ko? tiếp tục hỏi chatgpt :))
vậy ‘admin’ cũng chính là: char(97)||char(100)||char(109)||char(105)||char(110)
kết hợp các thông tin mình tìm được lại, mình được payload:
SELECT uid FROM users WHERE uid=‘{uid}’ and upw=‘{upw}’ and level=1//union//values/**/(char(97)||char(100)||char(109)||char(105)||char(110))
lưu ý: // = /****/
cuối cùng cũng ra được cái flag
Bonus:
ban đầu mình có 1 ý tưởng khác đó dùng dấu \ để escape phần uid, sau đó UNION phần upw nhưng tiếc là sqlite không hỗ trợ