Server side request forgery vulnerabilities (SSRF) - Các lỗ hổng giả mạo yêu cầu phía máy chủ (Phần 1)
I. Đặt vấn đề
1. Giới thiệu
Server-side request forgery (thường được gọi là SSRF) là một dạng tấn công trong đó kẻ tấn công lợi dụng một tính năng của server public nhằm truy xuất trái phép dữ liệu từ một trang web chỉ định khác, thường là các trang web back-end ở chính server đó. Để các bạn có thể hình dung rõ hơn về dạng lỗ hổng này, chúng ta cùng xét ví dụ sau:
Trong quá trình trao đổi dữ liệu với server public (server ), kẻ tấn công lợi dụng server gửi request tới server back-end (server , mạng nội bộ). Sau khi phân tích request này, server nhận thấy đây là một request đáng tin cậy do nó được gửi từ server , từ đó trả về response tới server , và server tiếp tục trả về dữ liệu tới kẻ tấn công. Như vậy kịch bản khai thác hoàn thành, cách thức hoạt động giống hệt với chiêu thức "mượn đao giết người"! Đây cũng chính là lý do dạng tấn công này được gọi là "giả mạo yêu cầu phía máy chủ" - kẻ tấn công mạo danh thành máy chủ để truy xuất dữ liệu nhạy cảm một cách "hợp pháp"!
2. Tầm ảnh hưởng
Kẻ tấn công thường lợi dụng kiểu tấn công này giả mạo yêu cầu truy cập tới các trang web vốn cần quyền hạn cao hoặc không nằm trong phạm vi truy cập của người dùng thường, đó có thể là các trang dành cho quản trị viên, các end point chỉ có thể truy cập từ local hoặc chứa dữ liệu nhạy cảm. Từ đó thu thập trái phép dữ liệu hoặc thực hiện các hành vi phá hoại, trong một số trường hợp có thể leo thang từ tấn công SSRF lên tấn công Command Injection. Lỗ hổng Server-side request forgery được xếp ở vị trí số trong thông kê Top lỗ hổng bảo mật web của OWASP vào năm (A10:2021-Server Side Request Forgery (SSRF))
II. Phân tích và khai thác các lỗ hổng Server-side request forgery
1. Lỗ hổng SSRF trong một số ngôn ngữ
1.1. Ngôn ngữ PHP
Lỗ hổng SSRF có thể xuất hiện trong ngôn ngữ lập trình PHP khi các nhà phát triển sử dụng chưa tốt một số hàm làm việc với URL. Ví dụ xét đoạn code sử dụng hàm file_get_contents()
sau:
<?php
if (isset($_GET['url'])) {
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content;
} else {
echo "Give me the URL to show your content!";
}
Đoạn code trên in ra nội dung trang web thông qua tham số url
được truyền bởi người dùng bằng hàm file_get_contents()
. Ví dụ với url=https://google.com
:
Do trang web không có bất kỳ phương án ngăn chặn tấn công SSRF, nên kẻ tấn công có thể dễ dàng truy xuất nội dung tệp /etc/passwd
:
Hoặc đọc nội dung tại một port đang mở khác của server - vốn dĩ chỉ có thể truy cập thông qua mạng local:
Ngoài ra các hàm khác như fscokopen()
, curl_exec()
, ... nếu cài đặt thiếu cẩn thận cũng có nguy cơ gây ra lỗ hổng SSRF, các bạn có thể tìm hiểu thêm qua các tài liệu trên Google.
1.2. Ngôn ngữ Python
Xét đoạn code Python sử dụng thư viện Slack sau:
from flask import *
import requests
app = Flask(__name__)
@app.route('/ssrf')
def follow_url():
url = request.args.get('url', '')
if url:
return (requests.get(url).text)
return "no url parameter provided"
if __name__ == '__main__':
app.run(host = "0.0.0.0", port = 9999)
Do không thực hiện ngăn chặn lỗ hổng SSRF đối với tham số url
được truyền bởi người dùng nên trang web có thể bị tấn công SSRF như sau:
2. Lỗ hổng SSRF truy cập local server
Kẻ tấn công thường tận dụng lỗ hổng SSRF để truy cập các trang web vốn dành cho tài khoản có quyền quản trị viên hoặc chỉ có thể truy cập từ phía local server. Từ đó có thể sử dụng các chức năng của các trang web này. Local server thường được xác định với địa chỉ URL dạng: http://127.0.0.1
hoặc http://localhost
. Xét bài lab sau:
Phân tích lab Basic SSRF against the local server
Miêu tả: Chức năng stock check của trang web lấy 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. Để giải quyết bài lab, chúng ta cần khai thác lỗ hổng SSRF truy cập vào trang quản trị viên có địa chỉ http://localhost/admin
và thực hiện xóa tài khoản người dùng carlos.
Trang web chứa chức năng kiểm tra số lượng hàng còn lại trong kho:
Quan sát request và response trong Burp Suite khi sử dụng chức năng này:
Tham số stockApi
truyền bằng phương thức POST cho hệ thống giá trị là một địa chỉ URL http://stock.weliketoshop.net:8080/product/stock/check?productId=1&storeId=1
. Địa chỉ này chỉ có thể truy cập từ mạng local.
Do hệ thống nhận giá trị stockApi
là một địa chỉ URL nên chúng ta có thể dự đoạn tại đây có thể chứa lỗ hổng SSRF. Thực hiện kiểm tra: Sử dụng Burp Collaborator, thay giá trị stockApi
bằng domain mới được sinh ra:
Gửi request, kết quả tại client collaborator nhận được request tương tác - DNS lookup thành công:
Chứng tỏ chức năng stock check có thể tương tác với bất kỳ URL nào, khả năng lớn chứa lỗ hổng SSRF. Bởi vậy, chúng ta có thể khai thác lỗ hổng truy cập trang quản trị bằng một số cách như sau:
- Payload :
stockApi=http://localhost/admin
- Payload :
stockApi=http://127.0.0.1/admin
Cuối cùng, thực hiện xóa tài khoản người dùng carlos bằng cách truy cập tới đường dẫn /admin/delete?username=carlos
Payload: stockApi=http://127.0.0.1/admin/delete?username=carlos
Bài lab hoàn thành:
Các tài liệu tham khảo
- https://portswigger.net/web-security/ssrf
- https://www.geeksforgeeks.org/server-side-request-forgery-ssrf-in-depth/
- https://owasp.org/Top10/
©️ Tác giả: Lê Ngọc Hoa từ Viblo
All rights reserved