HotCakeX / Harden-Windows-Security

Harden Windows Safely, Securely using Official Supported Microsoft methods and proper explanation | Always up-to-date and works with the latest build of Windows | Provides tools and Guides for Personal, Enterprise, Government and Military security levels | Read The Rationale https://github.com/HotCakeX/Harden-Windows-Security/blob/main/Rationale.md
https://hotcakex.github.io
MIT License
1.87k stars 148 forks source link

Update Harden-Windows-Security.ps1 #5

Closed HotCakeX closed 1 year ago

HotCakeX commented 1 year ago

The script now applies the official Microsoft Security Baselines and on top of that applies as many of the script settings as possible using Group Policy, the rest of the settings that aren't possible to be applied using Group Policy continue to be applied using registry and PowerShell Cmdlets.

Also: enforce encryption type on removable and fixed drive types to full disk encryption instead of only used disk encryption

HotCakeX commented 1 year ago

Read this Wiki page to learn more about the whole process

https://github.com/HotCakeX/Harden-Windows-Security/wiki/Group-Policy

HotCakeX commented 1 year ago

To Do before this pull request has permission to be merged:


HotCakeX commented 1 year ago

Put an extra check for Bitlocker according to this issue https://github.com/HotCakeX/Harden-Windows-Security/issues/6

innovatodev commented 1 year ago

You could also check for 8GB ram requirements for defender application guard https://learn.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-application-guard/reqs-md-app-guard trying to install it on 4gb ram VM will just not work and will tell "pc is not ready to use that feature", but will works fine on 8 (at least for me).

You should rework the entire optionalfeature section because you dont check for any errors since the powershell is executed in another session. PowerShell.exe "..." this is really not good because you dont even know if the feature was added before continuing, you could error check it if you want to keep it in another session, but will require to use .LastExitCode -eq 0 by properly calling the process with start-process, or the method you want (but this method will works for pwsh too, if thats what you want). (or just check if the state is enabled after the process ended at least)

Also, your mdns firewall rule do not work on non-english systems. Disable-NetFirewallRule -DisplayName "mDNS (UDP-In)" because in french system (by example) this name is (UDP-Entrée), you have differents solutions for that : Targeting the DisplayGroup (it will be mdns on most system i think) or displayname -like "mdns" ^^ or even with the group directly (that should work on all systems) : @%SystemRoot%\system32\firewallapi.dll,-37302 but there also edge who is using mdns (Microsoft Edge (mDNS-In)) and maybe you want to disable it too, maybe the -like "mdns" is not too bad (but it will not work on arabic and chinese systems i think)

And what happens if the rule do not exist ? your code should throw 0 powershell errors, you need to check before doing something, or if you dont care about cheking, you can erroraction silentlycontinue, but the goal is to see no errors, because error = bad for the end user and the user can panic for it because its a big block of red text basically, and they just want to use your tool and be sure everything went ok, and if something went not ok, they want to know what, and why, if your script cant work on home edition (for many reasons actually) you should put a big warning on your readme, and maybe even checking it at the top of your script, and restrict your script to all but home edition.

Because some of powershell users have a powershell profile, you can configure here if the scripts will stop on error by default (default powershell will continue, but its not everywhere the same) you can add $ErrorActionPreference = "whateveryouwant" at the top of your script, to force it on all systems for your personal preference during your script ^^

HotCakeX commented 1 year ago

You could also check for 8GB ram requirements for defender application guard https://learn.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-application-guard/reqs-md-app-guard trying to install it on 4gb ram VM will just not work and will tell "pc is not ready to use that feature", but will works fine on 8 (at least for me).

You should rework the entire optionalfeature section because you dont check for any errors since the powershell is executed in another session. PowerShell.exe "..." this is really not good because you dont even know if the feature was added before continuing, you could error check it if you want to keep it in another session, but will require to use .LastExitCode -eq 0 by properly calling the process with start-process, or the method you want (but this method will works for pwsh too, if thats what you want).

Hi, I just tried again to run optional features category on a clean VM, with 4 cores and 4GB RAM, there was no error.

VM details:

Edition Windows 11 Pro Insider Preview
Version 22H2
Installed on    ‎1/‎24/‎2023
OS build    25276.1000
Experience  Windows Feature Experience Pack 1000.25276.1000.0

I will add System requirements for Microsoft Defender Application Guard to the Readme page for WDAG section in optional features category so users can find it easier.

when a system doesn't have 8GB RAM, the PowerShell script still turns on WDAG, and you restart the system, but still there won't be WDAG option in Edge browser because the system doesn't meet the RAM requirement.

for error handling about other optional features, I intentionally didn't suppress any errors because 1) I've never had any errors in my tests with real hardware and VM and 2) even if there is some rare error, I wouldn't know how to handle it, so the best thing is to show it to the user with details.

the script is for people who are fully aware what they are doing. when you run the script, there will be a clear warning to tell people to completely read the GitHub Readme page before using the script, so they can be aware of the requirements and what settings are going to be applied.

If I silently continued despite having errors and didn't output it in the PowerShell console, user would think everything was activated successfully which is not good at all.

the error message that you received saying "pc is not ready to use that feature" is good, it will inform the user to read GitHub readme and see the requirements for the feature, if they haven't read it already.

(or just check if the state is enabled after the process ended at least)

This is good, I will do that :)

Also, your mdns firewall rule do not work on non-english systems. Disable-NetFirewallRule -DisplayName "mDNS (UDP-In)" because in french system (by example) this name is (UDP-Entrée), you have differents solutions for that : Targeting the DisplayGroup (it will be mdns on most system i think) or displayname -like "mdns" ^^ or even with the group directly (that should work on all systems) : @%SystemRoot%\system32\firewallapi.dll,-37302 but there also edge who is using mdns (Microsoft Edge (mDNS-In)) and maybe you want to disable it too, maybe the -like "mdns" is not too bad (but it will not work on arabic and chinese systems i think)

Wow I never even thought about that scenario haha

Try this on your system please, that has French language pack installed, see if it will work and show you only 3 rules (private, domain, public) for mDNS (UDP-in) only. 🤞

get-NetFirewallRule |
Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" }

(get-NetFirewallRule |
Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" }).count

And what happens if the rule do not exist ? your code should throw 0 powershell errors, you need to check before doing something, or if you dont care about cheking, you can erroraction silentlycontinue, but the goal is to see no errors, because error = bad for the end user and the user can panic for it because its a big block of red text basically, and they just want to use your tool and be sure everything went ok, and if something went not ok, they want to know what, and why, if your script cant work on home edition (for many reasons actually) you should put a big warning on your readme, and maybe even checking it at the top of your script, and restrict your script to all but home edition.

Because some of powershell users have a powershell profile, you can configure here if the scripts will stop on error by default (default powershell will continue, but its not everywhere the same) you can add $ErrorActionPreference = "whateveryouwant" at the top of your script, to force it on all systems for your personal preference during your script ^^

I will add the info about Home edition not supported to the Readme page.

I can check if Home edition is installed if this command returns 101

more info

(Get-WmiObject Win32_OperatingSystem).OperatingSystemSKU

if Home edition is detected, the script won't run at all and exit.

HotCakeX commented 1 year ago

@innovatodev

Please also check this with French language pack, even if it returns 6 rules instead of 3, I think still acceptable to add it to the script, instead of only inbound rules, it will block inbound and outbound rules, but only for Windows mDNS, doesn't affect Edge browser or any other rule :)

(get-NetFirewallRule |
Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" }).count

get-NetFirewallRule |
Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" }

doing this because i suspect the word "inbound" is translated to French on a system where French language pack is installed.

ghost commented 1 year ago

trying to install it on 4gb ram VM will just not work and will tell "pc is not ready to use that feature", but will works fine on 8 (at least for me).

WDAG works with lower RAM with a manual registry tweak, however it's better to also show a warning that the user experience is going to suffer if user insists using WDAG on a device with low RAM.

innovatodev commented 1 year ago

Oh yeah you right, even if the feature is not activable manually by the GUI (greyed) with 4gb, it will enable it (even if will not usable without the registry tweak jxo is mentioning, at least it does not bug out) with the powershell command, so there no problem here, sorry !

get-NetFirewallRule |

Where-Object {$.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $.Direction -eq "inbound" } = this one is works perfectly (count 3)

Yes your suspects are good its exactly because the display is traduced ( UPD-In vs UDP-Entrée) so imagine in chinese windows, it will not even be standard charset, the hard firewall ruleset is a good way to work everywere i think. Everything is working on my side

bitlocker does not want to work from a fresh installed windows on this version using irm -Uri "https://raw.githubusercontent.com/HotCakeX/Harden-Windows-Security/HotCakeX-patch-2-GroupPolicy/Harden-Windows-Security.ps1" -OutFile "Harden-Windows-Security.ps1"

Add-TpmAndPinProtectorInternal: Group Policy settings do not allow the use of a PIN at startup. Choose another BitLocker boot option. (Exception from HRESULT: 0x80310060)

and if i reboot i got a weird message to tell me bitlocked was aborted (so it is trying to, even if i got this message before the restart)

Maybe it is because i get this on the first step : Invalid directory name for GPO backup: ..\Security-Baselines-X{300945C6-E397-4D12-A29F-18612FBD1058} from the lgpo.exe's output

it was working good with the manual registry settings you was doing on the yesterday's version, ill try to investigate, it is weird because i can see there a lot of configurated settings in my gpedit.msc, so the gpo import is working (or at least a part of it)

even doing a gpupdate /force between policies section and bitlocker section does not solve it.

ps: the .Direction is still "inbound/outbound" on firewall's rule property, its safe to add $_.Direction -eq "inbound if you want to you just need to not target DisplaySomething with english text.

HotCakeX commented 1 year ago

trying to install it on 4gb ram VM will just not work and will tell "pc is not ready to use that feature", but will works fine on 8 (at least for me).

WDAG works with lower RAM with a manual registry tweak, however it's better to also show a warning that the user experience is going to suffer if user insists using WDAG on a device with low RAM.

I'm updating the entire Readme with a new version that has updated info, I added your links to the WDAG section :)

https://github.com/HotCakeX/Harden-Windows-Security/pull/7

HotCakeX commented 1 year ago

Oh yeah you right, even if the feature is not activable manually by the GUI (greyed) with 4gb, it will enable it (even if will not usable without the registry tweak jxo is mentioning, at least it does not bug out) with the powershell command, so there no problem here, sorry !

get-NetFirewallRule |

Where-Object {$.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $.Direction -eq "inbound" } = this one is works perfectly (count 3)

Yes your suspects are good its exactly because the display is traduced ( UPD-In vs UDP-Entrée) so imagine in chinese windows, it will not even be standard charset, the hard firewall ruleset is a good way to work everywere i think. Everything is working on my side

bitlocker does not want to work from a fresh installed windows on this version using irm -Uri "https://raw.githubusercontent.com/HotCakeX/Harden-Windows-Security/HotCakeX-patch-2-GroupPolicy/Harden-Windows-Security.ps1" -OutFile "Harden-Windows-Security.ps1"

Add-TpmAndPinProtectorInternal: Group Policy settings do not allow the use of a PIN at startup. Choose another BitLocker boot option. (Exception from HRESULT: 0x80310060)

and if i reboot i got a weird message to tell me bitlocked was aborted (so it is trying to, even if i got this message before the restart)

Maybe it is because i get this on the first step : Invalid directory name for GPO backup: ..\Security-Baselines-X{300945C6-E397-4D12-A29F-18612FBD1058} from the lgpo.exe's output

it was working good with the manual registry settings you was doing on the yesterday's version, ill try to investigate, it is weird because i can see there a lot of configurated settings in my gpedit.msc, so the gpo import is working (or at least a part of it)

even doing a gpupdate /force between policies section and bitlocker section does not solve it.

ps: the .Direction is still "inbound/outbound" on firewall's rule property, its safe to add $_.Direction -eq "inbound if you want to you just need to not target DisplaySomething with english text.

Thank you,

so let me double check, which one of these should I use so that the PowerShell script will work in any system language (including French, Chinese etc.).

  1. This?
get-NetFirewallRule | Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" }
  1. or this?
get-NetFirewallRule | Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" }

I will also check that error ^^

innovatodev commented 1 year ago

Both works, but if you want to disable only the inbound, you can use the first one. The .direction should works the same on all system it is not something microsoft traduce, since it works for me the same as you

HotCakeX commented 1 year ago

Both works, but if you want to disable only the inbound, you can use the first one. The .direction should works the same on all system it is not something microsoft traduce, since it works for me the same as you

Awesome, appreciate that!

so I'm adding this to the Firewall category

get-NetFirewallRule
    | Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" }
        | ForEach-Object {
            Disable-NetFirewallRule -DisplayName $_.DisplayName}

To quickly verify it:

get-NetFirewallRule
    | Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" }
        | Select-Object -Property Enabled,name
innovatodev commented 1 year ago

Enabled Name


True MDNS-In-UDP-Private-Active True MDNS-In-UDP-Domain-Active True MDNS-In-UDP-Public-Active

It just works ^^

Get-NetFirewallRule |
Where-Object { $_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" } |
Select-Object -Property Enabled, name

does work !

I see you are using a lot of aliases in your script (popd will be automaticly converted to Pop-Location) if you want to with a single setting in vscode (some people have a custom aliases profile and remove the default microsoft provided alias, its always a good practice to not use aliases in your public projects because of this

HotCakeX commented 1 year ago

@innovatodev Good point, fixed it. their aliases were just cute to use lol I just updated the code in this pull request, see if there is any thing that needs changing, thanks

innovatodev commented 1 year ago

I like them a lot for personal projects but when you want to publicy offer powershell scripts, you want to be more standardized i think haha

if you want, you can use a more 'structured' menu for asking user different options, it is more clear both on the console and on the code than just a simple coloured read-host, an example you can test independally :

function Select-Option
{
    param(
        [parameter(Mandatory = $true, Position = 0)][string]$Message,
        [parameter(Mandatory = $true, Position = 1)][string[]]$Options
    )
    $Selected = $null
    while ($null -eq $Selected)
    {
        Write-Host $Message -ForegroundColor DarkMagenta
        for ($i = 0; $i -lt $Options.Length; $i++) { Write-Host "$($i+1): $($Options[$i])" }
        $SelectedIndex = Read-Host "Select an option"
        if ($SelectedIndex -gt 0 -and $SelectedIndex -le $Options.Length) { $Selected = $Options[$SelectedIndex - 1] }
        else { Write-Host "Invalid Option." -ForegroundColor Yellow }
    }
    return $Selected
}

An then you can use it by different ways, without modifying the logic of the function, a few exemples

# Possibility to ignore
switch (Select-Option -Options "Yes", "No", "Ignore" -Message "Do you want to continue ?")
{
    "Yes"
    {
        Write-Host "Lets go !"
    }
    "No"
    {
        Write-Host "Abort mission !"
    }
}
# Cannot ignore you request a yes or a no
$Options = "Yes", "No"
$Message = "Do you want to continue ?"
switch (Select-Option -Options $Options -Message $Message)
{
    "Yes"
    {
        Write-Host "Lets go !"
    }
    "No"
    {
        Write-Host "Abort mission !"
    }
}

So if one day your project has 150 questions, and you want to modify the colour of the warning, it will be 1 line modified for the next commit, instead of 150 lines. And generic functions like that can be used in a lot of differents project without reinventing the wheel each time for each questions ^^ Thats all about preferences, but if you want people to contribute to your code or fix issues, it should be the more generic possible, and less repetitive too. For your future "you" its also a good thing lol.

HotCakeX commented 1 year ago

@innovatodev I love that a lot, thank you! the current yes and no question was just something I quickly came up with and kept copy pasting it everywhere lol

I will use your code in the script and show you the result ^^

my goal is to reduce the PowerShell script's code as much as possible and enable all security measures with Group Policy eventually :)

HotCakeX commented 1 year ago

another good thing about your function is that I think using numbers 1..10 is better than Y and N for multi-language support because not all languages use Y or N.

innovatodev commented 1 year ago

Yeah its all about personal preference for this kind of things after all, but you want to manage the loop logic into the function, so on your script's body, there less bloat as possible ^^ Yes the 1.. is better cuz if you ask a chinese to reply Y, he will struggle to use alt+combinaison or open charmap.exe because his keyboard does not have it i imagine lol and it open to unlimited of options, you can set whatever you want in the options, even a list of things if you want Options = "Saint-honoré","Chocolatine","Hotdog" it will works the same, with the same function. Its all about generic as possible functions !

HotCakeX commented 1 year ago

Yeah its all about personal preference for this kind of things after all, but you want to manage the loop logic into the function, so on your script's body, there less bloat as possible ^^ Yes the 1.. is better cuz if you ask a chinese to reply Y, he will struggle to use alt+combinaison or open charmap.exe because his keyboard does not have it i imagine lol and it open to unlimited of options, you can set whatever you want in the options, even a list of things if you want Options = "Saint-honoré","Chocolatine","Hotdog" it will works the same, with the same function. Its all about generic as possible functions !

Very good, perfect ^^

I want my options to be "baguette" with "Nutella" :D

innovatodev commented 1 year ago

You can use #region to define regions of your code ^^

#region TLS Security
all
the
code
here
#endregion TLS Security

And you will be able to wrap/unwrap the part in all IDE, from ISE to vscode or even vs.

2023_01_26_22_08_12_launch ps1_-_hard_-_Visual_Studio_Code_ Administra

2023_01_26_22_08_18_launch ps1_-_hard_-_Visual_Studio_Code_ Administra

HotCakeX commented 1 year ago

Going for the super duper optimization I see ^^ I'm on it, meanwhile you can check out the last change I just made and see if everything is alright!

innovatodev commented 1 year ago

Its up to you these are just some better usages of what you are already using, its nice to be able to wrap your region while you are coding, its made for that, you said you want shorter code, i converted 6 lines to 2 + a new wrap feature on your editor ! 😄 ill check how is it going on my vm.

innovatodev commented 1 year ago

You need to set VSCode to auto format your powershell when you save, because actually, your firewall rule code do not work because of formating : bad

get-NetFirewallRule
    | Where-Object {$_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" }
        | Select-Object -Property Enabled,name

good

Get-NetFirewallRule |
Where-Object { $_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" } |
Select-Object -Property Enabled, name
#or
Get-NetFirewallRule
| Where-Object { $_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" }
| Select-Object -Property Enabled, name
#or even (but the pipeline has to be at the end of the previous line if you want to do that
Get-NetFirewallRule |
Where-Object { $_.RuleGroup -eq "@%SystemRoot%\system32\firewallapi.dll,-37302" -and $_.Direction -eq "inbound" } |
             Select-Object -Property Enabled, name

if you want to keep the pipelines to the start of the nextline, it has to be the first char (no space) and that is the type of things that can be auto corrected by vscode and some finetuned settings ^^ (powershell is ultra cool because it is the syntax is very free to a lot of different codestyles, but this can be tricky in certain ways, same thing happens with the ` character if you want to use it to split args from a command, it has to be the last char of the line.

HotCakeX commented 1 year ago

Thank you, fixed it ^^ And also used Shift + Alt + F to automatically format the code :)

Do you think it's ready to be published for now? we will optimize it more after that ^^

here is the file for easier testing

Fixed an issue with it, here is the new one

Harden-Windows-Security.zip

innovatodev commented 1 year ago

We can test your script everytime you push/commit by using irm -Uri "https://raw.githubusercontent.com/HotCakeX/Harden-Windows-Security/HotCakeX-patch-2-GroupPolicy/Harden-Windows-Security.ps1" -OutFile "Harden-Windows-Security.ps1"

to download this exact branch so no worries for that ^^ Ill test that when i got some time but it looks good so far !

innovatodev commented 1 year ago

Good news, your last change about the {300945C6-E397-4D12-A29F-18612FBD1058} in the name fixed most of my errors, bitlocker install properly and all the rest seems to be ok !

I just got an error at step 1, all the computer policies are properly imported, but all the user ones are not. Le mappage entre les noms de compte et les ID de sécurité n'a pas été effectué

=

Mapping between account names and security IDs was not done

Possibles case: Because administrator on non-english systems are not called administrator (administrateur in french) Our username are not the same (and thats gonna be a problem lol^^)

Possible fix : do you know if the security compliance template contains user settings ? because if not, you can use /m path\registry.pol import settings from registry.pol into machine config instead of /g to import only the computer ones

HotCakeX commented 1 year ago

Good news, your last change about the {300945C6-E397-4D12-A29F-18612FBD1058} in the name fixed most of my errors, bitlocker install properly and all the rest seems to be ok !

I just got an error at step 1, all the computer policies are properly imported, but all the user ones are not. Le mappage entre les noms de compte et les ID de sécurité n'a pas été effectué

=

Mapping between account names and security IDs was not done

Possibles case: Because administrator on non-english systems are not called administrator (administrateur in french) Our username are not the same (and thats gonna be a problem lol^^)

Possible fix : do you know if the security compliance template contains user settings ? because if not, you can use /m path\registry.pol import settings from registry.pol into machine config instead of /g to import only the computer ones

Yeah haha sorry, took me a while to realize that file name mismatch

Security Baselines X doesn't apply any user related policies, only machine. the file that is inside the zip file literally only has 1 word in it, lol. I verified this with Policy Analyzer too, it's empty.

you can check it out and verify too. do you think it's safe to delete User folder and only keep machine? it should fix the problem you are talking about, right?

innovatodev commented 1 year ago

we can test with /m parameter instead of g, and importing just the computer one. you dont have to delete anything until we know its working

actually i got this problem : Windows failed to apply the {F312195E-3D9D-447A-A3F5-08DFFA24735E} settings.

googling one guy is suggesting its a possible registry problem : https://www.theexperienceblog.com/2017/08/11/gpo-error-message-applying-settings-for-f312195e-3d9d-447a-a3f5-08dffa24735e/

Solution In the GPO setting Turn on Virtualization Based Security found in Computer Configuration\Administrative Templates\System\Device Guard edit the and set Virtualization Based Protection of Code Integrity to Disabled. This will make the HypervisorEnforcedCodeIntegrity turn to 0 and the GPO will apply without errors.

It is strange for a security compliance to set another security value to disabled tho, i dont really understand.

HotCakeX commented 1 year ago

Yeah I agree, better not use the solution he talks about. it's 6 years old anyway.

I haven't ever got that error in any tests, maybe during your tests, some setting was changed in a bad way that is causing that problem?

HotCakeX commented 1 year ago

Microsoft Security baselines have 2 User policies, they are in these 2 folders:

is Microsoft Security baselines available in French language? if so, can you test and see if you get the same error with it too? preferably on a fresh VM.

innovatodev commented 1 year ago

My vm is always fresh (i return on a snapshot from fresh first desktop between each tests, but, i cant seems to find any compliances in french its universal i think so no problem on that.

But actually, {F312195E-3D9D-447A-A3F5-08DFFA24735E} wich one is it ? i cant find this uid on the compliance, is it the one from the script itself ?

innovatodev commented 1 year ago

Yes i think there a problem in the Security-Baselines-X itself, all the others from microsoft import without problem, but the {F312195E-3D9D-447A-A3F5-08DFFA24735E} is from your gpo it is present is the backup.xml into Security-Baselines-X How do you process to make your own template for the rest of the settings that the compliance dont do?

Okay interessing !!! i made a gpreport to html (it is in french :() BUT it say everysettings are applied, with a /!\ with this

it say maybe it require a few reboot to finally work, ill try to reboot a few times (tried 2 times already) to see if the gpresult stop doing this error, but in all case, it seems to work since all settings are "applied" and nothing is "refused"

You dont get any error while updating with gpupdate in your side for the user policy ? thats really strange. i'm still getting the "Mapping between account names and security IDs was not done" when running the script and thats possible it is because default groups and users are not spelled the same on windows in other langages .. ill try with en-us iso tomorrow.

innovatodev commented 1 year ago

Ok i did get some time to test the en-us windows, and ... its night and day lol everything works perfectly, the windows is perfectly responsive, i still cant gpupdate /force without errors but on en-us i got some informations i dont get on the french one ... 2023_01_27_05_36_59_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u

so its only a problem because my host does not support this thing and my vm too since my host do not.

You can try it yourself too, just do gpupdate /force, if you got an error, you GPRESULT /H GPReport.html and read the report

I invite you to test another langage of windows, you can download an evaluation of windows in french, or any lang you prefair (it should be ok to navigate even if you dont understand the langage, its windows after all) or you can download a normal iso with static link provided by microsoft or mediacreationtool.exe : Start-Process -FilePath .\mediacreationtool.exe -ArgumentList "/Eula Accept /Retail /MediaArch x64 /MediaLangCode fr-FR /MediaEdition Enterprise" -Wait you can provide a generic key : NPPR9-FWDCX-D2C8J-H872K-2YT43

On en-us i dont get any errors in the output of lgpo.exe, all is ok, even if the policy is bugged out because of this IOMMU, it works. But on french windows, after your script, the windows become unresponsive, slow and bug a lot of thing, i got an error message in tray menu saying a service cannot load and i will not be able to elevate to administrator and things like that, code integrity from kernel isolation is disabled, a lot of things are not applied because of this. Maybe/probably because of this "Mapping between account names and security IDs was not done" error message i'm seeing when applying your Baseline-X, probably caused by having a different set of integrated groups (administrators = administrateurs etc.) we could analyze how microsoft is doing their policies, because they did it, their policies works on all langages without problems/errors when importing with lgpo.

But the good news is even if (my) policy is bugged even on en-us at least the rest of the stuff apply correctly, its just a problem of IOMMU and that seems to only affect the memory access protection : https://learn.microsoft.com/en-us/windows/security/information-protection/kernel-dma-protection-for-thunderbolt If you really want to publish, its your project, but you should try another langage in my opinion, to test with me if its only a problem on my side 😊 i tested : Windows 11, version 22H2 (22621.1194) amd64 fr-fr en-us Windows 11, version 22H2 (22621.1105) amd64 fr-fr both are retails, not insider but pretty recent. (last and second last one)

Apparently i'm not DMA Protection compatible because it only support intel cpu (vt-x) It will be hard to check every single possibilities for all your users, check if everyting is compatible etc. And it will not be possible to do it using a policy template, you will need to parse the .pol and apply settings by settings if you want to not apply a specific setting for a specific user, it is possible (lot of people are doing it) but it will take a few long functions in your script, in order to get/add from the .pol. But it could solve the problems for names and security IDs instantly too since it apply to the user's pol config already configurated to work on his machine 😊 Or you return to the old registry way for your settings part, but some settings will be policy applied and some others will not. ^^

If you need me to test other things hit me up.

HotCakeX commented 1 year ago

{F312195E-3D9D-447A-A3F5-08DFFA24735E}

This is for Device Guard: Virtualization Based Security

image

from LGPO.pdf file

I do get an error, saying Fast link detected, when I try to force the update with gpupdate /force and from my understanding that's because the system needs to be restarted.

https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/jj573586(v=ws.11)?redirectedfrom=MSDN

HotCakeX commented 1 year ago

Thank you for all your tests and helps,

that leaves us with 2 problems, one of them we know the answer to, the lack of IOMMU support which is required for Device Guard category to secure the system. I think it's called that on AMD systems and VT-x or VT-d on Intel CPUs.

7th gen Intel CPU from 2017 had the option in UEFI to turn on^^

what I'm worried about is the difference in languages, sure I will test other languages too, but I need to pinpoint the exact problem that causes you to get an error.

I created the security baseline x by setting policies on a fresh VM, and then back them up into GPO using LGPO.exe /b C:

HotCakeX commented 1 year ago

@innovatodev

I made a change to the script so that instead of importing the entire GPO, it now imports only the files that are necessary.

  1. registry.pol - for Machine-wide administrative templates policies
  2. GptTmpl.inf - for Machine-wide security policies

Things I don't need to import and don't configure and are omitted from this new workflow:

  1. User policies
  2. Audit policies

I totally verified this by taking a backup using Policy Analyzer, once after using the old GPO import method, and once after using the new selective import method, and compared the rule sets with Policy analyzer, everything was correct.

this new change is also better because it doesn't replace the Audit policies set by Microsoft Security Baselines.

please let me know if it solves the problem/error you were experiencing.

p.s for user-mode policies (Non-admin commands category), the script only uses PowerShell/registry, so no group policy is involved or necessary.

HotCakeX commented 1 year ago

@innovatodev I just tested the entire script on a Windows 11 22H2 with Chinese language pack installed, this is the output of GPRESULT /H GPReport.html. I reviewed it and didn't find anything problematic, but you do the same please and let me know.

image

GPReport.zip

HotCakeX commented 1 year ago

Another test on a Chinese VM:

image

innovatodev commented 1 year ago

The IOMMU refer to srv-io feature, the DMA protection need this in bios settings, i dont have it on my pc but i think, i got it on my xeon home server, but ill not be able to test this out before next week 😭 So you dont get any errors while using gpupdate /force on any of your tests ? thats nice, ill do another test with the main branch later today ! 😄

HotCakeX commented 1 year ago

The IOMMU refer to srv-io feature, the DMA protection need this in bios settings, i dont have it on my pc but i think, i got it on my xeon home server, but ill not be able to test this out before next week 😭 So you dont get any errors while using gpupdate /force on any of your tests ? thats nice, ill do another test with the main branch later today ! 😄

When I run gpupdate /force I get an error about refresh failed or something like that, when I generate a HTML report and read it, the only error I see is related to the fast link detected error and it points me to this article. so I assume whatever settings I'm applying using Group Policy, needs a proper system restart and not a forced policy refresh using that command. that's why I added a message to the end of the script so user will know to restart their system.

https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/jj573586(v=ws.11)?redirectedfrom=MSDN

I get that error on English language too. so I think we shouldn't force gpupdate according to that article. let me know if I missed something.

oh that's okay, the updated Readme page makes it clear to the user/reader that the hardware requirements of Windows 11 should be met before running this script ^^

innovatodev commented 1 year ago

But this is not windows 11 requirements, my vm has the requirements, it is more than simply the windows 11 requirements ^^ these security feature use way more things than just vt-x/amd-v, secure boot/tpm and 4 gb of ram ^^

Your script requires 8gb of ram (application guard), vt-x/amd-v + iommu (srv-io) support (thats not required by windows 11)

because my vm is 100% windows 11 compliant without cheats/bypass, and my host too.

The problem for the gpupdate do not disapear, even after 5 computer restart, but since everything is working it should not be a problem, but i think everytime the computer restart, it will create some warning event in the eventlog saying the policy {F312195E-3D9D-447A-A3F5-08DFFA24735E} get an error when updating, it is ok tho nobody is gpupdating manually on a consumer pc, but i'm a little bit more worried if you get this error too, even with iommu enabled pc.

It is clear that something works differently on en-us computer and on different lang, look : 2023_01_27_17_41_17_HardenWindows_sur_INNOVATODEV-PC_-_Connexion_à_un_ (Mapping between account names and security IDs was not done) when using it on english computer : 2023_01_27_18_06_18_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u

something about the integrated accounts/group does not work on the last policy, pretty sure we can anaylize how microsoft is doing their policies because they dont generate these messages on their import its only on the last one, just before lgpo exit 😟

also, both of my vm are not compliant for the hibernation feature, but do microsoft really recommand hibernation ? oO 2023_01_27_18_16_19_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u

Is it intended ? 2023_01_27_18_29_19_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u because i can enable it without problems, manually (the vm is compatible with it).

same for this one 2023_01_27_18_31_21_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u manually it does work, after your script it is disabled and forced

i'm not sure these are against microsoft recommandations, because both of the last feature i mention are ok and enabled if i do everything manually. 2023_01_27_18_33_28_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u 2023_01_27_18_36_49_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u

in my side, even on english systems it is not ready to use actually i cant see why microsoft would disable code integrity and tamper protection, these are really good feature (code integrity works very well against some kernel level malicious drivers, tamper protection disable most of the malicious tools trying to disable defender on registry or trying to delete/change some security registry keys by example.

This is a fully compliant hyper-v vm, with an iso downloaded with the official mediacreationtool a few hours ago

So even if the script is saying everything went ok, if i verify the settings manually under the windows security gui, it has some problems, i could try on some insider iso, but i think your goal is to also protect retail stable branch windows users, right ?

HotCakeX commented 1 year ago

Okay, well, about hardware requirements, I don't really have anything more to add about there, requirement for each feature is in the Readme page. there is nothing more I can do on my side.

Yes, Microsoft recommends Hibernate, check out the readme page. it's one of the Bitlocker countermeasures, you'll see why. Virtual machines in Hyper-V don't support hibernate. you can change that but I haven't tested the method.

Microsoft Security baselines don't disable any of those device guard features. the policies I created take full control of those features and enable them. if you want your VM to use those features, you need to enable nested virtualization for your VM and also have VT-x/VT-d/ IOMMU or their AMD equivalent on the UEFI of your actual hardware.

image image image

image

These are the results of only applying Microsoft Security Baselines + Security Baselines X. you need to restart your VM or computer to see the changes in the Windows Security app.

you said your hardware doesn't support IOMMU, this is a problem because it's needed for Device Guard and Security baselines to work properly.

in the screenshots above, you can see Firmware protection is turned off in the VM Windows Security app, that's because my real hardware doesn't support System Guard Secure Launch and SMM protection, so the hypervisor can't pass those security features to the VM.

The System information screenshot and details shown in there confirm that the Device Guard features are being applied correctly.

you mention an error about gpupdate, could you tell me where I can find it in the Event Viewer? the ID and category.

what is the reason for force updating Group Policies anyway? MSFT says they have Asynchronous and synchronous processing workflow, so best thing is to restart the system after using the script and let everything do their jobs naturally.

HotCakeX commented 1 year ago

by importing only registry.pol and GptTmpl.inf I'm doing it the same way as Microsoft's PowerShell script, aren't I? I'll take a look at the PowerShell script from security baselines again

HotCakeX commented 1 year ago

A note about Hibernate vs sleep vs modern standby.

from a security and convenience standpoint, if your hardware supports Modern Standby, use that instead of Sleep or Hibernate.

Modern Standby is what being used in Xbox Series X/S too.

Modern Standby prevents malicious users from modifying system files etc. in a malicious way because Windows Defender will be running at all times. Hibernate would allow user to put the computer in Hibernate state where everything will be saved on the disk, then user can change the state of the hibernate file and modify it and boot again with the embedded code. that's why in Guarded Hosts for HGS, Hibernation is disabled.

innovatodev commented 1 year ago

Nested virt is enabled by the way, i can even create a windows 11 vm into my already virtual windows 11 and it will boot to desktop without any problems ^^ thats why i dont understand why we got such different returns after running the script (if nested was not enabled, hyperv would not even install at all) 2023_01_27_19_59_54_Administrator_PowerShell

Yes there no reason to force the updates, but i can do as many restart as i want, tamper protection and code integrity will stay disabled, only error i see while running the script on the english one is the hibernation, everything else is correctly added without errors, but code integrity and tamper are still off and managed by administrator.

Thats so strange haha look at this 2023_01_27_20_05_32_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u thats after 3 reboots.

Ok i understand for the hibernate/sleep, if i understand, no sleep/hibernate > hibernate > sleep ? i never used any of these sleep features, i shutdown my pc, hibernate/sleep was good in the hdd world to save an entire minute, but since a long time now, any modern system will start from cold in 5 secs to the desktop, there no points to use any of these anymore, no ?

Ok so, in my system informations, its blank 😿 2023_01_27_20_11_40_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u

Event error is in Microsoft-Windows-GroupPolicy (Applications > Microsoft > Windows > GroupPolicy) ID 7016 will trigger at each reboot. And a ID 6033 Warning 2023_01_27_20_17_38_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u

The mitigationOptions also got an error when the script run but that will not happens at each reboot so its ok i think ^^

2023_01_27_20_19_30_HardenWindowsEN_sur_INNOVATODEV-PC_-_Connexion_à_u

thats really weird, because if i do manually most of the setting under windows security, it will work without problems

HotCakeX commented 1 year ago

Shut down/Hibernate/Modern Standby are equally good, just not sleep ^^

I use Hibernate even though I have SSD, because most of the time I'm working on something or VMs are running, I just Hibernate so that I can later continue my work instead of closing all programs.

thanks for the screenshots, what you see in Windows Security app and System information are consistent. I have an idea for you to try. roll back your VM to the clean state, then go to group policy and enable Device Guard features one by one, after turning on each of them, restart the VM, then see the changes and take notes. that should help you identify which one is having compatibility issue. (I suspect Memory Attribute Table, but we will see)

Thanks for the Event Viewer details, I'll check them out and report back :)

innovatodev commented 1 year ago

Yeah, i will try to apply one by one into policies manually and we will see who's the bad boy 😃

HotCakeX commented 1 year ago

You can also use this that I've linked to in Readme page, it's a PowerShell script.

Windows Defender Device Guard and Windows Defender Credential Guard hardware readiness tool https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/dg-readiness-tool

innovatodev commented 1 year ago

2023_01_27_21_56_13_WindowsHarder_sur_INNOVATODEV-PC_-_Connexion_à_un_

so ... even iommu works well finally lol

2023_01_27_22_00_54_WindowsHarder_sur_INNOVATODEV-PC_-_Connexion_à_un_

everything is enabled and running using the script from https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/dg-readiness-tool and memory integrity is working fine 2023_01_27_22_02_39_WindowsHarder_sur_INNOVATODEV-PC_-_Connexion_à_un_

but whenever i force it with the group policy, it will break both device guard and memory integrity, even if i do it manually.

its something to do with the DMA because every other option works 2023_01_27_22_25_10_WindowsHarder_sur_INNOVATODEV-PC_-_Connexion_à_un_

so i can use any of the compliance features, just dma kernel protection will not work, not too bad.

Still, i'm happy it works well if the user's host is dma compliant, ill have to find why this microsoft script say i'm iommu OK when it appear its not haha ... Happy powershelling, cant test more for you since my pc cant handle this thicc script entirely😆

HotCakeX commented 1 year ago

So, you're suggesting I add that PowerShell script to mine so it will run automatically?

or maybe should warn users about not forcing Group Policy update with that command and only use system restart?

honestly, I've mostly seen suggestions about using gpupdate /force command in old blog posts. if it was really necessary, Microsoft Security Baseline would run it automatically, but instead, it tells user to do a reboot.

Oh, DMA Kernel protection requires new hardware only, like at least Intel 10th gen or AMD equivalent. it also doesn't require manual enablement, it's automatically enabled on supported hardware.

How to check if Kernel DMA Protection is enabled Systems running Windows 10 version 1803 that do support Kernel DMA Protection do have this security feature enabled automatically by the OS with no user or IT admin configuration required.

that is why the script or Group Policy doesn't touch that.

however, the script enables Bitlocker's DMA protection if it detects Kernel DMA protection is unavailable.

Another feature that you can't use is Kernel Mode Hardware Enforced Stack Protection

There is a hardware dependency for this new feature that requires Intel Tiger Lake and beyond or AMD Zen3 and beyond.

Thank you so much for all the tests and helps so far, they've been very valuable!

you think the script is thicc and heavy now that it uses Microsoft Security Baseline? xD