Wednesday, September 11, 2019

ThunderBolt Security Configuration Item for SCCM

This comes out of a need to secure ThunderBolt PCIe against DMA attacks while still allowing users (rather than just administrators) to approve attached devices.  This attack is very serious as it can done on a machine that is in sleep or hibernate.  As we know most laptop users never turn their computers off, they just close the lid.  The computer goes to sleep and everything it was doing gets stored in memory.  DMA = Direct Memory Access, so someone comes along, plugs in a malicious device and grabs everything stored in memory without even opening the lid of the computer.

Mitigation is two parts.  One part is BIOS configuration.  By default any modern ThunderBolt enabled computer will come with the BIOS set to require "User Approval" of any device that gets attached.  The problem is (in the operating system) that approval require that the user actually be an administrator not just any user.  That is not a usable solution in an enterprise environment.  It also requires that the device(s) be approved every single time they are used.  So, let's say you have a Thunderbolt dock... an administrator has to come and approve it every time you dock your laptop.  That's just not workable.

So, we configure that BIOS to a newer standard, Secure Connect.  That allows the device to only require approval the first time it is used.  Unfortunately that approval still needs to be an administrator.

Finally we are to the point of my post.  Here are two scripts to create a configuration item to detect existence of ThunderBolt and remediate the registry so that normal users can approve device connections.

A tech said to me "I don't see how this is any different than setting the BIOS to No Security".  Well, as I explained to him, you must understand how the DMA attack works in this instance.  The attack happens by simply attaching a malicious device (USB Key, SD Card, whatever) to the machine and the machine accepts its DMA request.  This can happen even while the machine is in Sleep mode (no user interface).  So, the difference between this and no security is that a user must actually be logged in and active to approve the connection.  I can't just walk up to your machine while you are at lunch, plug in a USB key, and take everything that your OS has in memory away with me.  I would have to have a valid login to approve the connection.  The attack is a way around drive encryption.  Having a valid logon is a way around drive encryption so this method makes your machine as secure as a machine that does not have ThunderBolt at all, meaning that nobody can run this particular DMA without a valid logon.  Once someone has a valid logon, you have other mitigation that you need to have in place but that's a story for another time.

The first script, detection:
This script will detect the existence of the ThunderBolt registry branch.  If it doesn't exist then your machine doesn't have ThunderBolt (or at least doesn't have drivers for it which amounts to the same thing, you are not vulnerable to the DMA attack) so it is compliant.  If your machine does have the branch then it checks the AccessRule item to ensure that it is set to 1.  By default this item will either not exist (IBM Lenovo) or be set to 0 (HP).

Create a new CI of type Script.  I named mine "Win10 Core - ThunderBolt PCIe Security" to add it to my Win10 Core baseline.
   The Setting Type is Script.
   The Data Type is String.
   Here is the Discovery Script:

#Created by Mark Randol - randoltech.blogspot.com
#This script detects existence of teh Thunderbolt Service registry branch
#and the setting of the "Approval Level" item within it
#Non-existence of the branch = compliant
#Non-existence ApprovalLevel within the branch = noncompliant
#ApprovalLevel 1 = compliant
#Any other value for ApprovalLevel = noncompliant
 
if (Test-Path -Path "HKLM:SYSTEM\CurrentControlSet\Services\ThunderboltService\TbtServiceSettings") {
$OutString = (Get-ItemProperty "HKLM:SYSTEM\CurrentControlSet\Services\ThunderboltService\TbtServiceSettings").ApprovalLevel
}
else {
$OutString = "1"
}
Write-Output $OutString
Return $OutString

Here is the Remediation Script:

# Change Thundebolt security approval level to allow users
# to accept Thundebolt equpiment without being local admin
# Originally created by Jens-Kristian Myklebust <jensmyklebust@outlook.com>
# Modified to work as an SCCM CI by Mark Randol - randoltech.blogspot.com

$logfile = "$env:windir\ccm\logs\Install_Fix-ThunderboltRegistry.log"
Start-Transcript -Path $logfile -force #start logging

$RegistryKey = "SYSTEM\CurrentControlSet\Services\ThunderboltService\TbtServiceSettings" #Registry key to modify
$RegistryPath = "HKLM:\$RegistryKey" #Full path to the registry key
$ServiceName = "AdobeARMservice" #"ThunderboltService"

#Set the registry Value
if ((Test-Path -Path $RegistryPath)){ #make sure we're on a machine that actually has the key
       
    $TheService = Get-Service -Name $ServiceName
    #Stop the Thunderbolt Service
    if (($TheService)) {
        $TheService | Stop-Service -Confirm:$false -Verbose
        $TheService.WaitForStatus('Stopped')
    }

    $ACLinfo = Get-Acl "HKLM:\$RegistryKey" #Store original ACL info

    #Give "SYSTEM" user full access to registry key
        $RegKeyDotNETItem = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($RegistryKey,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions)
        $DotNET_ACL = $RegKeyDotNETItem.GetAccessControl()
        $DotNET_AccessRule = New-Object System.Security.AccessControl.RegistryAccessRule ("System","FullControl","Allow") -Verbose
        $DotNET_ACL.SetAccessRule($DotNET_AccessRule)
        $DotNET_AccessRule = New-Object System.Security.AccessControl.RegistryAccessRule ($env:USERNAME,"FullControl","Allow") -Verbose
        $DotNET_ACL.SetAccessRule($DotNET_AccessRule)
        $RegKeyDotNETItem.SetAccessControl($DotNET_ACL)

    #check for existence of the property in the key
    #if the property doesn't exist, create it
    if (!((Get-ItemProperty $RegistryPath).ApprovalLevel)){
        New-ItemProperty -Path $RegistryPath -Name 'ApprovalLevel' -Value 1 -PropertyType DWORD -Force -Verbose
    }
    #if the property does exist, change it to the correct value
    else {
        Set-ItemProperty -Path $RegistryPath -Name 'ApprovalLevel' -Value 1 -Verbose
    }

    #Put the security back on the registry
    $RegKeyDotNETItem.SetAccessControl($ACLinfo)

    #Restart service
    if (($TheService)) {
        $TheService | Start-Service -Confirm:$false -Verbose
        $TheService.WaitForStatus('Running')
    }
#>
}
Stop-Transcript #stop logging

Create a compliance rule, I named mine "ApprovalLevel" as that is the registry item that we are dealing with.  Here are the settings for it:
Value = 1
Check the checkbox "Run the specified remediation script when this setting is noncompliant"
Check the checkbox "Report noncompliance if the setting instance is not found"

From there, add your new CI to a baseline, deploy the baseline at your (suspected) Thunderbolt enabled machines and it should set the setting for you.

With BIOS set to SecureConnect and this registry entry your users should be able to approve devices to connect to their computer and will only need to do it the first time similar to pairing a Bluetooth device.

- Enjoy