Gần đây mình có dạo trên Liferay một chút thì thấy một CVE có impact khá cao có khả năng dẫn tới RCE hệ thống.
https://liferay.dev/portal/security/known-vulnerabilities/-/asset_publisher/jekt/content/CVE-2024-38002

Theo description, người dùng thông thường cũng có thể nhúng tay vào việc chỉnh sửa một workflow definition thông qua headless API từ đó dẫn tới việc thực thi code tùy ý (RCE) :>. Liferay có vẻ ưu ái cho user admin khi có kha khá chức năng mà admin có thể sử dụng để dẫn tới RCE được backend hệ thống như GogoShell, Groovy Script và cả Workflow. Vậy Workflow là gì mà lại có thể thực thi code?

 

Workflow

Từ phiên bản 7.3, Liferay tích hợp một Engine Workflow cho phép người dùng xem xét và phê duyệt các nội dung như Blogs, Web Content và Wiki trước khi chúng được xuất bản. Workflow giúp định nghĩa bất kỳ số lượng quy trình nghiệp vụ/quy trình làm việc nào, triển khai và quản lý chúng thông qua giao diện.

  • Building Workflow: Workflow được viết theo định dạng file XML với các tag được thiết kế riêng phù hợp, tuy nhiên, để dễ dàng và thuận tiện hơn, có thể sử dụng bản có giao diện chỉ việc kéo thả bằng Workflow Designer Overview.
  • Activating Workflow: Giả sử khi một workflow được kích hoạt cho Blogs, nút Publish sẽ được thay thế bằng nút Submit for Workflow. Khi nhấn nút này, trạng thái của một Blog sẽ được chuyển thành Pending, và Blog đó phải trải qua workflow được chọn sử dụng trước khi được xuất bản. Ví dụ như người đăng bài submit blog của mình lên -> người quản lý phê duyệt nội dung -> public bài đăng.

Trong quá trình định nghĩa một Workflow, có thể thêm các script Groovy code vào để đưa logic và truy cập các dịch vụ Java của Liferay. Các script này sẽ được chạy trong quá trình thực thi Workflow.
Các đoạn code Groovy sẽ được thêm vào <script> tag, <script> tag thì được sử dụng trong <actions> tag. Ví dụ:

 
<actions>
    <action>
        <script>
            <![CDATA[script code goes here]]>
        </script>
        <script-language>groovy</script-language>
    </action>
    ...
</actions>

Ngoài ra, có thể sử dụng một script để quản lý việc phân công, các <script> tag phân công được viết trong <scripted-assignment> tag:

 
<assignments>
   <scripted-assignment>
      <script>
         <![CDATA[
            ...
         ]]>
      </script>
      <script-language>groovy</script-language>
   </scripted-assignment>
</assignments>

Việc thêm các đoạn code Groovy này vào Workflow là không giới hạn, do đó người dùng admin khi định nghĩa một Workflow có thể thêm code Groovy độc hại nhằm thực thi lệnh hệ thống. Sẽ không có gì đáng nói nếu chỉ người dùng admin mới có quyền định nghĩa các Workflow.

 

Headless API

API Headless của Liferay cho phép tương tác theo chuẩn RESTful giúp việc triển khai và sử dụng trở nên đơn giản hơn. Truy cập tại path /o/api, các API này có thể truy cập và sử dụng tùy theo quyền hiện tại của người dùng xác thực. API headless của Workflow:

Sau một hồi mày mò thì mình thấy rằng người dùng xác thực có thể sử dụng API /v1.0/workflow-definitions để list được thông tin của tất cả các Workflow đã được định nghĩa. Các API thêm, chỉnh sửa Workflow khác đều đã bị giới hạn quyền truy cập ngoại trừ 2 API /v1.0/workflow-definitions/save/v1.0/workflow-definitions/update-active

Thực hiện diff code với phiên bản đã fix là 7.4.3.112, mình nhận thấy Liferay đã tạo thêm một class com.liferay.portal.workflow.kaleo.service.impl.KaleoDefinitionServiceImpl

Với một mục đích duy nhất là check quyền của người dùng khi thực hiện 2 API phía trên:

PoC

Mấu chốt của CVE này là việc một vài API headless chưa được phân quyền chặt chẽ dẫn tới khả năng chỉnh sửa lại các Workflow của người dùng thông thường -> RCE hệ thống.

Trước tiên thực hiện list các Workflow đã được định nghĩa trên hệ thống, vì việc sử dụng các Workflow này chỉ có người dùng admin mới có thể thực hiện, do đó việc chỉnh sửa lại các Workflow đang được sử dụng sẽ có tỉ lệ trigger Groovy malicious code cao hơn.

Sử dụng thông tin của Workflow có sẵn, thay thế content (Dữ liệu XML của Workflow dưới định dạng JSON) thành dữ liệu chứa code Groovy RCE và update thông qua API /v1.0/workflow-definitions/save

Sau khi sử dụng API này, Workflow sẽ tự động chuyển về trạng thái "active": false

test2 là người dùng thường (Regular Roles)

Sử dụng API /v1.0/workflow-definitions/update-active để active lại Workflow:

Giả sử Workflow này đang được sử dụng trong Blogs Entry:

Khi thực hiện tạo Blog mới sẽ xuất hiện nút Submit for Workflow

Nhấn nút này sẽ kích hoạt Workflow -> trigger Groovy code -> RCE

Affected Version

Các phiên bản bị ảnh hưởng bao gồm:

  • Liferay Portal 7.4.0 through 7.4.3.111
  • Liferay Portal 7.3.2 through 7.3.7
  • Liferay DXP 2023.Q4.0 through 2023.Q4.5
  • Liferay DXP 2023.Q3.1 through 2023.Q3.8
  • Liferay DXP 7.4
  • Liferay DXP 7.3

Fixed Version

  • Liferay Portal 7.4.3.112
  • Liferay DXP 2024.Q1.1
  • Liferay DXP 2023.Q4.6
  • Liferay DXP 2023.Q3.9

Tổng kết

Mấu chốt và cũng là điều kiện chính của CVE này nằm ở việc phân quyền không đúng chức năng của API Headless trong định nghĩa Workflow. Ngoài ra, để trigger được Groovy code trong Workflow thì Workflow đó phải đang được sử dụng và chỉ có admin mới có thể làm được điều đó. Do đó kịch bản thường thấy sẽ là attacker cố gắng chỉnh sửa tất cả các Workflow đang được publish rồi ngồi đợi con mồi của mình sập bẫy thui. Các bản vá cũng đã khắc phục được lỗ hổng này bằng cách giới hạn lại quyền truy cập và thực hiện các API Headless. Nếu không muốn update version, các nhà phát triển có thể tự patch bằng cách mà Liferay đã fix đó là tạo thêm một class com.liferay.portal.workflow.kaleo.service.impl.KaleoDefinitionServiceImpl

Tham khảo

114 lượt xem