Phân tích CVE-2022-26503: Lỗ hổng LPE trên Veeam Agent for Microsoft Windows
Bài đăng này đã không được cập nhật trong 2 năm
Gần đây thì Veeam có đưa ra bản patch cho một loạt các lỗ hổng nghiêm trọng trên các sản phẩm của mình bao gồm:
- CVE-2022-26503: ảnh hưởng tới Veeam Agent for Microsoft Windows.
- CVE-2022-26500, CVE-2022-26501, CVE-2022-26504: ảnh hưởng tới Veeam Backup & Replication.
Trong bài viết này, mình sẽ phân tích về CVE-2022-26503.
Sau khi đọc thông tin về CVE này chúng ta nắm được một số thông tin sau:
Vulnerability (CVE-2022-26503) in Veeam Agent for Microsoft Windows allows local privilege escalation. An attacker who successfully exploited this vulnerability could run arbitrary code with LOCAL SYSTEM privileges.
Veeam Agent for Microsoft Windows uses Microsoft .NET data serialization mechanisms. A local user may send malicious code to the network port opened by Veeam Agent for Windows Service (TCP 9395 by default), which will not be deserialized properly.
Diff patch
Như thường lệ, công việc đầu tiên khi phân tích 1day thì ta sẽ cài đặt 2 version của product. Một version bị lỗi và một version là bản patch cho lỗi đó. Ở đây mình dùng 2 version là: 5.0.2.4680 và 5.0.3.4708.
Sau khi cài đặt cả 2 version ta kéo hết DLL của cả hai ra hai folder và tiến hành diff. Về công cụ thì các bạn có thể sử dụng dnSpy
để extract hết DLL ra code C# và sau đó sử dụng WinMerge
để diff cả hai folder. Tuy nhiên trong bài này thì mình dùng công cụ là JustAssembly
để diff trực tiếp các file DLL.
Ưu điểm của công cụ này là ta có thể diff trực tiếp dll mà không cần phải extract ra code C#. Đồng thời nó cũng có thể decompile trong trường hợp muốn nhìn kĩ hơn source code trong quá trình diff.
Sau khi tìm kiếm một hổi thì mình tìm thấy điểm khả nghi sau trong Veeam.Common.Remoting.dll
Vì sao lại sửa đổi ở chỗ này, mình sẽ nói kĩ hơn ở phần sau. Cho đến thời điểm hiện tại ta chỉ biết vị trí gây ra lỗi là ở thuộc tính TypeFilterLevel
nằm trong class CSrvTcpChannelRegistration
. Bây giờ ta sẽ đi phân tích sâu hơn để hiểu tại sao nơi này lại gây ra lỗi.
Phân tích CVE-2022-26503
Theo như thông tin nắm được ở đầu bài viết, ta biết được nguyên nhân gây ra CVE này nằm ở việc local user có thể gửi gói tin độc hại đến port được sử dụng bởi Veeam Agent for Windows Service (mặc định là cổng 9395).
Hãy cùng xem xét xem service nào đang sử dụng port 9395.
có thể thấy rằng Veeam.Endpoint.Service.exe
đang được khởi chạy và lắng nghe ở port 9395.
Xem xét file trên bằng cách load vào dnSpy.
Quan sát thấy nếu chương trình chạy không có tham số truyền vào thì sẽ được chạy như là một service.
Chú ý method OnStart
, khi được thực thi sẽ khởi tạo các biến môi trường (dòng 55).
Tại đây chương trình sẽ thực hiện đăng kí một channel TCP với tên channel là bstcp
, và port là num2
chính là BackupServerPort
. Trong đó num2
nếu chưa được setvalue thì default sẽ là 9392, và nếu cổng đó đã được sử dụng thì sẽ tăng số cổng lên 1 cho đến khi hợp lệ.
Tuy nhiên thì cổng này đã được setvalue ở một nơi khác là 9395. Nên cổng được đăng kí cho TCP channel sẽ là 9395.
Quay lại với việc đăng kí TCP channel, chương trình đăng kí channel với option secure
được set là true
và thuộc tính TypeFilterLevel=Full
.
Nếu các bạn còn nhớ thì ở đầu bài viết khi mà diff patch ta có nhận thấy đây là nơi gây ra lỗi, vậy nguyên do do đâu.
Lý do là chương trình sử dụng .NET remoting để trao đổi dữ liệu giữa client và server, và nếu thuộc tính TypeFilterLevel
được set là Full
thì nó sẽ deserialize request message gửi đến với tất cả các type. Điều này rất nguy hiểm bởi cơ chế hoạt động của .NET remoting là auto deserialize request message mà nếu không kiểm soát chặt chẽ type có thể deserialize thì rất dễ bị tấn công thực thi mã từ xa (RCE).
Cần phải nói thêm về cơ chế trao đổi dữ liệu trong .NET remoting, nếu trao đổi ở kênh truyền TCP thì dữ liệu phải được serialize ở dạng binary sử dụng BinaryFormatter. Với những bạn đã tìm hiểu về lỗ hổng .NET deserialize thì sẽ biết rằng BinaryFormatter là một trong những formatter dễ tấn công nhất vì nó không yêu cầu chặt chẽ về type khi deserialize. Cụ thể về cơ chế trao đổi thông tin này bạn có thể đọc thêm ở bài viết sau của mình: https://viblo.asia/p/net-remoting-la-gi-hacker-loi-dung-no-de-tan-cong-nhu-the-nao-naQZRR1vZvx
Đến đây gần như ta đã có thể khai thác lỗi thông qua .NET remoting, tuy nhiên ta cần phải biết tên của service thì mới có thể khai thác thành công. Quay lại với method OnStart
, thông qua document tại đây ta được biết rằng method này sẽ tự động được thực hiện khi hệ điều hành khởi động. Khi xem xét kĩ hơn ở trong thân của OnStart
thì cả nhánh If lẫn nhánh else đều gọi đến CEpRemotingAPIRegistration.RegisterRemotingType(this)
. Từ đó dẫn đến đoạn code đăng kí dịch vụ có tên là VeeamService
như hình dưới.
Khai thác
Thông qua một bài viết khác về .NET remoting đó là : https://xz.aliyun.com/t/9605. Tác giả giới thiệu một công cụ có thể sửa đổi gói tin TCP để khai thác lỗ hổng trên .NET remoting là ExploitRemotingService.
Để khai thác thành công chúng ta cần 2 bước:
- Gen payload bằng ysoserial .NET, lưu ý là dùng gadget cho BinaryFormatter:
.\ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -o base64 -c "calc"
- Gửi payload lên server sử dụng ExploitRemotingService:
.\ExploitRemotingService.exe --secure --tokenimpersonationlevel=Identification tcp://localhost:9395/VeeamService raw <payload_base_64_from_ysoserial>
PoC
All rights reserved