- vừa được xem lúc

Tìm cách RCE trên Manageengine ServiceDesk version cổ tới mức không bị affect bởi một CVE RCE nào

0 0 16

Người đăng: Real Alpha Man

Theo Viblo Asia

Chuyện là trong hệ thống công ty mình đang chạy 1 con server ManageEngine ServiceDesk gần chục năm tuổi (xin phép được giấu version). Lúc mới vào công ty khoảng 8 tháng trước cũng được giao việc check xem con này có lỗi gì không thì mình nhận thấy nó cổ đến mức không bị một cái CVE nào nghiêm trọng, vì thế cũng không chứng minh được impact để yêu cầu update.

Dạo gần đây công ty có triển khai thử nghiệm một số giải pháp SOC mới, mình được giao nhiệm vụ redteam vào những con được giám sát để test, trong đó có con này. Nghĩ lại vẫn có gì đó cay cay, và mình cũng muốn xem trình độ của mình sau 8 tháng có tăng thêm tí nào không nên mình đã quyết định focus vào nó. Đây là hành trình từ không có gì đến RCE được hệ thống.

1. Tìm lỗ hổng trong ServiceDesk

Tải version của con hàng này về, mình tập trung tìm các endpoint unauth trước. Ngày trước mình hay tìm lỗi dựa vào sink, cứ search string ví dụ Runtime.exec nhưng như thế sót khá nhiều nên dạo gần đây mình hay tìm theo source.

Nhanh chóng phát hiện ra 1 endpoint unauth dính LFI là /fosagent/repl/download-file?basedir=4&filepath=<file> (Sau này check lại mới biết nó cũng đã được gắn CVE từ trước)

Servlet handle là com.zoho.clustering.agent.filerepl.api.DownloadFileServlet, nhận trực tiếp filepath mà không check gì cả, sau đó read file và trả về dưới dạng attachment

Mừng rơi nước mắt, mình nhanh chóng check xem trong folder install ServiceDesk (SD) có file nào nhạy cảm hay account admin không. Tuy nhiên cuộc đời không dễ dàng như vậy. Cũng có một số file log nhưng không có gì có thể lợi dụng.

Lúc này thử nmap IP thì phát hiện hệ thống public port 1433 của MS SQL ra ngoài.

Khi mình install local thì mình dùng Postgresql theo mặc định nhưng đọc document của SD thì có thể đổi sang MS SQL thông qua changeDBServer.bat command trong folder bin.

Vì thế mình thử xem có thể lợi dụng MS SQL không.

2. TÌm lỗ hổng để vào được MS SQL

Theo mặc định, MS SQL Server khi được cài sẽ nằm ở C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA, và database của SD tên là servicedesk

Hí hửng download file này về nhưng không

Bị access denied vì không có quyền đọc?? Ta thấy nó ghi FileNotFound nhưng thực tế nó access denied, vì nếu là FileNotFound thì nó sẽ như sau

Bỏ qua chuyện đó, mình tìm được chức năng backup trong SD. Khi chạy backUpData.bat

Một file backup được tạo ra ở trong folder backup (có thể custom)

Tên của file sẽ được gắn thêm thời gian chạy backup. Mình cũng không cần bruteforce để biết tên nó vì tên của nó đã được lưu trong log tại C:\ManageEngine\ServiceDesk\bin\SDPbackup.log

Nhìn tên thì mình thấy khá yên tâm khi nó được backup hàng ngày (nhưng cũng không yên tâm lắm vì backup nằm ngay trên server 🙄).

Bây giờ thì chỉ cần đọc file đó. Nhưng một lần nữa số phận lại trêu ngươi. Mình có thể đọc trên con server local của mình, nhưng như các bạn thấy, folder backup của con SD cần tấn công lại nằm ở ổ D. Trước giờ chưa từng gặp trường hợp như này nên cũng chưa thử, nhưng đến bây giờ mình mới biết trong Windows mặc định khi các bạn path traversal từ ổ C thì không thể ra được ổ D.

Kết quả không bất ngờ

Bây giờ chúng ta chỉ có 1 lỗi LFI đọc được các file ở ổ C, chúng ta có thể làm gì với nó?

Mình trở lại với việc tìm lỗi trên SD. Mình phát hiện thêm một endpoint mới khá tiềm năng là /fosagent/repl/take-snapshot, servlet com.zoho.clustering.agent.filerepl.api.TakeSnapshotServlet. Chức năng của nó là snap shot lại ổ đĩa sau đó zip và lưu lại vào C:\ManageEngine\ServiceDesk\server\default\deploy\fosagent.war\snapshots

Nếu kết hợp với lỗi LFI kia thì hoàn toàn có thể đọc được toàn bộ data.

Mình định sử dụng lỗi này để tải về cả ổ đĩa nhưng sau khi chạy được 1 lúc thì server mình báo run out of disk space mặc dù trước đó mình để thừa gần 100GB.

Full disk

Tình hình layoff đang khá căng, giờ mà bị đuổi việc thì chết đói, do vậy mình cũng không dám chạy trên server target, sợ nó lại sập.

Đến đây thì mình cũng đã sức cùng lực kiệt, tìm đến giải pháp cuối cùng là cố gắng crack sa password của MS SQL Server. Password được lưu tại C:\Program Files\Microsoft SQL Server\110\Setup Bootstrap\Log\<time_of_something_random>\Datastore\ProductSettings_SqlEngine_Public.xml

Mình cũng không cần quan tâm cái chỗ folder kia là gì vì mình có thể đọc nó trong file C:\Program Files\Microsoft SQL Server\110\Setup Bootstrap\Log\Summary.txt

Đã có được password

Lúc này đi hỏi ChatGPT nhưng cũng không biết đây là thuật toán gì

Trong document của Microsoft cũng nói rằng cách mã hóa SA password không được công khai vì lí do bảo mật. Chẳng lẽ lại reverse SQL Server. Kiệt sức vì nó, mình quay đi làm việc khác.

Trong quá trình đó mình cũng có một công việc khác là audit con SupportCenter của ManageEngine. Nhận thấy code khá giống nhau, và trong khi debug thì có 1 tính năng mình có thể extract raw password của SQL Server, mình quyết định tìm hiểu sâu hơn. (Sau này nhận được tin sét đánh từ đồng nghiệp là SupportCenter là tên khác bản mới của ServiceDesk).

3. Lấy password của MS SQL Server

Như mình đã nhắc ở trên, SD cho phép người dùng thay đổi database server bằng cách chạy changeDBServer.bat, giao diện của nó như thế này đây

Sau một hồi mày mò, mình nhận thấy khi save config, bật lên trở lại và test connection thì nó thành công luôn, nghĩa là nó đã lưu password ở đâu đó??? Đáng lẽ mình phải nghĩ tới điều này sớm hơn.

Thử debug vào quá trình nó check connection, mình nhận ra điều đó là đúng, hơn nữa nó đã load được cả password clear text.

Hàm thực hiện load config là com.adventnet.servicedesk.tools.ChangeDBServer#getDBDetails.

Hàm này thực hiện đọc file config như sau

Như vậy với MS SQL Server, file config sẽ nằm trong C:\ManageEngine\ServiceDesk\server\default\deploy\mssql-ds.xml

Tuy nhiên trong file này không có thông tin đăng nhập

Tiếp tục debug, mình thấy nơi nó get username và password là hàm com.adventnet.servicedesk.tools.ChangeDBServer#getDBUserNameAndPassword

Như vậy file lưu user và pass là C:\ManageEngine\ServiceDesk\server\default\conf\login-config.xml

Ngon luôn, đã tìm được user và password, tuy nhiên đang ở bản encryption.

Phía trên có password cleartext, vì vậy chắc chắn có đoạn decrypt ở đâu đó, tiếp tục debug mình thấy hàm giải mã là org.jboss.resource.security.SecureIdentityLoginModule#decode

Sau đó password về dạng clear text

Mừng rơi nước mắt một lần nữa, mình thực hiện đọc file lấy password encrypt trên server.

Không cần biết cái thuật toán mã hóa kia là gì, mình chỉ cần thay cái mật khẩu đã mã hóa vào trong file config của mình, sau đó run debug lại, để tự server của mình giải mã cái password của server target, kết quả decrypt thành công

Thành công login tới con này từ remote, đoạn này rõ ràng đội vận hành đã không cấu hình kĩ càng.

4. Leo quyền Admin, thực hiện RCE

Khi đã chọc được DB, lên admin khá đơn giản, chỉ mất hơi nhiều thời gian mày mò xem user, quyền các thứ ở trong bảng nào để sửa. Tạo hẳn 1 nick mới, up lên quyền Admin, mình thành công trở thành admin của SD. Đoạn này không có gì quá technical nên mình xin được skip, cũng là một bài test kiên trì cho độc giả muốn thử làm.

Khi đã là Admin, ta có thể thực hiện RCE thông qua chức năng Custom Trigger.

ServiceDesk có 2 chức năng để RCE cho admin là Custom Trigger và Custom Schedule. Khác với Custom Schedule là tạo một command chạy theo thời gian định sẵn, Custom Trigger chạy khi có một ticket được tạo / sửa match với điều kiện. Vì vậy cứ mỗi lần phải tạo / sửa request mới có thể RCE -> thông báo được gửi tới người quản lý ticket.

Lời kết

Qua lần này, bên mình cũng đã có thêm nhiều bài học về việc làm sao để cấu hình hệ thống chuẩn hơn, luôn luôn cập nhật hệ thống lên bản mới nhất cũng như tăng cường khả năng giám sát.

Ké tuyển dụng: Chuyên gia nào đọc đến đây mà muốn tìm kiếm môi trường làm việc mới thì có thể gửi CV về hi@shfsec.com. Bên mình vẫn đang tuyển Senior / Expert Offensive và Defensive.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 302

- vừa được xem lúc

Học Spring Boot bắt đầu từ đâu?

1. Giới thiệu Spring Boot. 1.1.

0 0 278

- vừa được xem lúc

Cần chuẩn bị gì để bắt đầu học Java

Cần chuẩn bị những gì để bắt đầu lập trình Java. 1.1. Cài JDK hay JRE.

0 0 51

- vừa được xem lúc

Sử dụng ModelMapper trong Spring Boot

Bài hôm nay sẽ là cách sử dụng thư viện ModelMapper để mapping qua lại giữa các object trong Spring nhé. Trang chủ của ModelMapper đây http://modelmapper.org/, đọc rất dễ hiểu dành cho các bạn muốn tìm hiểu sâu hơn. 1.

0 0 194

- vừa được xem lúc

[Java] 1 vài tip nhỏ khi sử dụng String hoặc Collection part 1

. Hello các bạn, hôm nay mình sẽ chia sẻ về mẹo check String null hay full space một cách tiện lợi. Mình sẽ sử dụng thư viện Lớp StringUtils download file jar để import vào thư viện tại (link).

0 0 71

- vừa được xem lúc

Deep Learning với Java - Tại sao không?

Muốn tìm hiểu về Machine Learning / Deep Learning nhưng với background là Java thì sẽ như thế nào và bắt đầu từ đâu? Để tìm được câu trả lời, hãy đọc bài viết này - có thể kỹ năng Java vốn có sẽ giúp bạn có những chuyến phiêu lưu thú vị. DJL là tên viết tắt của Deep Java Library - một thư viện mã ng

0 0 139