SharePoint Server và câu chuyện về research. Phần 1: CVE đầu tay

Thời điểm giữa năm 2021, cộng đồng bảo mật xôn xao vì hàng loạt lỗ hổng 0-day của Exchange được công bố. Người người đi diff, nhà nhà có poc, chẳng cho mình là ngoại lệ, tôi cũng nhảy vào nghiên cứu phân tích cho bằng bạn bằng bè. Tuy nhiên đời không như là mơ, trong khi anh em đã ra lỗi thì bản thân lại đang quanh quẩn ở một phase nào đấy chẳng chút liên quan. Không há miệng chờ poc, tôi bắt đầu nghiêm túc với công việc gọi là research này. Chọn một mục tiêu mà bản thân nghĩ sẽ nhẹ nhàng hơn cũng như để tích lũy kinh nghiệm về .NET – SharePoint Server là ứng cử viên sáng giá.

Công cuộc tìm kiếm CVE đầu tay bắt đầu, mặc dù gặp nhiều khó khăn nhưng sau vài tháng thì tôi cũng có thành quả với lỗ hổng Store XSS (CVE-2022-24472). Vẫn chưa bằng lòng với kết quả này, suy nghĩ của tôi lúc đó là “Các thứ khác có hay không không quan trọng, CVE đầu tay phải là RCE”. Vì vậy tôi đã không để acknowledgement và tiếp tục dấn thân sâu hơn vào con đường này. Ông trời không phụ lòng người, sau hơn nhiều tháng tìm kiếm và chờ đợi, ngày 13 tháng 12 năm 2022, lỗ hổng được vá và đánh số CVE-2022-44693.

Phân tích

Đây là một biến thể của CVE-2021-34520 tồn tại trong chức năng Workflow của SharePoint. Mọi người có thể tham khảo phân tích của lỗ hổng này tại đây. Có thể tóm tắt như sau:

  • Workflow là một luồng công việc được thực hiện một cách tự động, bao gồm nhiều bước.
  • Các bước này sẽ chúa một hoặc nhiều hoạt động (activity) và các điều kiện (rule).
  • SharePoint có một danh sách các activity/rule được đánh dấu là an toàn (allow list) và người dùng chỉ có thể tạo workflow (dưới định dạng XML) với các activity/rule đó. Quá trình kiểm tra đều dựa trên định dạng XML.
  • SetVariableActivity (nằm trong danh sách an toàn) có chứa thuộc tính ValueType. Nếu thuộc tính này mang giá trị là chuỗi System.Resources.ResourceSet thì có thể dẫn đến remote code execution.
  • Lỗ hổng được vá bằng cách kiểm tra giá trị của các thuộc tính với allow list. Nếu thỏa mãn thì sẽ thực thi và ngược lại.
  • Payload sẽ như sau:

1. Payload cho CVE-2021-34520

Trong qua trình kiểm tra workflow config, hàm IsGoodWorkflowCore trong thư viện Microsoft.SharePoint.dll được gọi với xmlReader chính là file config và authorizedTypes là allow list đã quy định từ sẵn.

2. Hàm IsGoodWorkflowCore trong bản vá tháng 10 năm 2022

Đây là một hàm rất dài, chức năng của nó là đọc lấy giá trị của từng node và thuộc tính sau đó đem so sánh với allow list, cuối cùng là trả về true/false nếu thỏa mãn/không thỏa mãn. Cũng vì sự dài dòng nên tôi đã chăm chăm vào việc tìm chỗ bypass logic mà không để ý đến những dòng code cuối. Nếu quá trình đọc xảy ra bất kỳ exception nào thì chương trình sẽ ghi log lại và … return true. Do đó ta chỉ cần tìm một đoạn code có khả năng gây exception thì sẽ bypass hoàn toàn được cơ chế này. Chúng ta sẽ đi tiếp vào hàm IsAuthorizedType, hàm này được gọi bởi IsGoodWorkflowCore. Nó có tác dụng đọc và so sánh thuộc tính từ workflow config.

3: Hàm IsAuthorizedType trong bản vá tháng 10 năm 2022

Tại dòng 221, attributeValue được tách ra với ký tự “{” sau đó gán vào mảng array. Còn tại dòng 225, giá trị array[1] được gọi. Ta dễ dàng thấy rằng nếu attributeValue mang giá trị là “” hoặc “{}” thì sẽ gây ra IndexOutOfRangeException vì lúc này mảng array chỉ có duy nhất một phần tử. Tới đây mọi thứ đã quá đơn giản, mặc dù vẫn còn một số vấn đề khác để hoàn thành CVE nhưng nó không ảnh hưởng quá nhiều đến kết quả. Payload cho lỗ hổng như sau:

4. Payload cho CVE-2022-44693

Ở đây tôi chọn thuộc tính Name với giá trị là “{}” do nó là thuộc tính mặc định và có thể nhận bất cứ giá trị nào (quá trình parse XML để chạy workflow sẽ có bước kiểm tra thuộc tính có tồn tại trong acitvity/rule hay không). Bên cạnh đó, thuộc tính xmlns cũng có thể được sử dụng thay vì Name. Ngoài ra, còn rất nhiều vị trí có khả năng gây exception, ví dụ như dòng 243 trong chính hàm IsAuthorizedType.

Kết luận

Mặc dù impact là remote code execution nhưng theo đánh giá của những người anh em xã hội, đây là một bug khá dễ, khả năng bị trùng không nhỏ. Và thật sự nó đã bị “dup”, tuy nhiên đây vẫn là một thành quả không nhỏ, cũng như một bước đệm để tôi tiếp tục với bug workflow ở phần 2.