+11

Setup debug .NET và bước đầu phân tích CVE-2019-11217 (updating...)

Mở đầu

image.png

Bonobo Git Server là một Git Server dành cho máy chủ Windows, khi mà Linux đã có rất nhiều các giải pháp xịn xò như Git Lab, thì có vẻ đối với nền tảng Windows, người dùng không có nhiều lựa chọn. Bonobo Git Server hiện đang có hơn 1.7K star trên Github và version hiện tại đang là 6.5. Phiên bản bị lỗi là 6.3. Trước tiên mình sẽ đi vào setup trước đã. Bài này mình sẽ ghi cụ thể các bước, coi như là note lại về cách debug .NET cho khỏi quên và luyện skill debug .NET 😂.

Cài đặt

IIS

Trước tiên là chúng ta cần máy ảo, Mình đã chuẩn bị sẵn một máy ảo Win10, và bắt đầu cài. Chúng ta vào phần Turn Windows features on or off từ Control Panel và bật các tính năng sau để có thể chạy được ứng dụng:

  • Internet Information Services
  • IIS Management Console
  • ASP.NET 4.8
  • Static Content

image.png

Sau khi cài xong và khởi động lại chúng ta đã có thể truy cập vào màn hình quản lý của IIS.

Cài đặt app

Trên trang chủ đang là phiên bản mới nhất, chúng ta tải phiên bản lỗi từ link sau: https://bonobogitserver.com/resources/releases/6_3_0.zip và giải nén. Để được thư mục Bonobo.Git.Server. Copy thư mục này vô C:\inetpub\wwwroot

image.png

Ở đây ta cần điều chỉnh quyền thư mục để user của IIS có thể chỉnh sửa được. Bật cấu hình Properties của thư mục App_Data lên, vào chỉnh full quyền cho IIS_IUSRS:

image.png

Giờ chuyển qua màn hình của Internet Information Services (IIS) Manager:

image.png

Chọn Convert to Application, OK với cấu hình mặc định. Giờ vào phần Authentication của IIS và đảm bảo là Anonymous Authentication được Enabled:

image.png

Truy cập vào http://localhost/Bonobo.Git.Server thấy hiện ra giao diện và setup user admin như vầy là xong. Nếu đến đây bạn vẫn chưa chạy được thì có thể tham khảo thêm video: https://www.youtube.com/watch?v=S3Dm2Z-hc1o

image.png

Cài đặt debug

Khi vào thư mục bin ta có thể thấy các file dll:

image.png

File mình cần quan tâm là: Bonobo.Git.Server.dll. Bật DnSpy lên, clear all tất cả các dll hiện có và load dll này vào:

image.png

Tuy nhiên, hiện giờ vẫn chưa debug được do code đang được precompiled, nên dù đặt breakpoint ở file này, cũng sẽ không hit breakpoint (vì server dùng file precompiled và có dùng file dll này đâu 😂). Để có thể debug được thì mình cần disable tính năng này, chi tiết tham khảo ở đây: https://blog.richardszalay.com/2019/06/14/debugging-sitecore-assemblies/

Sau khi tải file IISAssemblyDebugging.psm1 từ link gist trong bài, bật powershell mới với quyền admin và chạy:

Set-ExecutionPolicy -ExecutionPolicy Unrestricted
Import-Module .\IISAssemblyDebugging.psm1
Enable-IISAssemblyDebugging C:\inetpub\wwwroot\Bonobo.Git.Server\

Giờ chúng ta đã có thể đặt breakpoint và debug được rồi, bấm Ctrl + Alt + P hoặc từ menu Debug > Attach to Process, và chọn w3wp.exe:

image.png

CVE 2019-11217

Ngoài ra còn có CVE 2019-11218 liên quan đến leo quyền từ auth user lên admin, mình sẽ để sau.

Tìm sink và source

Xem thông tin trên https://nvd.nist.gov/vuln/detail/CVE-2019-11217:

The GitController in Jakub Chodounsky Bonobo Git Server before 6.5.0 allows execution of arbitrary commands in the context of the web server via a crafted http request.

Vậy đây là một lỗi RCE và có vẻ như là unauthenticated. Tuy nhiên thông tin chưa được đầy đủ lắm, tìm thêm ở link https://flab.cesnet.cz/advisories/cve-2019-11217 cho chúng ta cái nhìn chi tiết hơn:

Bonobo.Git.Server/Controllers/GitController.cs at private ActionResult GetInfoRefs(String repositoryName, String service) calls GitService.ExecuteServiceByName(…) without sanitizing user supplied string serviceName. Succesfull exploitation process involves creation of the new repository, management of repository configuration and executing arbitrary command through core.editor setting.

Chi tiết đã có, nhưng thay vì đọc patch thì mình sẽ đọc code trước, tìm đến file GitController.cs:

image.png

Chúng ta chú ý đến dòng:

string serviceName = service.Substring(4);

Vậy tham số cần có độ dài tối thiểu 4 ký tự:

chọn Analyze:

image.png

method GetInfoRefs được dùng duy nhất bởi SecureGetInfoRefs

image.png

Chúng ta thấy đã xuất hiện tham số service như trong thông tin. Đọc nhanh qua hàm này ta có thể hiểu flow như sau:

  • Tham số service sẽ được kiểm tra với git-receive-pack, nếu đúng là service này thì sẽ kiểm tra xem User hiện tại có quyền push đối với repo hay không. Nếu không thì văng 401.
  • Trường hợp còn lại, nếu user (đã đăng nhập hoặc anonymous) có quyền xem repo thì sẽ đi vào case trigger lỗi.

Tuy nhiên hàm này được gọi từ đâu hoặc endpoint là gì thì chúng ta chưa biết. Thử tìm nhanh trên github ta phát hiện ra endpoint:

image.png

Như vậy, để trigger được bug unauth thì ta cần GET đến link http://localhost/Bonobo.Git.Server/{repositoryName}.git/info/refs?service=xxxx và như vậy, server cần phải có repo được public ra bên ngoài (chỉ cần xem, không cần push code). Mình setup một repo mới public-repo như sau:

image.png

Giờ đặt breakpoint ở đầu method SecureGetInfoRefs và truy cập vào link: http://localhost/Bonobo.Git.Server/public-repo.git/info/refs?service=git-receive-pack thì hit breakpoint:

image.png

OK, vậy là xong phần source, giờ chúng ta sẽ xem tiếp phần sink. Tìm đến GitService.ExecuteServiceByName, đặt breakpoint ở dòng 31 và continue:

image.png

Chúng ta có thể thấy rất rõ các tham số được truyền vào. Tham số serviceName đã bị cắt đi 4 ký tự đầu và chỉ còn receive-pack và được nối chuỗi với các tham số khác để đưa vào làm tham số cho git.exe (nằm ở C:\inetpub\wwwroot\Bonobo.Git.Server\App_Data\Git) và thực thi.

Và đúng là bản patch đã confirm format của tham số như vậy: https://github.com/jakubgarfield/Bonobo-Git-Server/commit/2e547948f394e78e4cd03c46543b33059ff444cd#diff-45dd4dd61d7c23aa8787e129094a7ba2842de4ea2067538a9f685f6c2cc2e7ef

image.png

Setup Process Monitor và filter các process git.exe:

image.png

sau đó continue, ta sẽ thấy git.exe được thực thi, sau đó spawn git-receive-pack.exe và thực thi:

image.png

Bế Stuck

Sau một hồi thử các tham số khác nhau thì mình nhận thấy:

  • Chúng ta chỉ có thể execute các sub command của git chứ không break out ra ngoài và chạy các cmd tùy ý được (cũng giống như trong miêu tả của CVE). Lý do là payload của chúng ta đã được đưa vào làm tham số của ProcessStartInfo:
var info = new ProcessStartInfo(gitPath, args)
  • Các câu lệnh thực thi đều sẽ có 2 tham số --stateless-rpc--advertise-refs và cả những tham số đằng sau nữa, nên không phải command nào cũng chạy được, thường sẽ văng ra exit code 129 hoặc 128, do dùng sai hướng dẫn sử dụng 😥 và mình đang stuck ở đây.
  • Thử thêm hướng add thêm config thông qua git config để thêm cấu hình core.editor vào cũng vẫn đang chưa làm sao để ignore đống param củ chuối đằng sau được.

image.png

Update 1

Nhờ sự trợ giúp của người em @minhtuan.nguy , mình đã có thể update được setting của core.editor thành binary mong muốn.

image.png

@minhtuan.nguy sử dụng trick thêm " vào trước binary để đưa toàn bộ phần đằng sau thành cmd, và với calc.exe không nhận tham số thì khi trigger RCE sẽ không bị ảnh hưởng: Với cách này, cmd ban đầu:

"C:\inetpub\wwwroot\Bonobo.Git.Server\App_Data\Git\git.exe" {payload} --stateless-rpc --advertise-refs C:\inetpub\wwwroot\Bonobo.Git.Server\App_Data\Repositories\public-repo                    

Sẽ trở thành

"C:\inetpub\wwwroot\Bonobo.Git.Server\App_Data\Git\git.exe" "{payload} --stateless-rpc --advertise-refs C:\inetpub\wwwroot\Bonobo.Git.Server\App_Data\Repositories\public-repo"

và kết quả

image.png

Bước tiếp theo là trigger RCE thông qua việc invoke core.editor, theo mình biết thì có thể thông qua một số lệnh

  • git config -e -f {tên bất kỳ}
  • git commit
  • git commit --amend

Tuy nhiên vẫn là vấn đề cần điều chỉnh đưa phần param thừa đằng sau --stateless-rpc... làm sao cho thành câu lệnh hợp lệ 😂

Updating... (nếu tìm ra được cách trigger RCE)

The End

🇻🇳🇻🇳🇻🇳


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.