1

I have two different Watchguard XTM 515 firewalls. Each has it's own set of VPNs created in them.

Now I need to use only one firewall to handle the VPNs of both. But the problem is that I don't know the PSK of VPNs (I inherited those firewall after joining my job). Asking the customers to change PSK is not an option for me.

Now I do know that when I export the configuration (XML file) of firewall, it includes the PSKs of all VPNs. That's the reason restoring that configuration to another firewall works. But I don't know how to get hold of those PSKs. I check the configuration XML files with plain text editor and seems like they are encrypted (no surprise here). But they must be encrypted using a static key since this configuration can be uploaded to any firewall. It's just that I don't know the decryption scheme and key.

Now my objective is certainly not to break the encryption of Watchguard XML configuration files. All I need to do is merge two firewalls into one. I thought about manually merging the sections of XML configuration files exported from both firewalls, but it seems like a daunting task.

Please can you help suggesting a method to merge VPNs of two different Watchguard firewalls into one?

Hemant
  • 229
  • 1
  • 3
  • 12

3 Answers3

2

You're right, they are encrypted with a static key, and the scheme is AES Key Wrap Algorithm (RFC 3394). And you can decrypt them.

I took this public domain C# library, stripped it right down to just the decrypt functions and ported it to PowerShell, so it would fit in a StackOverflow answer and not need compiling or binaries.

It's not pretty, has no error checking or anything, but it seems to work:

<#
.Synopsis
   Decrypts a Watchguard encrypted BOVPN pre-shared-key
.EXAMPLE
   Decrypt-WatchguardPsk -EncryptedPsk '0E611DC31F2AEBB4A6E69F2641E1E83D762F514F3636E1EFA86B9BDECFEFADFB'
#>
function Decrypt-WatchguardPsk
{
    [CmdletBinding()]
    [Alias()]
    [OutputType([int])]
    Param([Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)]$EncryptedPsk)

    Process
    {
        function Group-ByCount ($ByteArray, $n) { #BigArray -> Arrays of n items
            $NumGroups=$ByteArray.Count/$n
            $Output= @()
            0..($NumGroups-1) | ForEach-Object { $Output += @(, [byte[]]$ByteArray[($_*$n)..(($_*$n)+$n-1)]) }
            $Output
        }

        $KeyEncryptionKey = [byte[]] @(29, 3, 245, 130, 135, 152, 43, 199, 1, 34, 115, 148, 228, 152, 222, 35)
        $EncryptedPsk = $EncryptedPsk -replace '\s|(</*psk>)|\+' # trim xml line. Here so you can do: sls '<psk>' *.xml | % Line | Decrypt-WatchguardPsk
        [byte[]] $Arrby = $EncryptedPsk -split "(?<=\G\w{2})(?=\w{2})" |% { [Convert]::ToByte($_, 16) } #HexTo[byte[]]
        $C = Group-ByCount $Arrby 8  #Byte array to groups of 8 bytes (AES blocks)

        # 1) AES Key Wrap - Initialize variables
        $A = $C[0]
        $R = @($C[1..($C.Count-1)])
        $Blockn = $R.Count

        # 2) Calculate intermediate values
        for ($j = 5; $j -ge 0; $j--) {
            for ($i = $Blockn - 1; $i -ge 0; $i--) {
                $t = $Blockn * $j + $i + 1  # add 1 because i is zero-based

                #64 bit XOR
                $A2 = $A.Clone()
                [Array]::Reverse($A2)
                $A2 = [BitConverter]::GetBytes([BitConverter]::ToInt64($A2, 0) -bxor $t)
                [Array]::Reverse($A2)
                $A = $A2

                # Decrypt block
                $Alg = New-Object -type System.Security.Cryptography.RijndaelManaged
                $Alg.Padding = [System.Security.Cryptography.PaddingMode]::None
                $Alg.Mode = [System.Security.Cryptography.CipherMode]::ECB
                $Alg.Key = $KeyEncryptionKey

                $ms = New-Object System.IO.MemoryStream
                $xf = $Alg.CreateDecryptor()
                $cs = New-Object System.Security.Cryptography.CryptoStream -ArgumentList @($ms, $xf, [System.Security.Cryptography.CryptoStreamMode]::Write)

                $AConcatRi = $A + $R[$i] + (New-Object 'byte[]' (16 - $A.Count - $R[$i].Count))

                $cs.Write($AConcatRi, 0, $Alg.BlockSize / 8)

                $B = Group-ByCount $ms.ToArray() 8
                $A         = $B[0] #MSB(B)
                $R[$i]     = $B[1] #LSB(B) 64 least significant bits of a 128
            }
        }

        -join ($R | % { [System.Text.Encoding]::ASCII.GetString($_) })
    }
}

e.g.

PS C:\> Decrypt-WatchguardPsk -EncryptedPsk '8B4B449A6D4253232C4CFC48E311B7B9DF360D5F4EAB310CAD9D7B92B4CD3CA6340841671FA9187E6AB5F4604D5E2B9319EC890A826B96EF47163B83F2294289109F8336441879416A230C26E0AEEBDC332798F54F482250'
Testing with dummy text lorem ipsum dolor sit amet, consectetur adipiscing elit

I don't think posting this is a security problem - any attacker who can get the firewall config file is already past the security, on the firewall or on a management workstation. The config contains no device management login credentials. And there isn't much else they could do to encrypt things in a config file without trading off a lot of other concerns instead. It's really a pragmatic layer to stop passwords showing up in plain text searches and indexes.

TessellatingHeckler
  • 5,676
  • 3
  • 25
  • 44
  • Thanks for the answer which is useful in future. I ended up using another method. See below. :) – Hemant Apr 04 '17 at 09:54
2

Apart from the answer posted by @TessellatingHeckler, there is another non-technical way to transfer a VPN from one watch guard to another. I ended up using this method and it worked like a charm.

  • Export the configuration from old firewall. Keep the file safe. Lets call it old.xml.
  • Make the VPN with same configuration on new firewall. Obviously you don't know the PSK, so type anything in the box.
  • Export the configuration from new firewall. Lets call it new.xml.
  • Copy the encrypted PSK string of VPN that you are trying to migrate from old.xml. Overwrite the PSK string of VPN in new.xml.
  • Apply the new.xml back to new firewall.

The idea is that we are not interested in what the value of PSK is. We just want to migrate it. So why not just migrate the encrypted value? Since the encryption is same in every firebox, we can just migrate the encrypted PSK.

Hemant
  • 229
  • 1
  • 3
  • 12
0

Reset the passphrase on the gateways on both ends at the same time, and record the new passphrase. Apply that new passphrase to the new config and save to the firebox.