+6

Phát hiện RCE nhưng... bạn phải đăng nhập trước đã: Câu chuyện CVE của mình với 56.000 host!

Sumary

Bạn có biết rằng có những lỗ hổng nghe có vẻ rất nguy hiểm nhưng lại có một điều kiện 'bé xíu' là bạn phải đăng nhập không? Hôm nay, mình sẽ kể cho các bạn nghe về một lỗi RCE mà mình đã phát hiện và ảnh hưởng đến hơn 56.000 host. Nhưng đừng quá lo lắng, bạn sẽ cần phải đăng nhập để khai thác nó! Lỗi dẫn đến RCE này được định danh CVE-2024-46256 và CVE-2024-46257.


Bối cảnh

Lỗ hổng này xuất hiện trong Nginx Proxy Manager, một ứng dụng web phổ biến sử dụng để quản lý proxy nginx do nhiều bên đang sử dụng. Với hơn 56.000 host bị ảnh hưởng, đây thực sự là một lỗi đáng lo ngại. Và đúng thế, mình đã tìm thấy nó!

image.png

Quá trình phát hiện ra lỗ hổng

Nói thật với mọi người, mình đã từng bị ám ảnh với những CVE, mình quay cuồng trong việc tìm lỗi từ các opensource để cố gắng cho mình một cái CVE. Nhưng có lẽ, đúng như mọi người nói, càng cố gắng tìm càng không thấy, đôi khi vô tình lại hay hơn. Đúng vậy, mình đã vô tình phát hiện được cái CVE đầu tiên của mình.

Vẫn là một buổi chiều, mình vô tình tìm thấy một site đăng nhập Nginx Proxy Manage với đường link dẫn tới github [https://github.com/NginxProxyManager/nginx-proxy-manager]

image.png

Cũng thử tìm kiếm trên Shodan như hình trên bạn thấy, mình thấy đây là một tiềm năng nào đó cho bản thân. Bắt tay vào tìm thôi nào!!!

Setup hệ thống

Rất may, hệ thống này lại có sẵn docker file để tạo container, với các bước setup đơn giản, mình đã có cho mình một hệ thống mới nhất. Thông tin đăng nhập mặc định cũng được tạo sẵn admin@example.com / changeme . Bên cạnh đó, mình tải luôn source code bản mới nhất để có thể whitebox cho tiện.

Xác định lỗi

Trước tiên là tìm hiểu hệ thống có gì đã! Thường sẽ thực hiện sử dụng lướt qua để mình hiểu được nghiệp vụ hệ thống. Rồi từ các api thu được mình tra cứu trong code. Hệ thống này sử dụng NodeJS. Đây là một ngôn ngữ mà hiếm khi nào mình sử dụng, việc đọc code ở mức hiểu là vẫn có thể thực hiện được, mình cũng phải áp dụng cả ChatGPT cho việc hiểu được code. Cũng không có nhiều kinh nghiệm liên quan đến research CVE, 1-day gì cả, tất cả đều tự học từ internet. Thiếu đâu thì tìm và đọc đó.

Khi đã hiểu được hết các chức năng và trace được các api trả về được xử lý ở đâu thì mình đã nghiên cứu sâu hơn vào từng file trong folder /nginx-proxy-manager-2.11.3/backend/internal. Ở đây có một file khiến mình chú ý hơn cả certificate.js. Tại sao ư? Bởi vì có một số dòng code như thế này:

image.png

Theo kinh nghiệm của bản thân, cái gì cộng chuỗi cũng có thể tiềm năng có lỗi. Nhưng khoan, sao lại lộ liễu thế, thử truy ngược lại bản mới này được comment gì khi release không:

image.png

Diff patch:

image.png

Trong đầu mình đang nghĩ, ủa, sao fix như chưa fix thế nhỉ? Tại sao mình lại nghĩ vậy ư? Thật ra nếu chú ý thì có thể thấy biến certificate.domain_names

image.png

Domain name là giá trị chúng ta có thể kiểm soát, đúng vậy, ý tưởng bừng lên, Command Injection rồi!!!

Case này thì quá cơ bản với trường hợp cộng chuỗi rồi, thêm đôi ba cái | là thành công thôi quá dễ: test.com" || whoami # "

image.png

Có thể thấy lỗi trả về không hề trả thông tin gì. Nhưng check debug trong docker có gì nào:

image.png

Ohhh! Root

Chính xác là những gì mình cần. Sau đó thì thử các câu lệnh khác cũng tương tự, bật debug check thì quá là ok! Sau đó là thực hiện reverse shell cũng thành công

image.png

Bên cạnh đó, mình đã trace thêm các hàm tương tự thực hiện execute command thì cũng thấy một hàm bị lỗi tương tự.

Report

Sau các bước confirm và viết POC hoàn chỉnh cho lỗi, mình lập tức thực hiện report CVE này đến https://www.cve.org/. Và chờ đợi!

Thật vui khi 2 lỗi report đều được gán CVE với các tên lần lượt là CVE-2024-46256 và CVE-2024-46257, bên cạnh đó, trong lúc chờ đợi lỗi RCE được cấp CVE thì mình cũng tìm được thêm 1 lỗi trên hệ thống và cũng submit, thằng em ngồi trên công ty cứ đùa bữa nay submit như rau ấy nhỉ? 😄 Mình cũng chỉ biết cười thôi :v

image.png


Kết

Phương án khắc phục tạm thời

Tại thời điểm này, nếu có thể các bạn hãy sửa lại mã nguồn của hệ thống tại vị trí mình có chụp ở phía trên.

Còn một số cách khả dĩ hơn nếu không can thiệp code như:

  1. Tạm thời giới hạn truy cập vào cổng dịch vụ hoặc không public ra internet
  2. Thay đổi thông tin đăng nhập với bản docker, và sử dụng mật khẩu mạnh với hệ thống này
  3. Cách cuối ai cũng biết

image.png

Tổng kết

Hãy cố gắng đôi khi thành công sẽ là điều bất ngờ!

Và đừng dùng cộng chuỗi cho các câu lệnh thực thi command trong hệ thống :V

Update 23/10/2024:

Hệ thống đã được fix bằng cách thêm filter để chặn các giá trị có thể khiến command injection xảy ra như sau: image.png

Link commit fix: https://github.com/NginxProxyManager/nginx-proxy-manager/pull/4073/commits/c39d5433bcd13993def222bbb2b6988bbb810a05


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí