If you’ve seen the following 3 words in recent updates like KB4025342, don’t panic,…

…keep calm and read the CVE-2017-8565 on the new security updates guide portal

Yes, CVE-2017-8565 was published on July 11, 2017.

Oleksandr Mirosh and Alvaro Muñoz from Hewlett-Packard Enterprise Security reported this vulnerability as far as we can see on the acknowledgments page.

On the following page, you can read a good description of the issue:

A remote code execution vulnerability exists in PowerShell when PSObject wraps a CIM Instance. An attacker who successfully exploited this vulnerability could execute malicious code on a vulnerable system.

In an attack scenario, an attacker could execute malicious code in a PowerShell remote session.

The update addresses the vulnerability by correcting how PowerShell deserializes user supplied scripts.

The above page states it’s a Remote Code Execution (RCE) vulnerability and I guess it’s because Remoting is involved in the attack scenario.

Here’s why I don’t 100% agree with this classification:
First, let’s quickly examine who can access remoting on a Windows 10 1703 workstation with the Get-PSSessionConfiguration cmdlet

  • NT AUTHORITY\INTERACTIVE (S-1-5-4) are Users who log on for interactive operation. This is a group identifier added to the token of a process when it was logged on interactively. The corresponding logon type is LOGON32_LOGON_INTERACTIVE. (source)
  • BUILTIN\Administrators (S-1-5-32-544)
    A built-in group. After the initial installation of the operating system, the only member of the group is the Administrator account. When a computer joins a domain, the Domain Admins group is added to the Administrators group. When a server becomes a domain controller, the Enterprise Admins group also is added to the Administrators group (source)
  • BUILTIN\Remote Management Users (S-1-5-32-580) A Builtin Local group. Members of this group can access WMI resources over management protocols (such as WS-Management via the Windows Remote Management service). This applies only to WMI namespaces that grant access to the user. (source)

Based on the 3 groups listed above who can connect via remoting, either you already are an admnistrator of the box or are logged interactively (you’re an admin or a standard user) and/or belong to the local BUILTIN\Remote Management Users group.

If you’re not already an administrator, you could eventually become one by exploiting the CVE-2017-8565 vulnerability through remoting sessions.
In this case, I’m more likely to call this kind of a vulnerability an Elevation of Privilege (EoP) than a Remote Code Execution (RCE).


Invoking code via PowerShell Remoting is the prime purpose of PowerShell Remoting


Now let’s say, other remoting configurations were added because you’ve implemented JEA (Just Enough Administration) or constrained remoting endpoints with a RunAs account (a privileged account) to delegate access to some (less privileged) remote users (typically helpdesk members).
Again a less privileged remote user who was given access to a (vulnerable) remoting configuration/session could gain more privileges by exploiting this vulnerability.

We can see more details about this vulnerability in PowerShell Core. The beauty of open source projects is that they tend to be more transparent and agile in fixing bugs.

The issue with CIM deserializer was introduced in the PowerShell Core github repository the day after the security updates were released for regular Windows versions of PowerShell.
And it was fixed in about 3 days.
You can see the related merged Pull Request using this link.

I’ve tested this vulnerability on Windows 10 1703 fully patched where KB4025342 was installed. Importing the corrupted CIM class didn’t spawn a calculator process.

I’ve removed KB4025342 and restarted the computer

wusa.exe /uninstall /kb:4025342 /norestart

Importing the corrupted CIM class launched a calculator process. Its integrity was labeled “AppContainer” and has actually a lower integrity level than its parent process (wsmprovhost.exe) level set to medium (as I run as a standard user).

Importing the corrupted CIM class has the same result as doing the following already allowed:

Invoke-Command -ComputerName . -EnableNetworkAccess { calc.exe }

No elevation of privilege so far.

Now, let’s say I add a somehow quite restricted endpoint (allowing only import-clixml and access to the filessystem provider)

$HT = @{
 SchemaVersion = '1.0'
 ExecutionPolicy = 'Restricted'
 SessionType = 'RestrictedRemoteServer'
 LanguageMode = 'NoLanguage'
 VisibleCmdlets = 'Import-Clixml'
 VisibleProviders = 'FileSystem'
 RunAsVirtualAccount = $true
New-PSSessionConfigurationFile -Path C:\config.pssc @HT
Register-PSSessionConfiguration -Path 'C:\config.pssc' -Name "Test" -Force

Importing the corrupted CIM class results in the ability to escape the constrained endpoint restrictions – the “sandbox” – and run arbitrary code under a more privileged account. You can see that wsmprovhost.exe runs under a WinRM virtual user, has a High integrity level and has two child processes that inherited from its security context (cmd.exe and openwith.exe triggred by trying to run calc):

In my opinion, there’s no need to panic.
Arbitrary code can only run in a higher security context only in some specific scenarios.
This vulnerability can be easily remediated by just applying already available Windows security updates.

On a Windows 7, only Administrators can connect through remoting by default:

How do I update VScode

Whenever I see a twitter post from @code saying
, I know it’s time to update my local copy of VSCode 😀

So, I open my (saved) code snippet and run the following
Disclaimer: use at your own risk, it’s not a function or a module. I only need some level of automation but not full automation 😛

if (-not(Test-Path ~/Downloads/VSCode -PathType Container)) {
Write-Warning 'Folder ~/Downloads/VSCode not found'
if (Test-Path ~/Downloads/VSCode/ {
Write-Warning -Message 'Zip file found in ~/Downloads/VSCode/'
# version in prod
$localver = (Get-Item -Path 'C:\Program Files (x86)\Microsoft VS Code\Code.exe' -ErrorAction SilentlyContinue).VersionInfo.FileVersion
Write-Verbose -Message "Local version in program files $($localver) detected" -Verbose
# new online version
$uri = ''
$onlineloc = (Invoke-WebRequest -Uri $uri -MaximumRedirection 0 -ErrorAction SilentlyContinue -UseBasicParsing).Headers.Location
Write-Verbose -Message "Online location found at $($onlineloc)" -Verbose
$onlinever =([regex]'VSCode-win32-(ia32-)?(?<Version>(\d{1,}\.){1,3}\d{1,})\.zip').Matches(
if ([version]$localver -eq [version]$onlinever) {
Write-Verbose -Message "Already up-to-date: $($localver)" -Verbose
} else {
Write-Verbose -Message "You need to update your local version $($localver) to $($onlinever)" -Verbose
Write-Verbose "About to download online version $($onlinever)" -Verbose
Invoke-WebRequest -Uri $onlineloc -OutFile ~/Downloads/VSCode/
if (Test-Path ~/Downloads/VSCode/ {
# rename folder
if (Test-Path ~/Downloads/VSCode/VSCode-win32-stable) {
Rename-Item -Path ~/Downloads/VSCode/VSCode-win32-stable -NewName ('VSCode-win32-stable-{0}' -f (
dir "~/Downloads/VSCode/VSCode-win32-stable/Code.exe").VersionInfo.FileVersion
) -Verbose
# expand zip
Expand-Archive -Path ~/Downloads/VSCode/ -DestinationPath ~/Downloads/VSCode/VSCode-win32-stable -Force
# new version?
(Get-Item -Path '~/Downloads/VSCode/VSCode-win32-stable/Code.exe').VersionInfo |
Select FileVersion,ProductVersion
# signed?
dir '~\Downloads\VSCode\VSCode-win32-stable\*' -Include *.exe,*.dll -Recurse -Force -ErrorAction SilentlyContinue|
# push to prod
& (gcm "$($env:systemroot)\system32\robocopy.exe") @(
'C:\Program Files (x86)\Microsoft VS Code','/R:0','/Z','/S','/PURGE','/NP'
# ren zip
Rename-Item -Path ~/Downloads\VSCode\ -NewName ('VSCode-win32-stable-{0}.zip' -f (
dir "~/Downloads/VSCode/VSCode-win32-stable/code.exe").VersionInfo.FileVersion
) -Verbose
# enjoy!
& 'C:\Program Files (x86)\Microsoft VS Code\Code.exe'

WSUS (bundled or installable) child updates

This morning there was question on about how to find if the following .Net Rollup update (4019112) has been installed.

The person approved 4019112 but noticed that the WMI Win32_QuickFixEngineering class didn’t list it.
Instead it contained the following updates KB4014504 and KB4014511 that are actually bundled inside the rollup 4019112

The person was also asking if there’s another way to find what child updates an update installs instead of what’s listed on its support page.

Yes, there is one. If you use the WSUS API GetInstallableItems method. It will list what child updates an update will install (more precisely, it will get the directly bundled, non-explicitly-deployable child updates of this update. Creates an installable item on behalf of this update if the update itself has files.)

(Get-WsusServer).SearchUpdates('4019112') |
Out-GridView -PassThru -Title 'Select an update'| 
ForEach-Object { 
} | ft -AutoSize

As you can see the KB4019112 (logically) bundles an update for every supported version of .Net.

Unfortunately, we couldn’t use the GetRelatedUpdates method and its enum UpdatesBundledByThisUpdate that should also list child updates that are bundled in this update.

# what's the numeric value of the UpdatesBundledByThisUpdate enum

(Get-WsusServer).SearchUpdates('4019112') | 
ForEach-Object {
 $_ | 
 Add-Member -MemberType ScriptProperty -Name UpdatesBundledByThisUpdate -Value {
 } -Force -PassThru
} | Select Title,UpdatesBundledByThisUpdate | 
Out-GridView -PassThru | Select -ExpandProperty UpdatesBundledByThisUpdate

As you can see, it doesn’t return anything. Why?


Well, because the above two searches also don’t return anything.
It means that these updates don’t exist as individual updates in WSUS.

To find out if the .Net rollup 4019112 has been installed on a target computer you can either:

# use the Get-HotFix cmdlet
Get-HotFix -Id 'kb4014504','kb4014508','kb4014511','kb4014514'
# or the  Get-WmiObject cmdlet
Get-WmiObject -Query 'Select * FROM Win32_QuickFixEngineering WHERE HotFixID = "KB4014504" OR HotfixID = "KB4014508" OR HotfixID = "KB4014511" OR HotFixID = "KB4014514"'