IV. Ô nhiễm tham số phía máy chủ
1. Định tuyến API nội bộ
Trong phát triển ứng dụng hiện đại, việc sử dụng API nội bộ để xử lý các yêu cầu từ ứng dụng client ngày càng trở nên phổ biến. Khi một người dùng tìm kiếm thông tin, ví dụ như người dùng có tên peter, trình duyệt sẽ gửi một yêu cầu đến server thông qua API công khai:
GET /userSearch?name=peter&back=/home
Yêu cầu này bao gồm các tham số thiết yếu cho frontend, như name=peter
để tìm kiếm người dùng và back=/home
để xác định trang mà người dùng sẽ quay lại sau khi hoàn thành thao tác.
Server xử lý yêu cầu và truy cập API nội bộ
Khi server nhận yêu cầu từ client, nó sẽ lọc và xác định các tham số cần thiết cho backend, rồi tạo một yêu cầu mới tới API nội bộ để lấy thông tin cần thiết. Yêu cầu này có thể có dạng:
GET /users/search?name=peter&publicProfile=true
Trong số các tham số này, có thể có những tham số mà client không yêu cầu, nhưng backend cần để xử lý yêu cầu. Nếu không có biện pháp kiểm tra hợp lý, có khả năng tồn tại lỗ hổng ô nhiễm tham số (parameter pollution), cho phép kẻ tấn công có thể chèn và thay đổi giá trị các tham số mà internal API sẽ sử dụng. Dưới đây là một số dạng ô nhiễm tham số:
- Ô nhiễm tham số trong chuỗi truy vấn (Query String Parameter Pollution)
- Ô nhiễm tham số trong định dạng dữ liệu (Data Formats Parameter Pollution)
- Ô nhiễm tham số trong đường dẫn REST (REST Paths Parameter Pollution)
2. Ô nhiễm tham số trong chuỗi truy vấn
Để hiểu rõ hơn về sự cố này, chúng ta sẽ khảo sát bài lab có tiêu đề Exploiting server-side parameter pollution in a query string. Trong đó, server không yêu cầu tài khoản, nhưng chúng ta có thể tìm thấy chức năng quên mật khẩu với API /forgot-password
.
Kiểm tra cách server xử lý các tham số truyền lên bằng cách thêm một tham số không tồn tại x=y
theo hai cách.
- Không mã hóa ký tự
&
: - Mã hóa URL ký tự
&
:
Nếu server phản hồi từ API cho thấy thông báo lỗi Parameter is not supported., điều này có thể chỉ ra việc xử lý tham số không chặt chẽ.
Hãy kiểm tra cách nhận giá trị của server khi có hai tham số giống hệt nhau. Gửi:
username=administrator%26username=not_exist
Và:
username=not_exist%26username=administrator
Sẽ cho thấy server chọn giá trị tham số đầu tiên, cho phép chúng ta ghi đè tham số khác bên trong API nội bộ nếu nó tồn tại, thông qua tham số unknown_param
.
Chúng ta cần thử nghiệm để tìm hiểu các tham số ẩn bằng cách sử dụng ký tự #
để cắt chuỗi. Gửi giá trị:
username=administrator%23
Server giờ sẽ không nhận được tham số unknown_param
, và phản hồi có thể gợi ý về một tham số khác, như field
. Từ đó, chúng ta có thể sử dụng công cụ fuzzing với danh sách từ khóa để phát hiện giá trị hợp lệ cho tham số ẩn.
Chương trình Python để tìm kiếm giá trị tham số
Để tăng khả năng tìm kiếm, bạn có thể sử dụng đoạn mã Python sau:
import sys
from itertools import permutations, product
def generate_keyword_combinations(keywords):
special_chars = ['', '-', '_']
combinations = set()
for perm in permutations(keywords):
for chars in product(special_chars, repeat=len(keywords) - 1):
combined = perm[0]
for word, char in zip(perm[1:], chars):
combined += char + word
combinations.add(combined)
for perm in permutations(keywords):
camel_case = perm[0].lower() + ''.join(word.capitalize() for word in perm[1:])
combinations.add(camel_case)
return sorted(combinations)
if __name__ == "__main__":
keywords = sys.argv[1:]
if not keywords:
print("Please provide keywords separated by spaces.")
else:
output = generate_keyword_combinations(keywords)
for item in output:
print(item)
Chương trình trên cho phép bạn tạo ra các giá trị khác nhau để phục vụ việc kiểm tra.
3. Ô nhiễm tham số trong định dạng dữ liệu
Ô nhiễm tham số của định dạng dữ liệu khác với ô nhiễm chuỗi truy vấn, vì các tham số được gửi qua nội bộ có thể dùng định dạng gói tin POST
, PATCH
, thường là JSON. Có hai kiểu ghi payload chính:
Kiểu 1: Form-urlencoded tới JSON
Gói tin từ client có dạng:
POST /myaccount
...
name=peter
Và gói tin internal API:
PATCH /users/7312/update
...
{"name":"peter"}
Để thêm tham số ẩn access_level
, payload sẽ trở thành:
POST /myaccount
...
name=peter","access_level":"administrator
Kiểu 2: JSON tới JSON
Tương tự, nếu gói tin từ client có dạng JSON:
POST /myaccount
...
{"name": "peter"}
Payload có thể được xây dựng để thêm tham số ẩn giống như trước, cho phép server xử lý tham số này mà không gặp lỗi.
4. Ô nhiễm tham số trong đường dẫn REST
Khi API nội bộ sử dụng định dạng RESTful, tham số được nhúng vào đường dẫn URL thay vì được đặt thành chuỗi truy vấn. Khi một client gửi yêu cầu:
GET /profile?id=1
Hệ thống internal API có thể được yêu cầu ở dạng:
GET /api/profile/1/info
Trong trường hợp tấn công IDOR thất bại, bạn có thể thử lùi thư mục với payload như id=1%2f..%2f2
, giúp bạn truy cập thông tin về người dùng có id=2
. Việc thực hành khai thác này có thể tìm thấy trong bài lab Exploiting server-side parameter pollution in a REST URL.