Hunting and Decrypting EFS Encrypted Files

At home last week, I started doing some preparations for upgrading my home server from Windows Server 2012 R2 to Windows Server 2016. This server was originally installed using Windows Server 2012 R2 Essentials and since, I have performed a Standard edition, edition upgrade on the machine which means that the host has ADDS, ADCS, NPS and some other roles installed as part of the original Essentials server installation. We all know that unbinding ADDS and ADCS can be a bit of a bore which is why nobody in the age of virtualization should be installing ADDS and ADCS on a single server together but that’s by the by.

When I started looking at decommissioning the ADCS role, I noticed that an EFS certificate had been issued to my domain user account. I’ve never knowingly used EFS but the presence of a certificate for that purpose lead me to believe there may be some files out there so I started looking.

EFS was a technology that appeared circa Windows XP to allow users to encrypt files before BitLocker was a thing. It was a nice idea but it was troubled and flawed in that it was enabled by default and users could self-encrypt files without IT having implemented the proper tools to allow them to recover the files when disaster struck.

Read the Full Post

Hyper-V Replication Firewall Rules on Nano Server

Nano Server is the newest edition in the Windows Server family and because of it’s ultra-low footprint and patching requirement, makes it an ideal Hyper-V host for running your private cloud infrastructure.

One of the resiliency features in Hyper-V, Hyper-V Replicas allows you to replicate a VM on a timed interval of as low as 30 seconds. This isn’t a new feature but is a great one none-the-less and is ideally suited to organisations with multiple data centres wanting to protect their VMs across two or more sites without the need for expensive SAN replication technologies.

Nano Server ships by default with the Windows Firewall enabled and there are two rules for Hyper-V Replicas which are both disabled by default. If you want to use Hyper-V Replica, even once you’ve configured everything you need via the Hyper-V Manager console or via PowerShell such as virtual networks and enabling the Hyper-V Replica feature, you will still need to configure this rule.

Read the Full Post

Modifying the Nano Server Pagefile

This weekend, I’ve been working on a little pet project using an ultra-small form factor PC that I’ve got setup running Nano Server and Boot from VHD.

The setup is great and ideal for my use case however there is a problem when using Boot from VHD and that is that the operating system you are booting cannot host a pagefile inside the VHD file. When you boot a PC using a native boot VHD file, the pagefile will be automatically created on the physical partition with the most available free space and set to System Managed which means that the pagefile will swell and shrink according to demand and not perhaps on the disk or partition you want it to be on.

I started the journey trying to modify the pagefile configuration however I quickly discovered that even the PowerShell Cmdlets recommended by many other people online to use with Server Core don’t work because they rely on using WMI to modify the parameters and if you try these, you’ll very quickly find that Nano Server only accepts and extremely small subset of WMI PowerShell Cmdlets, presumably down to the compressed WMI database in Nano.

Luckily, I found one set of Cmdlets that do work on Nano Server and allows you to configure your pagefile as you desire.

Set-CimInstance -Property @{AutomaticManagedPageFile = $False}

$PageFile = Get-CimInstance -ClassName Win32_PageFileSetting
$PageFile | Remove-CimInstance

New-CimInstance -ClassName Win32_PageFileSetting -Property  @{Name= "$("P"):\pagefile.sys"}
Get-CimInstance -ClassName Win32_PageFileSetting | Set-CimInstance -Property @{InitialSize = 4096; MaximumSize = 4096}

As you’ll see, I’m using P as my pagefile drive volume and I’m setting the initial and maximum sizes to 4096MB. Simply change these to suit your needs and job’s a good one.

Setting PowerShell as the Default Shell in Server Core

As part of a little weekend project I’ve embarked on this week, I’ve built myself a pair of new Domain Controllers for my home AD environment running on Server Core. Not only does using Server Core for Domain Controllers make great sense because they take up less resources (CPU, Memory and Storage) but they also need less patching which means we can keep them up more often. Sure, it would be nice to be able to use Nano Server for Domain Controllers but least in Technical Preview 5 at the time of writing, this isn’t a role that’s available. DNS is but AD isn’t and hopefully it will come.

Living in the present though, with Windows Server 2012 R2 and Server Core being the best we can do for Active Directory, there is a problem that most people will notice when they start using Server Core and that is that it uses Command Prompt as it’s default shell. This means that if you want to use any PowerShell Cmdlets, you need to step up to PowerShell first. I know this doesn’t seem like a hardship but if you do it enough, it gets tiresome, especially when you think that the Active Directory Cmdlets all live in PowerShell.

Luckily, we can fix this and make PowerShell the default shell in Server Core. If you’ve only got one server to do this against then the easiest thing to do it do it manually but if you’ve got a larger estate of Server Core machines, you can go it with Group Policy Preferences too.

Setting PowerShell as the Default Shell Manually

If you’ve only got one server, a couple of servers or maybe your Server Core machines are workgroup members so you can’t use Group Policy and if any of these are true, the manual method is for you. It’s a simple PowerShell one-liner:

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name Shell -Value 'PowerShell.exe -NoExit'

 Setting PowerShell as the Default Shell via Group Policy

As I mentioned, we can use a Group Policy Object to ensure that all of our Server Core machines get PowerShell as their default shell.

The first step is to setup a WMI Filter in Active Directory to detect Server Core machines and the second is to create and link the GPO itself. To create a new WMI Filter, using Group Policy Management Console create a new WMI Filter. Name it whatever you chose but I called mine Windows Server 2012 R2 Server Core Only. For the query itself, use the following WMI Query:

SELECT InstallState FROM Win32_OptionalFeature WHERE (Name = "Server-Gui-Shell") AND (InstallState = "2")

To break it down, this queries WMI in the Win32_OptionalFeature class and grabs the InstallState property. It then checks to see whether InstallState is equal two for the Server-Gui-Shell value. In Windows server 2008 and 2008 R2, this was a little easier as Server GUI and Server Core identified themselves as different SKUs of the operating system however because Windows Server 2012 R2 allows us to install and uninstall the GUI as a feature that means there isn’t a different in the SKU so the way to tell the two apart is the installation state of the Server-Gui-Shell feature. On a server with a GUI, this will equal 1 and on a server without the GUI this will equal 2.

With the WMI Filter now created, we can create the GPO itself. Create a new GPO and configure it to use the WMI Filter we just created. Once created and filtered, open up the GPO Editor so that we can add our setting.

With the GPO Editor, expand Computer Configuration Preferences Windows Preferences Registry. Right-click the Registry node on the left and select New Registry Item and configure the registry item as follows:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
Value Name: Shell
Value Type: REG_SZ
Value Data: PowerShell.exe -NoExit

Once you set this, hit OK and you’re done. Link the GPO to an OU in your Active Directory hierarchy that contains your servers and once it has applied, you’ll start to get PowerShell as your default prompt when you logon. Because the WMI Filter only applies to Server Core machines, it’s safe to link this GPO to a root OU that contains all of your servers so that when any Server Core machines get dropped in, they will automatically pick this GPO up.

Cleaning Up Active Directory and Cluster Computer Accounts

Recently at work, I’ve been looking at doing a clean up of our Active Directory domain and namely removing stale user and computer accounts. To do this, I short but sweet PowerShell script which gets all of the computer objects from the domain and include the LastLogonTimestamp and the pwdLastSet attributes to show when the computer account was last active however I came across an interesting problem with cluster computer objects.

Import-Module ActiveDirectory
Get-ADComputer -Filter * -SearchBase “DC=domain,DC=com” -Properties Name, LastLogonTimestamp, pwdLastSet -ResultPageSize 0 | Select Name, @{n='LastLogonTimestamp';e={[DateTime]::FromFileTime($_.LastLogonTimestamp)}}, @{n='pwdLastSet';e={[DateTime]::FromFileTime($_.pwdLastSet)}}, DistinguishedName

When reviewing the results, it seemed as though Network Names for Cluster Resource Groups weren’t updating their LastLogonTimestamp or pwdLastSet attributes even though those Network Names are still in use.

After a bit of a search online, I found a TechNet Blog post at http://blogs.technet.com/b/askds/archive/2011/08/23/cluster-and-stale-computer-accounts.aspx which describes exactly that situation. The LastLogonTimestamp attribute is only updated when the Network Name is brought online so if you’ve got a rock solid environment and your clusters don’t failover or come crashing down too often, this object will appear as although it’s stale.

To save you reading the article, I’ve produced two updated versions of the script. This first amendment simply adds the servicePrincipalName column to the result set so that you can verify them for yourself.

Import-Module ActiveDirectory
Get-ADComputer -Filter * -SearchBase “DC=domain,DC=com” -Properties Name, LastLogonTimestamp, pwdLastSet, servicePrincipalName -ResultPageSize 0 | Select Name, @{n='LastLogonTimestamp';e={[DateTime]::FromFileTime($_.LastLogonTimestamp)}}, @{n='pwdLastSet';e={[DateTime]::FromFileTime($_.pwdLastSet)}}, servicePrincipalName, DistinguishedName

This second amended version uses the -Filter parameter of the Get-ADComputer Cmdlet to filter out any results that include the MSClusterVirtualServer which designates it as a cluster object computer account.

Import-Module ActiveDirectory
Get-ADComputer -Filter 'servicePrincipalName -NotLike "*MSClusterVirtualServer*"' -SearchBase “DC=domain,DC=com” -Properties Name, LastLogonTimestamp, pwdLastSet, servicePrincipalName -ResultPageSize 0 | Select Name, @{n='LastLogonTimestamp';e={[DateTime]::FromFileTime($_.LastLogonTimestamp)}}, @{n='pwdLastSet';e={[DateTime]::FromFileTime($_.pwdLastSet)}}, DistinguishedName

The result set generated by this second amendment of the script will produce exactly the same output as the original script with the notable exception that the cluster objects are automatically filtered out of the results. This just leaves you to ensuring that when you are retiring clusters from your environment that you perform the relevant clean up afterwards to delete the account. Alternatively, you could use some clever automation script like Orchestrator to manage the decommissioning of your clusters and include this as an action for you.