Tuesday, November 22, 2016

On the Effectiveness of Device Guard User Mode Code Integrity

Is a security feature with known bypasses pointless?

I felt compelled to answer to this question after seeing several tweets recently claiming that Device Guard User Mode Code Integrity (UMCI) is a pointless security mechanism considering all of the recently reported bypasses. Before specifically diving into UMCI and its merits (or lack thereof), let’s use an analogy in the physical world to put things into perspective - a door.

Consider the door at the front of your home or business. This door helps serve as the primary mechanism to prevent intruders from breaking, entering, and stealing your assets. Let's say it's a solid wood door for the sake of the analogy. How might an attacker go about bypassing it?

  • They could pick the lock
  • They could compromise the latch with a shimming device
  • They could chop the door down with an ax
  • They could compromise the door and the hinges with a battering ram

Now, there are certainly better doors out there. You could purchase a blast door and have it be monitored with a 24/7 armed guard. Is that measure realistic? Maybe. It depends on the value of the assets you want to protect. Realistically, it's probably not worth your money since you suspect that a full frontal assault of enemy tanks is not a part of your threat model.

Does a determined attacker ultimately view the door as a means of preventing them from gaining access to your valuable assets? Of course not. Does the attacker even need to bypass the door? Probably not. They could also:

  • Go through the window
  • Break through a wall
  • Hide in the store during business hours and wait for everyone to leave
  • Submit their resume, get a job, develop trust, and slowly, surreptitiously steal your assets

So, will a door prevent breaches in all cases? Absolutely not. Will it prevent or deter an attacker lacking a certain amount of skill from breaking and entering? Sure. Other than preventing the elements from entering your store, does the locked door serve a purpose? Of course. It is a preventative mechanism suitable for the threat model that you choose to accept or mitigate against. The door is a baseline preventative mechanism employed in conjunction with a layered defense consisting of other preventative (reinforced, locked windows) and detective (motion sensors, video cameras, etc.) measures.




Now let's get back to the comfortable world of computers. Is a preventative security technology completely pointless if there are known bypasses? Specifically, let’s focus on Device Guard user mode code integrity (UMCI) as it’s received a fair amount of attention as of late. Considering all of the public bypasses posted, does it still serve a purpose? I won't answer that question using absolutes. Let me make a few proposals and let you, the reader decide. Consider the following:

1) A bypass that applies to Device Guard UMCI is extremely likely to apply to all application whitelisting solutions. I would argue that Device Guard UMCI goes above and beyond other offerings. For example, UMCI places PowerShell (one of the largest user-mode attack surfaces) into constrained language mode, preventing PowerShell from being used to execute arbitrary, unsigned code. Other whitelisting solutions don’t even consider the attack surface posed by PowerShell. Device Guard UMCI also applies code integrity rules to DLLs. There is no way around this. Other solutions allow for DLL whitelisting but not by default.

2) Device Guard UMCI, as with any whitelisting solution, is extremely effective against post-exploitation activities that are not aware of UMCI bypasses. The sheer amount of attacks that app-whitelisting prevents without any fancy machine learning is astonishing. I can say first hand that every piece of “APT” malware I reversed in a previous gig would almost always drop an unsigned binary to disk. Even in the cases where PowerShell was used, .NET methods were used heavily - something that constrained language mode would have outright prevented.

3) The majority of the "misplaced trust" binaries (e.g. MSBuild.exe, cdb.exe, dnx.exe, rcsi.exe, etc.) can be blocked with Device Guard code integrity policy updates. Will there be more bypass binaries? Of course. Again, these binaries will also likely circumvent all app-whitelisting solutions as well. Does it require an active effort to stay on top of all the bypasses as a defender? Yes. Deal with it.

Now, I along with awesome people like Casey Smith (@subtee) and Matt Nelson (@enigma0x3) have reported our share of UMCI bypasses to Microsoft for which there is no code integrity policy mitigation. We have been in the trenches and have seen first hand just how bad some of the bypasses are. We are desperately holding out hope that Microsoft will come through, issue CVEs, and apply fixes for all of the issues we’ve reported. If they do, that will set a precedent and serve as proof that they are taking UMCI seriously. If not, I will start to empathize a bit more with those who claim that Device Guard is pointless. After all, we’re starting to see more attackers “live off the land” and leverage built-in tools to host their malware. Vendors need to be taking that seriously.

Ultimately, Device Guard UMCI is just another security feature that a defender should consider from a cost/benefit analysis based on threats faced and the assets they need to defend. It will always be vulnerable to bypasses, but raises the baseline bar of security. Going back to the analogy above, a door can always be bypassed but you should be able to detect an attacker breaking in and laying their hands on your valuable assets. So obviously, you would want to use additional security solutions along with Device Guard - e.g. Windows Event Forwarding, an anti-malware solution, and to perform periodic compromise/hunt assessments.

What I’m about to say might be scandalous but I sincerely think that application whitelisting should the new norm. You probably won’t encounter any organizations that don’t employ an anti-malware solution despite the innumerable bypasses. These days, anti-malware solutions are assumed to be a security baseline as I think whitelisting should be despite the innumerable bypasses that will surface over time. Personally, I would ask any defender to seriously consider it and I would encourage all defenders to hold whitelisting solution vendors' feet to the fire and hold them accountable when there are bypasses for which there is no obvious mitigation.


I look forward to your comments here or in a lively debate on Twitter!

Monday, November 21, 2016

Device Guard Code Integrity Policy Auditing Methodology

In my previous blogpost, I provided a detailed reference of every component of a code integrity (CI) policy. In this post, I'd like to exercise that reference and perform an audit of a code integrity policy. We're going to analyze a policy that I had previously deployed to my Surface Pro 4 - final.xml.

<?xml version="1.0" encoding="utf-8"?>
<SiPolicy xmlns="urn:schemas-microsoft-com:sipolicy">
  <VersionEx>10.0.0.0</VersionEx>
  <PolicyTypeID>{A244370E-44C9-4C06-B551-F6016E563076}</PolicyTypeID>
  <PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID>
  <Rules>
    <Rule>
      <Option>Required:Enforce Store Applications</Option>
    </Rule>
    <Rule>
      <Option>Enabled:UMCI</Option>
    </Rule>
    <Rule>
      <Option>Disabled:Flight Signing</Option>
    </Rule>
    <Rule>
      <Option>Required:WHQL</Option>
    </Rule>
    <Rule>
      <Option>Enabled:Unsigned System Integrity Policy</Option>
    </Rule>
    <Rule>
      <Option>Enabled:Advanced Boot Options Menu</Option>
    </Rule>
  </Rules>
  <!--EKUS-->
  <EKUs />
  <!--File Rules-->
  <FileRules>
    <FileAttrib ID="ID_FILEATTRIB_F_1_0_0_1_0_0" FriendlyName="cdb.exe" FileName="CDB.Exe" MinimumFileVersion="99.0.0.0" />
    <FileAttrib ID="ID_FILEATTRIB_F_2_0_0_1_0_0" FriendlyName="kd.exe" FileName="kd.exe" MinimumFileVersion="99.0.0.0" />
    <FileAttrib ID="ID_FILEATTRIB_F_3_0_0_1_0_0" FriendlyName="windbg.exe" FileName="windbg.exe" MinimumFileVersion="99.0.0.0" />
    <FileAttrib ID="ID_FILEATTRIB_F_4_0_0_1_0_0" FriendlyName="MSBuild.exe" FileName="MSBuild.exe" MinimumFileVersion="99.0.0.0" />
    <FileAttrib ID="ID_FILEATTRIB_F_5_0_0_1_0_0" FriendlyName="csi.exe" FileName="csi.exe" MinimumFileVersion="99.0.0.0" />
  </FileRules>
  <!--Signers-->
  <Signers>
    <Signer ID="ID_SIGNER_S_1_0_0_0_0_0_0_0" Name="Microsoft Windows Production PCA 2011">
      <CertRoot Type="TBS" Value="4E80BE107C860DE896384B3EFF50504DC2D76AC7151DF3102A4450637A032146" />
    </Signer>
    <Signer ID="ID_SIGNER_S_AE_0_0_0_0_0_0_0" Name="Intel External Basic Policy CA">
      <CertRoot Type="TBS" Value="53B052BA209C525233293274854B264BC0F68B73" />
    </Signer>
    <Signer ID="ID_SIGNER_S_AF_0_0_0_0_0_0_0" Name="Microsoft Windows Third Party Component CA 2012">
      <CertRoot Type="TBS" Value="CEC1AFD0E310C55C1DCC601AB8E172917706AA32FB5EAF826813547FDF02DD46" />
    </Signer>
    <Signer ID="ID_SIGNER_S_17C_0_0_0_0_0_0_0" Name="COMODO RSA Certification Authority">
      <CertRoot Type="TBS" Value="7CE102D63C57CB48F80A65D1A5E9B350A7A618482AA5A36775323CA933DDFCB00DEF83796A6340DEC5EBF7596CFD8E5D" />
    </Signer>
    <Signer ID="ID_SIGNER_S_18D_0_0_0_0_0_0_0" Name="Microsoft Code Signing PCA 2010">
      <CertRoot Type="TBS" Value="121AF4B922A74247EA49DF50DE37609CC1451A1FE06B2CB7E1E079B492BD8195" />
    </Signer>
    <Signer ID="ID_SIGNER_S_2E0_0_0_0_0_0_0_0" Name="VeriSign Class 3 Code Signing 2010 CA">
      <CertRoot Type="TBS" Value="4843A82ED3B1F2BFBEE9671960E1940C942F688D" />
    </Signer>
    <Signer ID="ID_SIGNER_S_34C_0_0_0_0_0_0_0" Name="Microsoft Code Signing PCA">
      <CertRoot Type="TBS" Value="27543A3F7612DE2261C7228321722402F63A07DE" />
    </Signer>
    <Signer ID="ID_SIGNER_S_34F_0_0_0_0_0_0_0" Name="Microsoft Code Signing PCA 2011">
      <CertRoot Type="TBS" Value="F6F717A43AD9ABDDC8CEFDDE1C505462535E7D1307E630F9544A2D14FE8BF26E" />
    </Signer>
    <Signer ID="ID_SIGNER_S_37B_0_0_0_0_0_0_0" Name="Microsoft Root Certificate Authority">
      <CertRoot Type="TBS" Value="391BE92883D52509155BFEAE27B9BD340170B76B" />
    </Signer>
    <Signer ID="ID_SIGNER_S_485_0_0_0_0_0_0_0" Name="Microsoft Windows Verification PCA">
      <CertRoot Type="TBS" Value="265E5C02BDC19AA5394C2C3041FC2BD59774F918" />
    </Signer>
    <Signer ID="ID_SIGNER_S_1_1_0_0_0_0_0_0" Name="Microsoft Windows Production PCA 2011">
      <CertRoot Type="TBS" Value="4E80BE107C860DE896384B3EFF50504DC2D76AC7151DF3102A4450637A032146" />
    </Signer>
    <Signer ID="ID_SIGNER_S_35C_1_0_0_0_0_0_0" Name="Microsoft Code Signing PCA">
      <CertRoot Type="TBS" Value="27543A3F7612DE2261C7228321722402F63A07DE" />
    </Signer>
    <Signer ID="ID_SIGNER_S_35F_1_0_0_0_0_0_0" Name="Microsoft Code Signing PCA 2011">
      <CertRoot Type="TBS" Value="F6F717A43AD9ABDDC8CEFDDE1C505462535E7D1307E630F9544A2D14FE8BF26E" />
    </Signer>
    <Signer ID="ID_SIGNER_S_1EA5_1_0_0_0_0_0_0" Name="Microsoft Code Signing PCA 2010">
      <CertRoot Type="TBS" Value="121AF4B922A74247EA49DF50DE37609CC1451A1FE06B2CB7E1E079B492BD8195" />
    </Signer>
    <Signer ID="ID_SIGNER_S_2316_1_0_0_0_0_0_0" Name="Microsoft Windows Verification PCA">
      <CertRoot Type="TBS" Value="265E5C02BDC19AA5394C2C3041FC2BD59774F918" />
    </Signer>
    <Signer ID="ID_SIGNER_S_3D8C_1_0_0_0_0_0_0" Name="Microsoft Code Signing PCA">
      <CertRoot Type="TBS" Value="7251ADC0F732CF409EE462E335BB99544F2DD40F" />
    </Signer>
    <Signer ID="ID_SIGNER_S_4_1_0_0_0" Name="Matthew Graeber">
      <CertRoot Type="TBS" Value="B1554C5EEF15063880BB76B347F2215CDB5BBEFA1A0EBD8D8F216B6B93E8906A" />
    </Signer>
    <Signer ID="ID_SIGNER_S_1_1_0" Name="Intel External Basic Policy CA">
      <CertRoot Type="TBS" Value="53B052BA209C525233293274854B264BC0F68B73" />
      <CertPublisher Value="Intel(R) Intel_ICG" />
    </Signer>
    <Signer ID="ID_SIGNER_S_2_1_0" Name="Microsoft Windows Third Party Component CA 2012">
      <CertRoot Type="TBS" Value="CEC1AFD0E310C55C1DCC601AB8E172917706AA32FB5EAF826813547FDF02DD46" />
      <CertPublisher Value="Microsoft Windows Hardware Compatibility Publisher" />
    </Signer>
    <Signer ID="ID_SIGNER_S_19_1_0" Name="Intel External Basic Policy CA">
      <CertRoot Type="TBS" Value="53B052BA209C525233293274854B264BC0F68B73" />
      <CertPublisher Value="Intel(R) pGFX" />
    </Signer>
    <Signer ID="ID_SIGNER_S_20_1_0" Name="iKGF_AZSKGFDCS">
      <CertRoot Type="TBS" Value="32656594870EFFE75251652A99B906EDB92D6BB0" />
      <CertPublisher Value="IntelVPGSigning2016" />
    </Signer>
    <Signer ID="ID_SIGNER_S_4E_1_0" Name="Microsoft Windows Third Party Component CA 2012">
      <CertRoot Type="TBS" Value="CEC1AFD0E310C55C1DCC601AB8E172917706AA32FB5EAF826813547FDF02DD46" />
    </Signer>
    <Signer ID="ID_SIGNER_S_65_1_0" Name="VeriSign Class 3 Code Signing 2010 CA">
      <CertRoot Type="TBS" Value="4843A82ED3B1F2BFBEE9671960E1940C942F688D" />
      <CertPublisher Value="Logitech" />
    </Signer>
    <Signer ID="ID_SIGNER_S_5_1_0_0_0" Name="Matthew Graeber">
      <CertRoot Type="TBS" Value="B1554C5EEF15063880BB76B347F2215CDB5BBEFA1A0EBD8D8F216B6B93E8906A" />
    </Signer>
    <Signer ID="ID_SIGNER_F_1_0_0_1_0_0" Name="Microsoft Code Signing PCA">
      <CertRoot Type="TBS" Value="27543A3F7612DE2261C7228321722402F63A07DE" />
      <CertPublisher Value="Microsoft Corporation" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_1_0_0_1_0_0" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_2_0_0_1_0_0" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_3_0_0_1_0_0" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_4_0_0_1_0_0" />
    </Signer>
    <Signer ID="ID_SIGNER_F_2_0_0_1_0_0" Name="Microsoft Code Signing PCA 2010">
      <CertRoot Type="TBS" Value="121AF4B922A74247EA49DF50DE37609CC1451A1FE06B2CB7E1E079B492BD8195" />
      <CertPublisher Value="Microsoft Corporation" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_1_0_0_1_0_0" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_2_0_0_1_0_0" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_3_0_0_1_0_0" />
    </Signer>
    <Signer ID="ID_SIGNER_F_3_0_0_1_0_0" Name="Microsoft Code Signing PCA 2011">
      <CertRoot Type="TBS" Value="F6F717A43AD9ABDDC8CEFDDE1C505462535E7D1307E630F9544A2D14FE8BF26E" />
      <CertPublisher Value="Microsoft Corporation" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_4_0_0_1_0_0" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_5_0_0_1_0_0" />
    </Signer>
    <Signer ID="ID_SIGNER_F_4_0_0_1_0_0" Name="Microsoft Windows Production PCA 2011">
      <CertRoot Type="TBS" Value="4E80BE107C860DE896384B3EFF50504DC2D76AC7151DF3102A4450637A032146" />
      <CertPublisher Value="Microsoft Windows" />
      <FileAttribRef RuleID="ID_FILEATTRIB_F_4_0_0_1_0_0" />
    </Signer>
  </Signers>
  <!--Driver Signing Scenarios-->
  <SigningScenarios>
    <SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName="Kernel-mode rules">
      <ProductSigners>
        <AllowedSigners>
          <AllowedSigner SignerId="ID_SIGNER_S_1_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_AE_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_AF_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_17C_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_18D_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_2E0_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_34C_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_34F_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_37B_0_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_485_0_0_0_0_0_0_0" />
        </AllowedSigners>
      </ProductSigners>
    </SigningScenario>
    <SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="User-mode rules">
      <ProductSigners>
        <AllowedSigners>
          <AllowedSigner SignerId="ID_SIGNER_S_1_1_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_1_1_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_2_1_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_4_1_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_19_1_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_20_1_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_4E_1_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_65_1_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_35C_1_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_35F_1_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_1EA5_1_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_2316_1_0_0_0_0_0_0" />
          <AllowedSigner SignerId="ID_SIGNER_S_3D8C_1_0_0_0_0_0_0" />
        </AllowedSigners>
        <DeniedSigners>
          <DeniedSigner SignerId="ID_SIGNER_F_1_0_0_1_0_0" />
          <DeniedSigner SignerId="ID_SIGNER_F_2_0_0_1_0_0" />
          <DeniedSigner SignerId="ID_SIGNER_F_3_0_0_1_0_0" />
          <DeniedSigner SignerId="ID_SIGNER_F_4_0_0_1_0_0" />
        </DeniedSigners>
      </ProductSigners>
    </SigningScenario>
  </SigningScenarios>
  <UpdatePolicySigners>
    <UpdatePolicySigner SignerId="ID_SIGNER_S_5_1_0_0_0" />
  </UpdatePolicySigners>
  <CiSigners>
    <CiSigner SignerId="ID_SIGNER_F_1_0_0_1_0_0" />
    <CiSigner SignerId="ID_SIGNER_F_2_0_0_1_0_0" />
    <CiSigner SignerId="ID_SIGNER_F_3_0_0_1_0_0" />
    <CiSigner SignerId="ID_SIGNER_F_4_0_0_1_0_0" />
    <CiSigner SignerId="ID_SIGNER_S_1_1_0" />
    <CiSigner SignerId="ID_SIGNER_S_1_1_0_0_0_0_0_0" />
    <CiSigner SignerId="ID_SIGNER_S_2_1_0" />
    <CiSigner SignerId="ID_SIGNER_S_4_1_0_0_0" />
    <CiSigner SignerId="ID_SIGNER_S_19_1_0" />
    <CiSigner SignerId="ID_SIGNER_S_20_1_0" />
    <CiSigner SignerId="ID_SIGNER_S_4E_1_0" />
    <CiSigner SignerId="ID_SIGNER_S_65_1_0" />
    <CiSigner SignerId="ID_SIGNER_S_35C_1_0_0_0_0_0_0" />
    <CiSigner SignerId="ID_SIGNER_S_35F_1_0_0_0_0_0_0" />
    <CiSigner SignerId="ID_SIGNER_S_1EA5_1_0_0_0_0_0_0" />
    <CiSigner SignerId="ID_SIGNER_S_2316_1_0_0_0_0_0_0" />
    <CiSigner SignerId="ID_SIGNER_S_3D8C_1_0_0_0_0_0_0" />
  </CiSigners>
  <HvciOptions>1</HvciOptions>
</SiPolicy>

A code integrity policy is only as good as the way in which it was configured. The only way to verify its effectiveness is with a thorough understanding of the policy schema and the intended deployment scenario of the policy all through the lens of an attacker. The analysis that I present, while subjective, will be thorough and well thought out based on the information I've learned about code integrity policy enforcement. The extent of my knowledge is driven by my experience with Device Guard thus far, Microsoft's public documentation, the talks I've had with the Device Guard team, and what I've reversed engineered.

Hopefully, you'll have the luxury of being able to analyze an orignal CI policy containing all comments and attributes. In some situations, you may not be so lucky and may be forced to obtain an XML policy from a deployed binary policy - SIPolicy.p7b. Comments and some attribtues are stripped from binary policies. CI policy XML can be recovered with ConvertTo-CiPolicy.

Alright. Let's dive into the analysis now. When I audit a code integrity policy, I will start in the following order:
  1. Policy rule analysis
  2. SigningScenario analysis. Signing scenario rules are ultimately generated based on a combination of one or more file rule levels.
  3. UpdatePolicySigner analysis
  4. HvciOptions analysis

Policy Rule Analysis
Policy rules dictate the overall configuration of Device Guard. What will follow is a description of each rule and its implications.

1) Required:Enforce Store Applications

Description: The presence of this setting indicates that code integrity will also be applied to Windows Store/UWP apps.

Implications: It is unlikely that the absence of this rule would lead to a code integrity bypass scenario but in the off-chance an attacker attempted to deploy an unsigned UWP application, Device Guard would prevent it from loading. The actual implementation of this rule is unclear to me and warrants research. For example, if you launch modern calc (Calculator.exe), it is not actually signed. There’s obviously some other layer of enforcement occurring that I don’t currently comprehend.

Note: This rule option is not actually officially documented but it is accessible the Set-RuleOption cmdlet.

2) Enabled:UMCI

Description: The presence of this setting indicates that user mode code integrity is to be enforced. This means that all user-mode code (exe, dll, msi, js, vbs, PowerShell) is subject to enforcement. Compiled binaries (e.g. exe, dll, msi) not conformant to policy will outright fail to load. WSH scripts (JS and VBScript) not conformant to policy will be prevented from instantiating COM objects, and PowerShell scripts/modules not conformant to policy will be placed into Constrained Language mode. The absence of this rule implies that the code integrity policy will only apply to drivers.

Implications: Attackers will need to come armed with UMCI bpasses to circumvent this protection. Myself, along with Casey Smith (@subtee) and Matt Nelson (@enigma0x3) have been doing a lot of research lately in developing UMCI bypasses. To date, we’ve discussed some of these bypasses publicly. As of this writing, we also have several open cases with MSRC addressing many more UMCI issues. Our research has focused on discovering trusted binaries that allow us to execute unsigned code, Device Guard implementation flaws, and PowerShell Constrained Language mode bypasses. We hope to see fixes implemented for all the issues we reported.

Attackers seeking to circumvent Device Guard should be aware of UMCI bypasses as this is often the easiest way to circumvent a Device Guard deployment.

3) Required:WHQL

Description: All drivers must be WHQL signed as indicated by a "Windows Hardware Driver Verification" EKU (1.3.6.1.4.1.311.10.3.5) in their certificate.

Implications: This setting raises the bar for trust and integrity of the drivers that are allowed to load.

4) Disabled:Flight Signing

Description: Flight signed code will be prevented from loading. This should only affect the loading of Windows Insider Preview code.

Implications: It is recommended that this setting be enabled. This will preclude you from running Insider Preview builds, however. Flight signed code does not go through the rigorous testing that code for a general availability release would go through (I say so speculatively).

5) Enabled:Unsigned System Integrity Policy

Description: This setting indicates that Device Guard does not require that the code integrity policy be signed. Code Integrity policy signing is a very effective mitigation against CI policy tampering as it makes it so that only code signing certificates included in the UpdatePolicySigners section are authorized to make CI policy changes.

Implications: An attacker would need to steal one of the approved code signing certificates to make changes therefore, it is critical that that these code signing certificates be well protected. It should go without saying that the certificate used to sign a policy not be present on a system where the code integrity policy is deployed. More generally, no code signing certificates should be present on any Device Guard protected system that are whitelisted per policy.

6) Enabled:Advanced Boot Options Menu

Description: By default, with a code integrity policy deployed, the advanced boot options menu is disabled. The presence of this rule indicates that a user with physical access can access the menu.

Implications: An attacker with physical access will have the ability to remove deployed code integrity policies. If this is a realistic threat for you, then it is critical that BitLocker be deployed and a UEFI password be set. Additionally, since the “Enabled:Unsigned System Integrity Policy” option is set, an attacker could simply replace the existing, deployed code integrity policy with that of their own which permits their their code to execute.

Analysis/recommendations: Policy Rules


After thorough testing had been performed, it would be recommended to
  1. Remove "Enabled:Unsigned System Integrity Policy" and to sign the policy. This is an extremely effective way to prevent policy tampering.
  2. Remove "Enabled:Advanced Boot Options Menu". This is an effective mitigation against certain physical attacks.
  3. If possible, enable "Required:EV Signers". This is likely not possible however since it is likely that all required drivers will not be EV signed.

SigningScenario analysis

At this point, we’re interested in identifying what is whitelisted and what is blacklisted. The most efficient place to start is by analyzing the SigningScenarios section and working our way backwards.

There will only ever be at most two SigningScenarios:

  • ID_SIGNINGSCENARIO_DRIVERS_1 - these rules only apply to drivers
  • ID_SIGNINGSCENARIO_WINDOWS - these rules only apply to user mode code

ID_SIGNINGSCENARIO_DRIVERS_1


The following driver signers are whitelisted:

- ID_SIGNER_S_1_0_0_0_0_0_0_0
  Name: Microsoft Windows Production PCA 2011
  TBS: 4E80BE107C860DE896384B3EFF50504DC2D76AC7151DF3102A4450637A032146
- ID_SIGNER_S_AE_0_0_0_0_0_0_0
  Name: Intel External Basic Policy CA
  TBS: 53B052BA209C525233293274854B264BC0F68B73
- ID_SIGNER_S_AF_0_0_0_0_0_0_0
  Name: Microsoft Windows Third Party Component CA 2012
  TBS: CEC1AFD0E310C55C1DCC601AB8E172917706AA32FB5EAF826813547FDF02DD46
- ID_SIGNER_S_17C_0_0_0_0_0_0_0
  Name: COMODO RSA Certification Authority
  TBS: 7CE102D63C57CB48F80A65D1A5E9B350A7A618482AA5A36775323CA933DDFCB00DEF83796A6340DEC5EBF7596CFD8E5D
- ID_SIGNER_S_18D_0_0_0_0_0_0_0
  Name: Microsoft Code Signing PCA 2010
  TBS: 121AF4B922A74247EA49DF50DE37609CC1451A1FE06B2CB7E1E079B492BD8195
- ID_SIGNER_S_2E0_0_0_0_0_0_0_0
  Name: VeriSign Class 3 Code Signing 2010 CA
  TBS: 4843A82ED3B1F2BFBEE9671960E1940C942F688D
- ID_SIGNER_S_34C_0_0_0_0_0_0_0
  Name: Microsoft Code Signing PCA
  TBS: 27543A3F7612DE2261C7228321722402F63A07DE
- ID_SIGNER_S_34F_0_0_0_0_0_0_0
  Name: Microsoft Code Signing PCA 2011
  TBS: F6F717A43AD9ABDDC8CEFDDE1C505462535E7D1307E630F9544A2D14FE8BF26E
- ID_SIGNER_S_37B_0_0_0_0_0_0_0
  Name: Microsoft Root Certificate Authority
  TBS: 391BE92883D52509155BFEAE27B9BD340170B76B
- ID_SIGNER_S_485_0_0_0_0_0_0_0
  Name: Microsoft Windows Verification PCA
  TBS: 265E5C02BDC19AA5394C2C3041FC2BD59774F918

TBS description:

The "Name" attribute is derived from the CN of the certificate. Ultimately, Device Guard doesn't validate the CN. In fact, the "Name" attribute is not present in a binary CI policy (i.e. SIPolicy.p7b). Rather, it validates the TBS (ToBeSigned) hash which is basically a hash of the certificate as dictated by the signature algorithm in the certificate (MD5, SHA1, SHA256, SHA384, SHA512). You can infer the hash algorithm used based on the length of the hash. If you're interested to learn how the hash is calculated, I recommend you load Microsoft.Config.CI.Commands.dll in a decompiler and inspect the Microsoft.SecureBoot.UserConfig.Helper.CalculateTBS method.

Signer hashing algorithms used:

SHA1:
 * Intel External Basic Policy CA
 * VeriSign Class 3 Code Signing 2010 CA
 * Microsoft Code Signing PCA
 * Microsoft Root Certificate Authority
 * Microsoft Windows Verification PCA

Note: Microsoft advises against using a SHA1 signature algorithm and is phasing the algorithm out for certificates. See https://aka.ms/sha1. It is likely within the realm of possibility that a non-state actor could generate a certificate with a SHA1 hash collision.

SHA256:
 * Microsoft Windows Production PCA 2011
 * Microsoft Windows Third Party Component CA 2012
 * Microsoft Code Signing PCA 2010
 * Microsoft Code Signing PCA 2011

SHA384:
 * COMODO RSA Certification Authority

Analysis/recommendations: Driver rules


Overall, I would say the the driver rules may be overly permissive. First of all, any driver signed with any of those certificates would be permitted to be loaded.  For example, I would imagine that most, if not all Intel drivers are signed with the same certificate. So, if there was a driver in particular that was vulnerable that had no business on your system, it could be loaded and exploited to gain unsigned kernel code execution. My recommendation for third party driver certificates is that you whitelist each individual required third party driver using the FilePublisher or preferably the WHQLFilePublisher (if the driver happens to be WHQL signed) file rule level. An added benefit of the FilePublisher rule is that the whitelisted driver will only load if the file version is equal or greater than what is specified. This means that if there is an older, known vulnerable version of the driver you need, the old version will not be authorized to load.

Another potential issue that I could speculatively anticipate is with the "Microsoft Windows Third Party Component CA 2012" certificate. My understanding is that this certificate is used for Microsoft to co-sign 3rd party software. Because this certificate seems to be used so heavily by 3rd party vendors, it potentially opens the door to permit a large amount vulnerable software. To mitigate this, you can use the WHQLPublisher or WHQLFilePublisher rule level when creating a code integrity policy. When those options are selected, if an OEM vendor name is associated with a drivers, a CertOemId attribute will be applied to signers. For example, you could use this feature to whitelist only Apple drivers that are cosigned with the "Microsoft Windows Third Party Component CA 2012" certificate.

ID_SIGNINGSCENARIO_WINDOWS


The following user-mode code signers are whitelisted (based on their presence in AllowedSigners):

- ID_SIGNER_S_1_1_0_0_0_0_0_0
   Name: Microsoft Windows Production PCA 2011
   TBS: 4E80BE107C860DE896384B3EFF50504DC2D76AC7151DF3102A4450637A032146
- ID_SIGNER_S_1_1_0
   Name: Intel External Basic Policy CA
   TBS: 53B052BA209C525233293274854B264BC0F68B73
   CertPublisher: Intel(R) Intel_ICG
- ID_SIGNER_S_2_1_0
   Name: Microsoft Windows Third Party Component CA 2012
   TBS: CEC1AFD0E310C55C1DCC601AB8E172917706AA32FB5EAF826813547FDF02DD46
- ID_SIGNER_S_4_1_0_0_0
   Name: Matthew Graeber
   TBS: B1554C5EEF15063880BB76B347F2215CDB5BBEFA1A0EBD8D8F216B6B93E8906A
- ID_SIGNER_S_19_1_0
   Name: Intel External Basic Policy CA
   TBS: 53B052BA209C525233293274854B264BC0F68B73
   CertPublisher: Intel(R) pGFX
- ID_SIGNER_S_20_1_0
   Name: iKGF_AZSKGFDCS
   TBS: 32656594870EFFE75251652A99B906EDB92D6BB0
   CertPublisher: IntelVPGSigning2016
- ID_SIGNER_S_4E_1_0
   Name: Microsoft Windows Third Party Component CA 2012
   TBS: CEC1AFD0E310C55C1DCC601AB8E172917706AA32FB5EAF826813547FDF02DD46
- ID_SIGNER_S_65_1_0
   Name: VeriSign Class 3 Code Signing 2010 CA
   TBS: 4843A82ED3B1F2BFBEE9671960E1940C942F688D
   CertPublisher: Logitech
- ID_SIGNER_S_35C_1_0_0_0_0_0_0
   Name: Microsoft Code Signing PCA
   TBS: 27543A3F7612DE2261C7228321722402F63A07DE
- ID_SIGNER_S_35F_1_0_0_0_0_0_0
   Name: Microsoft Code Signing PCA 2011
   TBS: F6F717A43AD9ABDDC8CEFDDE1C505462535E7D1307E630F9544A2D14FE8BF26E
- ID_SIGNER_S_1EA5_1_0_0_0_0_0_0
   Name: Microsoft Code Signing PCA 2010
   TBS: 121AF4B922A74247EA49DF50DE37609CC1451A1FE06B2CB7E1E079B492BD8195
- ID_SIGNER_S_2316_1_0_0_0_0_0_0
   Name: Microsoft Windows Verification PCA
   TBS: 265E5C02BDC19AA5394C2C3041FC2BD59774F918
- ID_SIGNER_S_3D8C_1_0_0_0_0_0_0
   Name: Microsoft Code Signing PCA
   TBS: 7251ADC0F732CF409EE462E335BB99544F2DD40F

The following user-mode code blacklist rules are present (based on their presence inDeniedSigners):

- ID_SIGNER_F_1_0_0_1_0_0
   Name: Microsoft Code Signing PCA
   TBS: 27543A3F7612DE2261C7228321722402F63A07DE
   CertPublisher: Microsoft Corporation
   Associated files:
     1) OriginalFileName: cdb.exe
        MinimumFileVersion: 99.0.0.0
     2) OriginalFileName: kd.exe
        MinimumFileVersion: 99.0.0.0
     3) OriginalFileName: windbg.exe
        MinimumFileVersion: 99.0.0.0
     4) OriginalFileName: MSBuild.exe
        MinimumFileVersion: 99.0.0.0
- ID_SIGNER_F_2_0_0_1_0_0
   Name: Microsoft Code Signing PCA 2010
   TBS: 121AF4B922A74247EA49DF50DE37609CC1451A1FE06B2CB7E1E079B492BD8195
   CertPublisher: Microsoft Corporation
   Associated files:
     1) OriginalFileName: cdb.exe
        MinimumFileVersion: 99.0.0.0
     2) OriginalFileName: kd.exe
        MinimumFileVersion: 99.0.0.0
     3) OriginalFileName: windbg.exe
        MinimumFileVersion: 99.0.0.0
- ID_SIGNER_F_3_0_0_1_0_0
   Name: Microsoft Code Signing PCA 2011
   TBS: F6F717A43AD9ABDDC8CEFDDE1C505462535E7D1307E630F9544A2D14FE8BF26E
   CertPublisher: Microsoft Corporation
   Associated files:
     1) OriginalFileName: MSBuild.exe
        MinimumFileVersion: 99.0.0.0
     2) OriginalFileName: csi.exe
        MinimumFileVersion: 99.0.0.0
- ID_SIGNER_F_4_0_0_1_0_0
   Name: Microsoft Windows Production PCA 2011
   TBS: 4E80BE107C860DE896384B3EFF50504DC2D76AC7151DF3102A4450637A032146
   CertPublisher: Microsoft Windows
   Associated files:
     1) OriginalFileName: MSBuild.exe
        MinimumFileVersion: 99.0.0.0

Analysis/recommendations: User-mode rules

Whoever created this policy is clearly mindful of and actively blocking known UMCI bypasses. The downside is that there have since been additional bypasses reported publicly - e.g. dnx.exe from Matt Nelson (@enigma0x3). As a defender employing application whitelisting solutions, it is critical to stay up to date on current bypasses. If not, you're potentially one trusted binary/script away from further compromise.

You may have noticed what seems like an arbitrary selection of "99.0.0.0" for the minimum file version. You can interpret this as any of the files with matching block rules that have a version number less than 99.0.0.0 will be blocked. It is fairly reasonable to assume that a binary won't exceed version 99.0.0.0 but I've recently seen several files in the hundreds so I now recommend setting MinimumFileVersion for each FilePublisher block rule to 999.999.999.999. Unfortunately, at the time of writing, you cannot block an executable by only its signature and OriginalFileName. I hope this will change in the future.

As for the whitelisted signers, I wouldn't have a ton to recommend. As an attacker though, I might try to find executables/scripts signed with the "Matthew Graeber" certificate. This sounds like it would be an easy thing to do but Microsoft actually does not provide an official means of associating an executable or script to a CI policy rule. Ideally, Microsoft would provide a Test-CIPolicy cmdlet similar to the Test-AppLockerPolicy cmdlet. I'm in the process of writing one now.

Overall, there are no signers that stick out to me as worthy of additional investigation. Obviously, Microsoft signers will need to be permitted (and in a non-restrictive) fashion if OS updates are to be accepted. It appears as thought there is some required Intel software present on the system. If anything, I might try to determine why the Intel software is required.


UpdatePolicySigners analysis

There is only a single UpdatePolicySigner: "Matthew Graeber". So while the effort was made to permit that code signing certificate to sign the policy, the "Enabled:Unsigned System Integrity Policy" policy rule was still set. So considering the intent to sign the policy was there, I would certainly recommend that the "Enabled:Unsigned System Integrity Policy" rule be removed and to start enforcing signed policies. As an attacker, I would also look for the presence of this code signing certificate on the same system. It should go without saying that a whitelisted code signing certificate should never be present on a Device Guard-enabled system that whitelists that certificate.

HvciOptions analysis

HvciOptions is set to "1" indicating that it is enabled and that the system will benefit from additional kernel exploitation protections. I cannot recommend setting HVCI to strict mode (3) yet as it is almost certain that there will be some drivers that are not compliant for strict mode.

Conclusion

I'll state again that this analysis has been subjective. An effective policy on one system that has a particular purpose likely won't be effective on another piece of hardware with a separate purpose. Getting CI policy configuration "right" is indeed a challenge. It takes experience, knowledge of the CI policy schema, and it requires that you apply an attackers mindset when auditing a policy.

It is worth noting that even despite having an extremely locked down policy, the OS is still at the mercy of UMCI bypasses. For this very reason, Device Guard should be merely a component of a layered defense. It is certainly recommended that anti-malware solutions be installed side by side with Device Guard. For example, in a post-exploitation scenario, Device Guard will do nothing about the exfiltration of sensitive data using a simple batch script or PowerShell script operating in constrained language mode.

I will leave the comments section open to encourage discussion about your thoughts on CI policy assessment and how you think this example policy might have additional vulnerabilities. I feel as though I'm breaking new ground here since there is no other information available regarding Device Guard policy audit methodology so I am certainly open to candid feedback.