PHÂN TÍCH VÀ XÂY DỰNG POC KHAI THÁC CVE-2022-36804

14/10/2022

PHÂN TÍCH VÀ XÂY DỰNG POC KHAI THÁC CVE-2022-36804 
+]
Introduction:
Mục tiêu nghiên cứu lần này sẽ là Bitbucket Server, một nền tảng thường được triển khai on-premise và sử dụng git cho nhiều hoạt động trong phần mềm.
Chúng tôi đã phát hiện một lỗ hổng argument injection cho phép chúng tôi thực thi các lệnh tùy ý thông qua tham số --exec cho git. Lỗ hổng này tồn tại do cách các thư viện khởi tạo process ngầm khi xử lý các null bytes.
Tất cả các phiên bản Bitbucket Server và Datacenter được phát hành sau 6.10.17, bao gồm tất cả các phiên bản từ 7.0.0 đến 8.3.0 đều bị ảnh hưởng bởi lỗ hổng này.
Atlassian đã khắc phục lỗ hổng này một cách nhanh chóng và gắn tag CVE-2022-36804 cho lỗ hổng này. 
[+] Methodology:
Để setup môi trường thực hiện nghiên cứu, chúng tôi đã thiết lập một container Docker chạy Bitbucket Server bằng cách sử dụng một image từ Docker Hub: https://hub.docker.com/r/atlassian/bitbucket-server.
Sau khi thiết lập môi trường, chúng tôi có thể sử dụng pspy để log tất cả các process với mục tiêu là tracking các điểm tiếp nhận (sinks) của lệnh git.
Trong khi pspy đang chạy, chúng tôi thực hiện một số action trong Bitbucket và hy vọng sẽ kích hoạt lệnh git bằng một cách nào đó. Ngoài ra, chúng tôi còn tạo một repository dưới dạng người dùng để xây dựng playground cho các lệnh sau này có thể gọi đến git.
Để tìm các điểm tiếp nhận mà lệnh git được thực thi cùng với đầu vào từ người dùng, chúng tôi bắt đầu thay thế các tham số request liên quan đến repository đã tạo bằng một chuỗi kí tự ngẫu nhiên để xác định liệu nó có xuất hiện trong lệnh được thực thi hay không.
Chúng tôi thực hiện kiểm tra trong một khoảng thời gian ngắn và đã tìm thấy một lỗ hổng Argument injection trong một subcommand của git, tuy nhiên nó không có tác động gì đặc biệt tới bảo mật hệ thống (/rest/api/latest/projects/~USER/repos/repo1/browse?at=--help).
Cuối cùng, chúng tôi cũng tình cờ phát hiện ra lỗ hổng command execution tại endpoint /rest/api/latest/projects/PROJECTKEY/repos/REPO/archive có chức năng truyền một bản archive của repository khi được request. Khi xem API documentaion cho endpoint này, chúng tôi nhận thấy có một tham số prefix được map tới "--prefix=" trong subcommand archive.
Để inject một tham số mới, chúng tôi thử sử dụng byte null và bất ngờ phát hiện rằng khi cung cấp đầu vào padding%00--option%00padding, xuất hiện một lỗi với thông báo --option is not a option to git subcmd chứng tỏ việc inject đã thành công. 
[+] Exploitation:
Câu hỏi đặt ra là sau khi có thể thực hiện arguemnt injection, làm thế nào để chúng ta có thể thực thi RCE? Câu trả lời được tìm thấy trong các chức năng có sẵn trong subcommand git archive, cụ thể là tham số --exec được định nghĩa như sau trong Git’s documentation:

 
anh-1.png
Đầu tiên chúng ta có thể thấy tham số trên chưa thể thực thi một lệnh tuỳ ý vì nó đang cần path đến git-upload-archive, thêm vào đó, tham số này cũng yêu cầu chúng ta chỉ định --remote, thường là remote SSH repository.
Chúng tôi đã tiến hành thử nghiệm trên local và phát hiện ra rằng khi gọi lệnh sau:

 
anh-2.png
sẽ dẫn tới thực thi execve('/bin/sh','-c','echo pew# /tmp')
Do vậy, công việc còn lại chỉ là xây dựng một payload cho API endpoint trong Bitbucket. Chúng tôi có thể sử dụng argument injection và lợi dụng điểm yếu của các cờ --exec--remote trong archive subcommand để có thể thực thi RCE khi không cần xác thực với Bitbucket với nội dung payload:

 
anh-3-anh-bia-(1).png
Để khai thác lỗ hổng này mà không cần, cần có public repository trong môi trường Bitbucket Server và ta cũng phải có thông tin về các biến projectKeyrepoSlug, đây là các điều kiện tiên quyết phải có để có thể khai thác thành công lỗ hổng này.
Khi thực hiện nghiên cứu, đôi khi chúng ta tìm ra một lỗ hổng, nhưng quan trọng là cần hiểu bản chất của lỗ hổng đó là gì.
Trong trường hợp này, việc phân tích nguyên nhân gốc của lỗ hổng này là cần thiết để chúng ta có thể hiểu tại sao byte null cho phép chúng ta inject các argument git archive subcommand.
Chúng tôi bắt đầu bằng việc phân tích ngược bản vá của Atlassian, và chúng tôi nhận thấy Atlassian đã vá lỗ hổng bằng cách kiểm tra byte null trong tất cả các index của các argument được truyền tới com.zaxxer.nuprocess.NuProcessBuilder cho thấy rằng lớp này có thể chịu trách nhiệm phân tách lệnh qua byte null.
Sau khi đọc qua lớp com.zaxxer.nuprocess.NuProcessBuilder, chúng tôi đã xác nhận giả thuyết ban đầu về lý do tại sao %00 hoạt động. Có thể thấy rằng com.zaxxer.nuprocess không sử dụng ProcessBuilder hoặc getRuntime().exec mà thay vào đó sử dụng hàm native Java_java_lang_ProcessImpl_forkAndExec yêu cầu char array làm command argument.
Các index trong char array được phân tách bằng byte null, và với cách hàm prepareProcess biến đổi các argument, chúng tôi có thể tạo ra các index mới trong char array bằng cách inject byte null.
Để mô tả điều gì đang xảy ra khi chúng ta cung cấp đầu vào người dùng với byte null, chúng ta có thể nhìn vào flow dưới đây:
 String Array to Char Array + VULN:

 
anh-4.png
Dưới đây là đoạn mã gây lỗi, cụ thể function prepareProcess:
 
anh-5.png
anh-6.pnganh-7.png
Và đây là đoạn code được cập nhật từ bản vá của Atlassian giúp khắc phục lỗ hổng này:
 
anh-8.png
 [+] Vendor Response:
 - Ngày 19 tháng 7 năm 2022: Lỗ hổng RCE được submit cho Atlassian thông qua BugCrowd.
- Ngày 21 tháng 7 năm 2022: Lỗ hổng RCE được phân loại ưu tiên bởi BugCrowd.
- Ngày 21 tháng 7 năm 2022: Atlassian xác nhận và trao giải 6.000 USD cho lỗ hổng RCE.
- Ngày 24 tháng 8 năm 2022: Atlassian submit CVE-2022-36804 và công bố một advisory.
- Ngày 24 tháng 8 năm 2022: Atlassian đã cung cấp bản patch.

 [+] Vendor Response:
Các chi tiết khắc phục được cung cấp từ advisory của Atlassian đảm bảo rằng lỗ hổng này không thể bị khai thác.
Bạn có thể tìm thấy advisory từ Atlassian tại đây theo đường dẫn.