Hidden within the latest Microsoft Security Advisory is a Whooper: ADV170012
https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/ADV170012
The summary is that some of the Infineon TPM chip implementations have a bug. And appears that someone has produced a Proof of Concept exploit. Wow.
Microsoft and Infineon have arguably done the right thing here and have announced the issue, produced a Hotfix to help customers better identify the issue, and have developed tools to update the issue through firmware.
What’s not clear to me is just what the issue is, and what the hotfix does. Unfortunately, it may be a while before Microsoft releases more information, while they give companies a head start working on application of the hotfixes.
A link in the article above suggest that exploit is not easy:
A successful attack depends on conditions beyond the attacker’s control. That is, a successful attack cannot be accomplished at will, but requires the attacker to invest in some measurable amount of effort in preparation or execution against the vulnerable component before a successful attack can be expected.
Which leads me to believe that any exploit is hard, requiring a highly skilled attacker, not someone who is going to steal my laptop from the local Starbucks in the hopes of getting my Credit Card number, saved somewhere on the machine.
Stay tuned…
Script
In the mean time, I decided to re-write the PowerShell script in the article above. The latest version works great when issuing commands remotely and collecting the data in a centralized location.
For example I could run the command:
icm { iwr 'https://gist.githubusercontent.com/keithga/22aa4500de40bc174f2f4921052e3b87/raw/Test-TPMReimann.ps1' | iex } -Cred $cred -Computer Pickett1,Pickett2,Pickett3,Pickett4 | ft *
And see the output:
Lucky for me I have Four machines that are affected with the Bad TPM Module.
- One machine is my work machine (Version 6.41)
- Two machines don’t have bad Infineon version numbers (Verison 3.19), but may need to be cleared anyways. Easy to do.
- One machine has the bad Infineon version (Version 4.32), but the TPM Module is on a replacement Riser card, and I can purchase a new one for $50.
Now to figure out how to address this at work.
Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Version 3 | |
#requires -RunAsAdministrator | |
<# | |
.SYNOPSIS | |
TPM Infineon Riemann Check | |
.DESCRIPTION | |
Checks the status of TPM on the local machine and returns status as a PowerShell object. | |
Must be run at elevated permissions. | |
.OUTPUTS | |
PSCustomObject with several properties. | |
.EXAMPLE | |
C:\PS> .\Test-TPMReimann.ps1 | |
hasTPM : True | |
ManufacturerId : 0x53544d20 | |
ManufacturerVersion : 13.12 | |
FirmwareVersionAtLastProvision : | |
NeedsRemediation : False | |
Reason : This non-Infineon TPM is not affected by the Riemann issue. 0x53544d20 | |
.EXAMPLE | |
C:\PS> icm -scriptblock { iwr 'https://gist.githubusercontent.com/keithga/22aa4500de40bc174f2f4921052e3b87/raw/Test-TPMReimann.ps1' | iex } -RunAsAdministrator -ComputerName PC1,PC2 | |
Given the URL path to this script ( to get the script, click on the raw link above ), will run the command on the machines and collect the results locally. | |
.LINK | |
https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/ADV170012 | |
.LINK | |
#> | |
[cmdletbinding()] | |
param() | |
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")){ | |
Throw "Not Administrator" | |
} | |
$TPM = try { Get-Tpm } catch { $Null } | |
$FirmwareVersionAtLastProvision = Get-ItemProperty –Path "HKLM:\SYSTEM\CurrentControlSet\Services\TPM\WMI" –Name "FirmwareVersionAtLastProvision" –ErrorAction SilentlyContinue | % FirmwareVersionAtLastProvision | |
#region Infineon version test routines | |
function Test-RiemannVersion ( [string[]] $version ) { | |
# Returns True if not safe | |
switch ( $version ) { | |
4 { return $version[1] -le 33 -or ($version[1] -ge 40 -and $version[1] -le 42) } | |
5 { return $version[1] -le 61 } | |
6 { return $version[1] -le 42 } | |
7 { return $version[1] -le 61 } | |
133 { return $version[1] -le 32 } | |
default { return $False } | |
} | |
} | |
#endregion | |
#region Test Logic | |
if ( !$TPM ) { | |
$Reason = "No TPM found on this system, so the Riemann issue does not apply here." | |
$NeedsRemediation = $False | |
} | |
elseif ( $TPM.ManufacturerId -ne 0x49465800 ) { | |
$Reason = "This non-Infineon TPM is not affected by the Riemann issue. 0x$([convert]::ToString($TPM.ManufacturerId,16))" | |
$NeedsRemediation = $False | |
} | |
elseif ( $TPM.ManufacturerVersion.IndexOf('.') -eq -1 ) { | |
$Reason = "Could not get TPM firmware version from this TPM. $($TPM.ManufacturerVersion)" | |
$NeedsRemediation = $False | |
} | |
elseif ( Test-RiemannVersion ( $Tpm.ManufacturerVersion -split '\.' ) ) { | |
$reason = "This Infineon firmware version TPM is not safe. $($Tpm.ManufacturerVersion)" | |
$NeedsRemediation = $true | |
} | |
elseif (!$FirmwareVersionAtLastProvision) { | |
$Reason = "We cannot determine what the firmware version was when the TPM was last cleared. Please clear your TPM now that the firmware is safe." | |
$NeedsRemediation = $true | |
} | |
elseif ($FirmwareVersion -ne $FirmwareVersionAtLastProvision) { | |
$Reason = "The firmware version when the TPM was last cleared was different from the current firmware version. Please clear your TPM now that the firmware is safe." | |
$NeedsRemediation = $true | |
} else { | |
$reason = 'OK' | |
$NeedsRemediation = $False | |
} | |
#endregion | |
#region Output Object | |
[PSCustomObject] @{ | |
# Basic TPM Information | |
hasTPM = $TPM -ne $null | |
ManufacturerId = "0x" + [convert]::ToString($TPM.ManufacturerId,16) | |
ManufacturerVersion = $Tpm.ManufacturerVersion | |
FWVersionAtLastProv = $FirmwareVersionAtLastProvision | |
# Does the machine need Remediation for Riemann issue? | |
NeedsRemediation = $NeedsRemediation | |
# Reason String | |
Reason = $Reason | |
} | |
#endregion | |
Notes
Don’t recall why I named it Reimann, I think I saw that as a code word in an article somewhere, and it stuck. Is the name of the researcher who found the issue, or just an arbitrary code name?
Not sure why you need to know when the last Provision Time was on machines *without* the issue. Either the TPM chips works or not!?!?