Drupal là một mã nguồn mở content management system (CMS) được sử dụng bởi hơn một triệu website trên toàn thế giới, bao gồm các trang web chính phủ, bán lẻ, các doanh nghiệp, tài chính. Tuy nhiên 28/3/2018 team security của Drupal đã công bố một lỗ hổng được đánh giá rất nghiêm trọng với tên là drupalgeddon2 (CVE-2018-7600). Lỗ hổng này cho phép kẻ tấn công không cần xác thực mà vẫn có thể remote code execution. Lỗ hổng này ảnh hưởng các version của Drupal từ 7.x đến trước 7.58, 8.3.x đến trước  8.3.9, 8.4.x đến trước 8.4.6, 8.5.x đến trước 8.5.1. Lỗ hổng được ước tính sẽ ảnh hưởng đến hơn một triệu người dùng và trang web của Drupal. Tồn tại lỗ hổng này là do Drupal không làm sạch đầu vào đối với các yêu cầu Form API (FAPI) AJAX.

Trong bài viết này tôi sẽ trình bày các khai thác lỗ hổng trên drupal version 8.5 và cách tôi tìm ra những website bị ảnh hưởng bởi lỗ hổng này.

Lỗ hổng drupalgeddon2

Render array

Render array, cấu trúc core của  Render API, là mảng phân cấp có chứa dữ liệu được hiển thị và các thuộc tính mô tả cách hiển thị dữ liệu. Một mảng render được trả về bởi một hàm để markup được gửi đến trình duyệt web hoặc các dịch vụ khác, cuối cùng sẽ được render bằng cách gọi hàm drupal_render(). Ở mỗi mức trong cấu trúc phân cấp của mảng render có một hoặc nhiều phần tử mảng. Các phần tử mảng có tên bắt đầu bằng ‘#’ được gọi là ‘properties’, các phần tử mảng với tên khác được gọi là “children”. Tên của các children khá linh hoạt trong khi tên của các ‘properties’ được xác định từ trước. Một số  properties được định nghĩa từ trước như là: form, html_tag, value, markup. Một trường hợp đặc biệt của mảng render là form array, trong đó sẽ chỉ định các phần tử của form cho form HTML. Một mảng render có thể trông như sau:

Để có thể khai thác được lỗ hổng này, chúng ta phải sử dụng thuộc tính #post_render với một giá trị là PHP function exec (dùng để thực hiện một lệnh chỉ định). #post_render được xử lí trong core/lib/Drupal/Core/Render/Renderer.php như sau:

Đây chính là đoạn chúng ta cần tiêm payload để có thể remote code execution. Vấn đề ở đây là cần phải tìm được dữ liệu người dùng được nhập ở đâu để dữ liệu được truyền đến đây. Như tôi đã nói ban đầu, lỗ hổng này cho phép kẻ tấn công không cần xác thực mà vẫn có thể remote code execution, vì vậy ta sẽ tập trung vào registering a new user.

Tạo payload để thực hiện lệnh tuỳ ý

Tiếp theo chúng ta cần tạo một payload để thực hiện một lệnh tuỳ ý. Tạo payload sẽ dựa trên Render array để có thể lừa drupal thực hiện render mảng của chúng ta, tức là khi đó sẽ thực hiện một lệnh tuỳ ý. Như tôi đã trình bày bên trên, tạo Render array sử dụng thuộc tính #post_render và hàm exec (thực hiện lệnh theo chỉ định) là phần tử đầu tiên của mảng:

mail[ #post_render ] [] = ‘exec’

Tiếp theo cần xác định tham số thực hiện. Quay trở lại hàm render tôi đã trình bày:

Tham số của hàm call_user_func có thuộc tính #children, vì vậy tham cần thực hiện của tôi sẽ được truyền vào như sau:

mail[ #chidren ] = ‘uname -a’

Kết quả trả về như sau:

Như vậy tôi có thể remote code execution mà không cần phải thực hiện bất kỳ một xác thực nào.

Vá lỗ hổng

Các nhà phát triển Drupal đã công bố bản vá, thêm một lớp RequestSanitizer với phương thức stripDangerousValues để xoá tất cả các phần tử đầu vào của mảng có key bẳt đầu là “#”. Phương pháp này làm sạch đầu vào trong  $_GET, $_POST và $_COOKIES.

Drupal phiên bản 8.6.5

/core/lib/Drupal/Core/DrupalKernel.php

/core/lib/Drupal/Core/Security/RequestSanitizer.php

Hàm stripDangerousValues lần lượt xác minh tất cả các tham số đầu vào, các phần tử đầu tiên của mảng đầu vào có giá trị bắt đầu “#” và các giá trị không được liệt kê trong danh sách trắng sẽ bị xoá.

Cách tôi tìm ra những website bị ảnh hưởng bởi lỗ hổng này như thế nào?

Lỗ hổng này được công bố 03/29/2018, được đánh giá là highly critical.  Tôi quyết định chạy một script quét hàng trăm ngàn website xem còn có những website nào còn bị lỗ hổng này hay không. Về script, mã khai thác tôi có tham khảo tại đây.

Mã khai thác này là thực hiện trên Drupal 7. Các tham số của mã khai thác tương tự như tôi đã phân tích trên, thay vì dùng function “exec”, mã khai thác này sử dụng function “passthru” cũng dùng để thực hiện lệnh. Tham số truyền vào cho function “passthru” là lệnh whoami. Kết quả trả về tôi lưu vào biến parsed_result.

Tôi lấy kí tự đầu tiên của biến này nếu như nó là một kí tự ascii, tôi sẽ trả về True, tức là trang web đó bị lỗi.

Kết quả cũng khá bất ngờ khi tôi nhận được gần 10 trang web vẫn bị ảnh hưởng của lỗ hổng nghiêm trọng này, đặc biệt trong đó có cả một trang web tạp chí kinh doanh nổi tiếng của Anh cũng bị ảnh hưởng.

Tôi cũng thực hiện kiểm tra lại trang web tạp chí này bằng tay, bằng cách chạy mã khai thác mà tôi đã chia sẻ bên trên:

Lời kết

drupalgeddon2 là một lỗ hổng nghiêm trọng của drupal, việc khai thác cũng khá dễ dàng khi đã có mã khai thác trên mạng. Hiện nay có rất nhiều các tổ chức, doanh nghiệp, tài chính, chính phủ có trang web sử dụng mã nguồn mở drupal. Vì vậy để phòng ngừa, ngăn chặn lỗ hổng này cách đơn giải nhất là cập nhật drupal lên phiên bản mới nhất.

Tài liệu tham khảo