| 
 | 1 | +---  | 
 | 2 | +description: This article explains how to configure and use WDAC to secure PowerShell.  | 
 | 3 | +ms.date: 09/19/2024  | 
 | 4 | +title: How to use WDAC to secure PowerShell  | 
 | 5 | +---  | 
 | 6 | +# How to use WDAC to secure PowerShell  | 
 | 7 | + | 
 | 8 | +This article describes how to set up a **Windows Defender Application Control** (WDAC) policy. You  | 
 | 9 | +can configure the policy to enforce or audit the policy's rule. In audit mode, PowerShell behavior  | 
 | 10 | +doesn't change but it logs Event ID 16387 messages to the `PowerShellCore/Analytic` event log. In  | 
 | 11 | +enforcement mode, PowerShell applies the policy's restrictions.  | 
 | 12 | + | 
 | 13 | +This article assumes you're using a test machine so that you can test PowerShell behavior  | 
 | 14 | +under a machine wide WDAC policy before you deploy the policy in your environment.  | 
 | 15 | + | 
 | 16 | +## Create a WDAC policy  | 
 | 17 | + | 
 | 18 | +A WDAC policy is described in an XML file, which contains information about policy options, files  | 
 | 19 | +allowed, and signing certificates recognized by the policy. When the policy is applied, only  | 
 | 20 | +approved files are allowed to load and run. PowerShell either blocks unapproved script files from  | 
 | 21 | +running or runs them in `ConstrainedLanguage` mode, depending on policy options.  | 
 | 22 | + | 
 | 23 | +You create and manipulate WDAC policy using the **ConfigCI** module, which is available on all  | 
 | 24 | +supported Windows version. This Windows PowerShell module that can be used in Windows PowerShell 5.1  | 
 | 25 | +or in PowerShell 7 through the **Windows Compatibility** layer. It's easier to use this module in  | 
 | 26 | +Windows PowerShell. The policy you create can be applied to any version of PowerShell.  | 
 | 27 | + | 
 | 28 | +## Steps to create a WDAC policy  | 
 | 29 | + | 
 | 30 | +For testing, you just need to create a default policy and a self signed code signing certificate.  | 
 | 31 | + | 
 | 32 | +1. Create a default policy  | 
 | 33 | + | 
 | 34 | +   ```powershell  | 
 | 35 | +   New-CIPolicy -Level PcaCertificate -FilePath .\SystemCIPolicy.xml -UserPEs  | 
 | 36 | +   ```  | 
 | 37 | + | 
 | 38 | +   This command creates a default policy file called `SystemCIPolicy.xml` that allows all Microsoft  | 
 | 39 | +   code-signed files to run.  | 
 | 40 | + | 
 | 41 | +   > [!NOTE]  | 
 | 42 | +   > Running this command can take up to two hours because it must scan the entire test machine.  | 
 | 43 | +
  | 
 | 44 | +1. Disable Audit Mode in default policy  | 
 | 45 | + | 
 | 46 | +   A new policy is always created in `Audit` mode. To test policy enforcement, you need to disable  | 
 | 47 | +   Audit mode when you apply the the policy. Edit the `SystemCIPolicy.xml` file using text editor  | 
 | 48 | +   like `notepad.exe` or Visual Studio Code (VS Code). Comment out the `Audit mode` option.  | 
 | 49 | + | 
 | 50 | +   ```XML  | 
 | 51 | +   <!--  | 
 | 52 | +   <Rule>  | 
 | 53 | +     <Option>Enabled:Audit Mode</Option>  | 
 | 54 | +   </Rule>  | 
 | 55 | +   -->  | 
 | 56 | +   ```  | 
 | 57 | + | 
 | 58 | +1. Create a self-signed code signing certificate  | 
 | 59 | + | 
 | 60 | +   You need a code signing certificate to sign any test binaries or script files that you want to  | 
 | 61 | +   run on your test machine. The `New-SelfSignedCertificate` is provided by the **PKI** module. For  | 
 | 62 | +   best results, you should run this command in Windows PowerShell 5.1.  | 
 | 63 | + | 
 | 64 | +   ```powershell  | 
 | 65 | +   $newSelfSignedCertificateSplat = @{  | 
 | 66 | +       DnsName = $env:COMPUTERNAME  | 
 | 67 | +       CertStoreLocation = "Cert:\CurrentUser\My\"  | 
 | 68 | +       Type = 'CodeSigningCert'  | 
 | 69 | +   }  | 
 | 70 | +   $cert = New-SelfSignedCertificate @newSelfSignedCertificateSplat  | 
 | 71 | +   Export-Certificate -Cert $cert -FilePath c:\certs\signing.cer  | 
 | 72 | +   Import-Certificate -FilePath C:\certs\signing.cer -CertStoreLocation "Cert:\CurrentUser\Root\"  | 
 | 73 | +   $cert = Get-ChildItem Cert:\CurrentUser\My\ -CodeSigningCert  | 
 | 74 | +
  | 
 | 75 | +   dir c:\bin\powershell\pwsh.exe | Set-AuthenticodeSignature -Certificate $cert  | 
 | 76 | +   ```  | 
 | 77 | + | 
 | 78 | +1. Add the code signing certificate to the policy  | 
 | 79 | + | 
 | 80 | +   Use the following command to add the new code signing certificate to the policy.  | 
 | 81 | + | 
 | 82 | +   ```powershell  | 
 | 83 | +   Add-SignerRule -FilePath .\SystemCIPolicy.xml -CertificatePath c:\certs\signing.cer -User  | 
 | 84 | +   ```  | 
 | 85 | + | 
 | 86 | +1. Convert the XML policy file to a policy enforcement binary file  | 
 | 87 | + | 
 | 88 | +   Finally, you need to convert the XML file to a binary file used by WDAC to apply a policy.  | 
 | 89 | + | 
 | 90 | +   ```powershell  | 
 | 91 | +   ConvertFrom-CIPolicy -XmlFilePath .\SystemCIPolicy.xml -BinaryFilePath .\SIPolicy.p7b  | 
 | 92 | +   ```  | 
 | 93 | + | 
 | 94 | +1. Apply the WDAC policy  | 
 | 95 | + | 
 | 96 | +   To apply the policy to your test machine, copy the `SIPolicy.p7b` file to the required system  | 
 | 97 | +   location, `C:\Windows\System32\CodeIntegrity`.  | 
 | 98 | + | 
 | 99 | +   > [!NOTE]  | 
 | 100 | +   > Some policies definition must be copied to a subfolder such as  | 
 | 101 | +   > `C:\Windows\System32\CodeIntegrity\CiPolicies`. For more information, see  | 
 | 102 | +   > [WDAC Admin Tips & Known Issues][01].  | 
 | 103 | +
  | 
 | 104 | +1. Disable the WDAC policy  | 
 | 105 | + | 
 | 106 | +   To disable the policy, rename the `SIPolicy.p7b` file. If you need to do more testing, you can  | 
 | 107 | +   change the name back to reenable the policy.  | 
 | 108 | + | 
 | 109 | +   ```powershell  | 
 | 110 | +   Rename-Item -Path .\SIPolicy.p7b -NewName .\SIPolicy.p7b.off  | 
 | 111 | +   ```  | 
 | 112 | + | 
 | 113 | +## Test using WDAC policy auditing  | 
 | 114 | + | 
 | 115 | +PowerShell 7.4 added a new feature to support WDAC policies in **Audit** mode. In audit mode,  | 
 | 116 | +PowerShell runs the untrusted scripts in `ConstrainedLanguage` mode without errors, but logs  | 
 | 117 | +messages to the event log instead. The log messages describe what restrictions would apply if the  | 
 | 118 | +policy was in **Enforce** mode.  | 
 | 119 | + | 
 | 120 | +### Viewing audit events  | 
 | 121 | + | 
 | 122 | +PowerShell logs audit events to the **PowerShellCore/Analytic** event log. The log isn't enabled by  | 
 | 123 | +default. To enable the log, open the **Windows Event Viewer**, right-click on the  | 
 | 124 | +**PowerShellCore/Analytic** log and select **Enable Log**.  | 
 | 125 | + | 
 | 126 | +Alternatively, you can run the following command from an elevated PowerShell session.  | 
 | 127 | + | 
 | 128 | +```powershell  | 
 | 129 | +wevtutil.exe sl PowerShellCore/Analytic /enabled:true /quiet  | 
 | 130 | +```  | 
 | 131 | + | 
 | 132 | +You can view the events in the Windows Event Viewer or use the `Get-WinEvent` cmdlet to retrieve the  | 
 | 133 | +events.  | 
 | 134 | + | 
 | 135 | +```powershell  | 
 | 136 | +Get-WinEvent -LogName PowerShellCore/Analytic -Oldest |  | 
 | 137 | +    Where-Object Id -eq 16387 | Format-List  | 
 | 138 | +```  | 
 | 139 | + | 
 | 140 | +```Output  | 
 | 141 | +TimeCreated  : 4/19/2023 10:11:07 AM  | 
 | 142 | +ProviderName : PowerShellCore  | 
 | 143 | +Id           : 16387  | 
 | 144 | +Message      : WDAC Audit.  | 
 | 145 | +
  | 
 | 146 | +    Title: Method or Property Invocation  | 
 | 147 | +    Message: Method or Property 'WriteLine' on type 'System.Console' invocation will not  | 
 | 148 | +        be allowed in ConstrainedLanguage mode.  | 
 | 149 | +        At C:\scripts\Test1.ps1:3 char:1  | 
 | 150 | +        + [System.Console]::WriteLine("pwnd!")  | 
 | 151 | +        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  | 
 | 152 | +    FullyQualifiedId: MethodOrPropertyInvocationNotAllowed  | 
 | 153 | +```  | 
 | 154 | + | 
 | 155 | +The event message includes the script position where the restriction would be applied. This  | 
 | 156 | +information helps you understand where you need to change your script so that it runs under the WDAC  | 
 | 157 | +policy.  | 
 | 158 | + | 
 | 159 | +> [!IMPORTANT]  | 
 | 160 | +> Once you have reviewed the audit events, you should disable the Analytic log. Analytic logs grow  | 
 | 161 | +> quickly and consume large amounts of disk space.  | 
 | 162 | +
  | 
 | 163 | +### Viewing audit events in the PowerShell debugger  | 
 | 164 | + | 
 | 165 | +If you set the `$DebugPreference` variable to `Break` for an interactive PowerShell session,  | 
 | 166 | +PowerShell breaks into the command-line script debugger at the current location in the script where  | 
 | 167 | +the audit event occurred. The breakpoint allows you to debug your code and inspect the current state  | 
 | 168 | +of the script in real time.  | 
 | 169 | + | 
 | 170 | +<!-- link references -->  | 
 | 171 | +[01]: /windows/security/application-security/application-control/windows-defender-application-control/operations/known-issues  | 
0 commit comments