Microsoft Office Security – Disable Macros

Executable code embedded within Office documents continues to be a popular way to deliver malware.

Office, by default, opens files downloaded from the internet in a safe way, that prompts the user to first enable editing, and then again to enable to macro content. I’m sure everyone has seen this before:


followed by:

You could be just one click away from ruining your day, and potentially at whole lot more people’s too…

Social engineering is often used to try to get you to enable the blocked content, usually by pretending that there’s hidden or encrypted information in the file that requires you to click those “enable” buttons. Microsoft Threat Intelligence Center’s John Lambert has created a compilation of screenshots of lots of these – quite an eye opener, and useful for staff training.

Sometimes, IT admins are forced to disable the protection features due to pressure from users who are annoyed with stuff not working “how it used to” or having to click through too many security checks. Sometimes, they don’t think to force the Office products to display the warnings, and leave the Trust Center settings available for users to change themselves (i.e. turn off).

As with many things macros can be of huge benefit, but if their use isn’t essential, just disabled them. If nobody needs them, nobody will notice if the functionality isn’t there. This advice is just common sense (right?) but if you don’t believe me, believe Microsoft – they say the same thing. As do the UK’s National Cyber Security Centre.

You have several options, and the two I’m going to show you require the latest Office Group Policy Templates, so download those if you’ve not already got them and put them into your central store for group policy (you are using one of those, right?).

Block macros from running in Office files from the Internet

In Office 2016 Microsoft included this new feature that you can enable via Group Policy. It’s available for Word, Excel and PowerPoint, and allows you to disable macros where Office detects that the file has come from the internet, be that downloaded via a web browser or from external email. They liked it so much, they even backported it to Office 2013 too.

In the Group Policy Management Editor, go to User configuration > Administrative templates > Microsoft Word 2016 > Word options > Security > Trust Center. Open the Block macros from running in Office files from the Internet setting to configure and enable it.

The effect for the end user is the red/pink bar in the following image:

Disable VBA for Office applications

This is the ultimate, just disable the Visual Basic for Applications functionality for the whole of Office. No more macros, or any other VBA stuff. This is done via the following Group Policy setting:

Computer or User Configuration > Administrative Templates > Microsoft Office 2016 > Security Settings.
Enable the setting Disable VBA for Office applications.

Office then displays the following when anything tries to access VBA functionality:

Hopefully you’ve found this a useful, practical guide to increasing your security.

Advertisements
Posted in Applications, Office 365, Security | Tagged , , , , , , | Leave a comment

Easy Group Policy Update from Start Menu

Save yourself and your users time and frustration by implementing this Start Menu shortcut to help them run a Group Policy update quickly and easily.

This is handy if you deploy network drives, printers, etc. to your users automatically via Group Policy. If for any reason they’re missing when the user logs on to Windows, they can usually make them appear just by getting the Group Policy processed again.

Once implemented, users can just click Start and type “group”, “policy”, or “update” to make the shortcut show up, or find it under “G”.

The shortcut then runs a gpupdate /force (why would you ever NOT do /force?), and pauses for a key to be pressed so that you or your user can verify that the updates completed successfully:

How to do it

  1. Open Group Policy Management Console (gpmc.msc), and navigate to a GPO that applies to the computers (or users) that you want to put the shortcut onto. I’m deploying this to the computer, and putting it into the All Users Start Menu, so that I only have one copy of it on the machine, rather than a copy in every user profile.
  2. Go to Computer Configuration, Preferences, Windows Settings, Shortcuts.
  3. Right-click and create a new shortcut with the following settings:
Action:      Replace
Name:        Group Policy Update
Target Type: File System Object
Location:    All Users Start Menu
Target:      %WindowsDir%\System32\cmd.exe
Arguments:   /c title Group Policy Update & gpupdate /force & pause
Start in:    %WindowsDir%\System32
Icon file path: %SystemRoot%\System32\SHELL32.dll
Icon index:  46

Then on the Common tab you can tick the box for Remove this item when it is no longer applied. This is why I chose the Replace action, rather than Update. Just in case you ever want to easily remove this from your machines – just remove the shortcut from the GPO and the icon will go from your machines too.

You can obviously change the icon to whatever else you want.

Posted in Windows | Tagged , , , , , , , , | Leave a comment

What is Cyber Essentials?

Cyber Essentials

Cyber Essentials (CE) is a UK government scheme that organisations can (and in some cases, must) use to certify a basic level of both IT security awareness and cyber-health. It’s mostly interested in technical controls to mitigate specific, common, cyber threats.

It is thus unlike certifications such as ISO 27001 which are more concerned with identification of risk, and allow for that risk to be mitigated in non-technical ways, e.g. with policy documents that users have to be made aware of. To take a common example, Cyber Essentials states that you mustuse administrative accounts to perform administrative activities only (no emailing, web browsing or other standard user activities that may expose administrative privileges to avoidable risks)“. Thus it’s no good if your users do log on with administrator-level accounts on a daily basis to perform those activities – it doesn’t matter if you’ve identified that as an acceptable business risk. You cannot pass CE if that is how you’re currently operating your IT.

I have been doing a fair amount of assessing and testing for both CE and CE+ recently, and thought some of the knowledge I have accrued might be of use to people who are considering getting certified. I have spent many (18) years designing and running large enterprise IT environments, and the last few years working for a cyber security training and consultancy company doing increasing amounts of security-related work. I am Tiger Scheme certified as a Qualified Security Team Member, which is a UK government penetration testing certification.

Cyber Essentials, if you ask the wrong people (i.e. security and IT product vendors) can be a licence to sell you all kinds of new hardware/software/devices, whereas in reality it’s often relatively easy to comply with what you almost certainly already have – albeit potentially with a few changes to your working practices. You probably know the things you’re currently doing that are bad and CE might just be the prod you need to get them changed.

Look out for further articles where I’ll explain how to get CE certified for no extra charge (except the certification fee!)

Get Certified

Once your IT and business practices comply with all the requirements for Cyber Essentials, getting certified is simply a case of selecting a suitable Certification Body, filling in a form and paying a fee of a few hundred pounds. Assuming you’re in compliance with the requirements, and you hopefully won’t fill out the form unless you know you are, you’ll shortly be awarded your certificate, be allowed to use the Cyber Essentials logo, and be added to the publicly searchable directory. Your certification lasts for 12 months, so just before your existing certification expires you need to go through the process again, ensuring you’ve kept up to date with any new or changed requirements.

You might want to consider contacting my employers, PGI, for a quote for certification and/or consultancy.

Plus

Cyber Essentials Plus is an enhanced level of certification, where you not only have to say that you comply with the requirements for CE, but you also get tested to ensure that you comply. This testing includes vulnerability scans of your internal and external infrastructure, and mobile devices. It is more expensive because you have to pay for a consultant to do the testing, some of which necessarily involves them being on site with you for a day or so. Note that this does not include a full penetration test: a vulnerability scan, as its name implies, just scans for vulnerabilities (e.g. missing security updates, misconfigured security settings), it does not try and exploit them.

CE+ is a bit like a cyber MOT for your organisation. It’s a reasonably standard set of tests that, if you’re in compliance, means you’re doing the basics right.

Required?

Sometimes, it can be a requirement to have CE or CE+. For example, the UK government requiresall suppliers bidding for certain sensitive and personal information handling contracts to be certified against the Cyber Essentials scheme“.

Is it for me?

CE is for everyone, from a sole trader to a large company. CE gives your customers and other organisations that you interact with a sense of reassurance that when it comes to cyber security, you’re getting the basics right – and are thus potentially safer to deal with than your competition.

I’ve also seen CE+ used by company directors as an easy and relatively inexpensive way to audit that their (often outsourced) IT is being managed sensibly when it comes to cyber security. Used in this way, it’s then giving a double benefit of being a good standardised benchmark to meet, and also getting a recognised certification.

More information?

For starters, if you’re even slightly technical (i.e. can use a computer for internet-based activities) you should really check out the Requirements for IT Infrastructure. You can also check out all the other information on the Nation Cyber Security Centre’s Cyber Essentials website. NCSC is part of GCHQ – they know what they’re talking about when it comes to Cyber stuff.

You can also ask me for advice either via the Hire Me link at the top, or by leaving a comment. You could also check out the PGI Cyber Essentials page – mention my blog if you contact them!

Posted in Business, Security | Tagged , , , , , , , , , , , , , , , , , , , , , | Leave a comment

Meltdown and Spectre – My update experiences on Windows

I’m intending to keep adding to this post as I find out new things and update more devices. This is primarily to aid me in tracking things I’ve done, what’s changed, and what’s still to do. Hopefully others might find some of this useful too.

Work laptop

My work laptop is a Dell Latitude E7450 with an Intel Core i7-5600U CPU and is running Windows 10 LTSB 2016 (1607), Kaspersky Endpoint Security 10 10.2.5.3201 and MalwareBytes AntiMalware 1.80.2.1012.

Kaspersky is compatible with the Windows Security Update as of a database update released on 28th December 2017, and MalwareBytes is compatible as of a database update released on 4th Jan 2018.

Running multiple AntiMalware products potentially causes the “I am compatible” registry value to not work properly – one product might not be compatible but if the other is and sets the value you could end up with bluescreens after installing the security update. Luckily both mine are compatible, and one of other of them set the registry value, which I checked via RegEdit.
The presence of a DWORD value called cadca5fe-87d3-4b96-b7fb-a231484277cc and set to 0 indicates that the AntiVirus product is compatible with the update. Interestingly, my machine has that value, but it also has a subkey called cadca5fe-87d3-4b96-b7fb-a231484277cc and with the default value set to 0. I have other machine that only have Kaspersky on and these also have the value and the subkey present so I think it’s Kaspersky doing this not MalwareBytes.

I’ve installed the KB4056890 update on this machine (via WSUS) but it’s not rebooted yet. Prior to installing the update I ran the PowerShell command Get-SpeculationControlSettings and it returned the following:

PS Scripts:\> Install-Module SpeculationControl

Untrusted repository
You are installing the modules from an untrusted repository. If you trust this repository, change its
InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to install the modules from
'PSGallery'?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"): y
PS Scripts:\> Get-SpeculationControlSettings
Speculation control settings for CVE-2017-5715 [branch target injection]

Hardware support for branch target injection mitigation is present: False
Windows OS support for branch target injection mitigation is present: False
Windows OS support for branch target injection mitigation is enabled: False

Speculation control settings for CVE-2017-5754 [rogue data cache load]

Hardware requires kernel VA shadowing: True
Windows OS support for kernel VA shadow is present: False
Windows OS support for kernel VA shadow is enabled: False

Suggested actions

 * Install BIOS/firmware update provided by your device OEM that enables hardware support for the branch target injection mitigation.
 * Install the latest available updates for Windows with support for speculation control mitigations.
 * Follow the guidance for enabling Windows support for speculation control mitigations are described in https://support.microsoft.com/help/4072698


BTIHardwarePresent             : False
BTIWindowsSupportPresent       : False
BTIWindowsSupportEnabled       : False
BTIDisabledBySystemPolicy      : False
BTIDisabledByNoHardwareSupport : False
KVAShadowRequired              : True
KVAShadowWindowsSupportPresent : False
KVAShadowWindowsSupportEnabled : False
KVAShadowPcidEnabled           : False

After a reboot, the above cmdlet now returns the following information:

> Get-SpeculationControlSettings
Speculation control settings for CVE-2017-5715 [branch target injection]

Hardware support for branch target injection mitigation is present: False
Windows OS support for branch target injection mitigation is present: True
Windows OS support for branch target injection mitigation is enabled: False
Windows OS support for branch target injection mitigation is disabled by system policy: False
Windows OS support for branch target injection mitigation is disabled by absence of hardware support: True

Speculation control settings for CVE-2017-5754 [rogue data cache load]

Hardware requires kernel VA shadowing: True
Windows OS support for kernel VA shadow is present: True
Windows OS support for kernel VA shadow is enabled: True
Windows OS support for PCID optimization is enabled: True

Suggested actions

 * Install BIOS/firmware update provided by your device OEM that enables hardware support for the branch target injection mitigation.
 * Follow the guidance for enabling Windows support for speculation control mitigations are described in https://support.microsoft.com/help/4072698


BTIHardwarePresent             : False
BTIWindowsSupportPresent       : True
BTIWindowsSupportEnabled       : False
BTIDisabledBySystemPolicy      : False
BTIDisabledByNoHardwareSupport : True
KVAShadowRequired              : True
KVAShadowWindowsSupportPresent : True
KVAShadowWindowsSupportEnabled : True
KVAShadowPcidEnabled           : True

This machine is running the latest available BIOS from Dell, so I’ll have to wait for a new BIOS to be able to get the updated CPU microcode to enable the hardware support (I assume).

Home PC

This has an AMD FX-8350 CPU and is running Windows 10 1709, Windows Defender, and MalwareBytes 3.2.2.2029. It had not been switched on since 3rd Jan. I turned it on on the evening of 5th Jan, and after updating the database for MalwareBytes, the registry value to enable the Windows Update to install was not present. I then updated Windows Defender’s threat definitions, the version is now 1.259.1223.0 and this has now added the registry value. The subkey with the same GUID as the value is not present on this machine, so I think my earlier suspicions about this being added by Kaspersky are correct. It’s also interesting to note that MalwareBytes does not seem to add the registry value at all.

> Get-SpeculationControlSettings
Speculation control settings for CVE-2017-5715 [branch target injection]

Hardware support for branch target injection mitigation is present: False
Windows OS support for branch target injection mitigation is present: False
Windows OS support for branch target injection mitigation is enabled: False

Speculation control settings for CVE-2017-5754 [rogue data cache load]

Hardware requires kernel VA shadowing: False

Suggested actions

 * Install BIOS/firmware update provided by your device OEM that enables hardware support for the branch target injection mitigation.
 * Install the latest available updates for Windows with support for speculation control mitigations.
 * Follow the guidance for enabling Windows support for speculation control mitigations are described in https://support.microsoft.com/help/4072698


BTIHardwarePresent             : False
BTIWindowsSupportPresent       : False
BTIWindowsSupportEnabled       : False
BTIDisabledBySystemPolicy      : False
BTIDisabledByNoHardwareSupport : False
KVAShadowRequired              : False
KVAShadowWindowsSupportPresent : False
KVAShadowWindowsSupportEnabled : False
KVAShadowPcidEnabled           : False

Upon scanning for Windows Updates this machine found the 2018-01 update (KB4056892). After installing it, the cmdlet now shows:

> Get-SpeculationControlSettings
Speculation control settings for CVE-2017-5715 [branch target injection]

Hardware support for branch target injection mitigation is present: False
Windows OS support for branch target injection mitigation is present: True
Windows OS support for branch target injection mitigation is enabled: False
Windows OS support for branch target injection mitigation is disabled by system policy: False
Windows OS support for branch target injection mitigation is disabled by absence of hardware support: True

Speculation control settings for CVE-2017-5754 [rogue data cache load]

Hardware requires kernel VA shadowing: False

Suggested actions

 * Install BIOS/firmware update provided by your device OEM that enables hardware support for the branch target injection mitigation.
 * Follow the guidance for enabling Windows support for speculation control mitigations are described in https://support.microsoft.com/help/4072698


BTIHardwarePresent             : False
BTIWindowsSupportPresent       : True
BTIWindowsSupportEnabled       : False
BTIDisabledBySystemPolicy      : False
BTIDisabledByNoHardwareSupport : True
KVAShadowRequired              : False
KVAShadowWindowsSupportPresent : True
KVAShadowWindowsSupportEnabled : False
KVAShadowPcidEnabled           : False

Useful links

Update 2018-01-10

Dell have now provided some pages with information about their efforts to deal with the problems:

  • Dell’s main Meltdown & Spectre page – this has an overview of the problem, and gives links to other pages with more specific information for PCs & thin client devices, Dell EMC hardware, VMware, and Pivotal.
  • Dell Consumer and Commercial product updates – this has BIOS versions or ETAs for new BIOS versions that will, in conjunction with OS updates, protect against Meltdown & Spectre. e.g. my E7450 laptop is due for a BIOS update to be released on 12th Jan 2018. Note that OS updates should be in place before the BIOS is updated.

Update 2018-01-16

Dell released a BIOS update for my E7450 work laptop on 12th Jan, version A18, which adds fixes for CVE-2017-5715 (one of the Spectre vulnerabilities) and various Intel Management Engine security issues (CVE-2017-5711 & CVE-2017-5712, CVE-2017-13077, CVE-2017-13078 & CVE-2017-13080). So this is a good thing to install ASAP.

Note that the SpeculationControl PowerShell module has been updated to version 1.0.4 since I first started this post, so you might want to do:

Update-Module -Name SpeculationControl -Force

Running Get-SpeculationControlSettings settings on my E7450 now results in the following:

PS Scripts:\> Get-SpeculationControlSettings
Speculation control settings for CVE-2017-5715 [branch target injection]
For more information about the output below, please refer to https://support.microsoft.com/en-in/help/4074629

Hardware support for branch target injection mitigation is present: True
Windows OS support for branch target injection mitigation is present: True
Windows OS support for branch target injection mitigation is enabled: True

Speculation control settings for CVE-2017-5754 [rogue data cache load]

Hardware requires kernel VA shadowing: True
Windows OS support for kernel VA shadow is present: True
Windows OS support for kernel VA shadow is enabled: True
Windows OS support for PCID performance optimization is enabled: True [not required for security]


BTIHardwarePresent             : True
BTIWindowsSupportPresent       : True
BTIWindowsSupportEnabled       : True
BTIDisabledBySystemPolicy      : False
BTIDisabledByNoHardwareSupport : False
KVAShadowRequired              : True
KVAShadowWindowsSupportPresent : True
KVAShadowWindowsSupportEnabled : True
KVAShadowPcidEnabled           : True

Which gives lots of green text, for each line that says “True”, which is nice.

It’s too early to tell if there’s any performance impact, but the machine so far (about an hour) is working fine.

I’ve also now disabled the option in the Dell BIOS called OROM Keyboard Access (found under Security), as this prevents access to the Ctrl-P preboot keypress to get into the Intel Management Engine.

Posted in Hardware, Security, Windows | Tagged , , , , , , , , , , , , , , , , , , , , , , , | 1 Comment

Automatically manage Office 365 Licences with Powershell

Managing Office 365 manually via the portal is fine, until you get fed up with it or need to make bulk changes. Automating the licence allocation process turned out to be fairly easy, once I’d got to grips with how the PowerShell cmdlets worked.

This is nothing massively complex. My top tips are:

  1. Make sure that you only ever specify “valid” combinations of licences – e.g. you can’t add Audio Conferencing if the user doesn’t have a Skype for Business licence. This is exactly the same as when you manage users via the Admin portal.
  2. Get to grips with the terminology:
    1. AccountSkuId = a code for a top level product as seen in the admin portal, for example O365_BUSINESS_PREMIUM is the Office 365 Business Premium bundle.
    2. Plans = subcomponents of an AccountSkuId, e.g. MICROSOFTBOOKINGS is (unsurprisingly) Microsoft Bookings. By default, all plans within an AccountSkuId are enabled when you add an AccountSkuId to a user. To disable some, you create an MsolLicenseOptions object specifying the plans you want disabled.
  3. To change the plans that are enabled/disabled within an AccountSkuId for a user, you have to remove the AccountSkuId from the user, create the MsolLicenseOptions object and then re-add the AccountSkuId specifying the MsolLicenseOptions object.
  4. For the Msol PowerShell cmdlets, it’s “License” not “Licence”!

I’ve been meaning to do this for some time, it just feels like it should be automated, and now, for me, it is.

What it does

The script below runs as a scheduled task. It writes its actions to the Application event log. The way it works is to assume that all users in Office 365 should have a Business Premium licence, unless they’re a member of an Office 365 security group called “Unlicensed Users”. If they’re in that group, it removes all licences from them.

Events logged are as follows:

  • 10003 – Start processing O365 Licenses
  • 10004 – Finish processing O365 Licenses
  • 10001 – Removed license from <User>
  • 10002 – Added license to <User>
  • 10005 – Failed to remove license from <User>
  • 10006 – Failed to add license to <User>

It’s easy to filter the event log to see just the information you’re looking for, to confirm what actions have been taken, and when.

Setup

The scheduled task is set to run as a user, and I’ve created an encrypted password file whilst running as that user, the password is for the Office 365 Global Admin account that’ll be used by the script. To create the password file, use:

runas /user:<domain>\scheduled-task-user

to run a powershell prompt on the machine where the scheduled task will be run. The within that PowerShell prompt run the following:

Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath "C:\Users\aacsyncuser\Documents\GlobalAdmin.pass"

and provide the Office 365 Global Admin password when prompted. This will create the .pass file used by the script.

Then from an Administrator PowerShell prompt, run the following to create the Event Log source used by the script:

New-EventLog -LogName Application -Source "Manage O365 Licenses"

Grant the scheduled task user the “Log on as a batch job” right: From your Administrator prompt, run gpedit.msc and go to Local Computer Policy – Computer Configuration – Windows Settings – Security Settings – Local Policies – User Rights Assignment. Double-click Logon on as a batch job and add the scheduled task user.

Make sure the machine running the scheduled task has the following installed:

Save the script and modify it to include the correct path to the password file you created, the correct Global Admin UPN for $MsolGlobalAdminUsername, and your MSOL Domain name for $MsolDomain.

Import-Module MSOnline

$EncryptedPasswordFile = "C:\Users\aacsyncuser\Documents\GlobalAdmin.pass"
$MsolGlobalAdminUsername = "rcmglobaladmin@RCMTECHCOUK.onmicrosoft.com"
$SecureStringPassword = Get-Content -Path $EncryptedPasswordFile | ConvertTo-SecureString
$MsolCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $MsolGlobalAdminUsername,$SecureStringPassword

Connect-MsolService -Credential $MsolCred

Write-EventLog -LogName Application -Source "Manage O365 Licenses" -EntryType Information -EventId 10003 -Message ("Start processing O365 Licenses")

$MsolDomain = "RCMTECHCOUK"

# Remove products from users in the "Unlicensed Users" group
$UnlicensedUsersGroupGUID = (Get-MsolGroup -GroupType Security | Where-Object -Property DisplayName -EQ "Unlicensed Users").ObjectID.Guid
$UnlicensedUsers = (Get-MsolGroupMember -GroupObjectId $UnlicensedUsersGroupGUID).EmailAddress
foreach($User in $UnlicensedUsers){
    $AccountLicenses = (Get-MsolUser -UserPrincipalName $User).Licenses
    if($AccountLicenses.Count -gt 0){
        Write-Host ("Remove license from "+$User)
        try{
            Set-MsolUserLicense -UserPrincipalName $User -RemoveLicenses $AccountLicenses.AccountSkuId # Remove all products
            Write-EventLog -LogName Application -Source "Manage O365 Licenses" -EntryType Information -EventId 10001 -Message ("Removed license from "+$User)
        }catch{
            Write-EventLog -LogName Application -Source "Manage O365 Licenses" -EntryType Warning -EventId 10005 -Message ("Failed to remove license from "+$User)
        }
    }
}

# Set license options
$MsolAccountSkuIdsToAdd = $MsolDomain+":O365_BUSINESS_PREMIUM"
$MsolLicenseOptions = New-MsolLicenseOptions -AccountSkuId $MsolAccountSkuIdsToAdd -DisabledPlans "EXCHANGE_S_STANDARD","MICROSOFTBOOKINGS","O365_SB_Relationship_Management"

# Add licenses to all users who currently do not have a licence as long as they're not in the "Unlicensed Users" group
$AllUnlicensedUsers = Get-MsolUser | Where-Object -Property IsLicensed -EQ $false
foreach($User in $AllUnlicensedUsers){
    if($UnlicensedUsers -notcontains $User.UserPrincipalName){
        Write-Host ("Add license to "+$User.UserPrincipalName)
        try{
            Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $MsolAccountSkuIdsToAdd -LicenseOptions $MsolLicenseOptions
            Write-EventLog -LogName Application -Source "Manage O365 Licenses" -EntryType Information -EventId 10002 -Message ("Added license to "+$User.UserPrincipalName)
        }catch{
            Write-EventLog -LogName Application -Source "Manage O365 Licenses" -EntryType Warning -EventId 10006 -Message ("Failed to add license to "+$User.UserPrincipalName)
        }
    }
}

Write-EventLog -LogName Application -Source "Manage O365 Licenses" -EntryType Information -EventId 10004 -Message ("Finish processing O365 Licenses")
Posted in Office 365, PowerShell | Tagged , , , , , , , , , , , | Leave a comment

Change Office 365 Products for a Group of Users with PowerShell

I wanted to switch all my users over to Office 365 Business Premium. It’s a bundle deal for companies of up to 300 people. Previously I’d been separately licencing each of Office 365 ProPlus, Skype for Business and OneDrive, but the Business Premium bundle is quite a bit cheaper, and gives you lots more apps.

I wanted to migrate the users over in batches, so wrote this script to help me. I created a new Office 365 security group to ToBusPrem (you can see this name in the script), added the users I wanted to migrate into that, then ran the script.

The script needs the creds of an Office 365 Global Admin, and prompts for them when it’s run. It also requires you to have the Microsoft Online Services Sign-in Assistant for IT Professionals  and Microsoft Azure Active Directory Module for Windows PowerShell installed.

It then gets all the users in the security group and transfers them over one by one.
Some of my users have extra licenses, e.g. Visio, Project, Audio Conferencing. The script works by removing all licenses that a user has, so I exclude Visio and Project from that list.

That won’t work for Audio Conferencing as the licence is only valid if an Office Suite licence is currently allocated. So I set a flag if Audio Conferencing is present, and use the flag to add audio conferencing back after the Business Premium licence has been added.

$MsolCred = Get-Credential
Connect-MsolService -Credential $MsolCred

$MigrationGroupId = (Get-MsolGroup -GroupType Security | Where-Object -Property DisplayName -EQ "ToBusPrem").ObjectId
$MigrationUsers = (Get-MsolGroupMember -GroupObjectId $MigrationGroupId).EmailAddress
$MigrationUsers.Count

$MsolDomain = "RCMTECHCOUK"
$MsolAccountSkuIdsToAdd = $MsolDomain+":O365_BUSINESS_PREMIUM"

foreach($MsolUPN in $MigrationUsers){
    Write-Host $MsolUPN -NoNewline
    $AccountLicenses = Get-MsolUser -UserPrincipalName $MsolUPN | foreach {$_.Licenses}
    $AccountLicenses = $AccountLicenses | Where-Object -Property AccountSkuId -notlike "*VISIOCLIENT" # Exclude Visio
    $AccountLicenses = $AccountLicenses | Where-Object -Property AccountSkuId -notlike "*PROJECTCLIENT" # Exclude Project
    if($AccountLicenses.AccountSkuId -like "*MCOMEETADV"){$AudioConferencing = $true}else{$AudioConferencing = $false} # Flag if Audio Conferencing user
    Write-Host " Remove" -ForegroundColor Gray -NoNewline
    Set-MsolUserLicense -UserPrincipalName $MsolUPN -RemoveLicenses $AccountLicenses.AccountSkuId # Remove all products
    Write-Host " Add" -ForegroundColor Gray -NoNewline
    $MsolLicenseOptions = New-MsolLicenseOptions -AccountSkuId $MsolAccountSkuIdsToAdd -DisabledPlans "EXCHANGE_S_STANDARD","MICROSOFTBOOKINGS","O365_SB_Relationship_Management"
    Set-MsolUserLicense -UserPrincipalName $MsolUPN -AddLicenses $MsolAccountSkuIdsToAdd -LicenseOptions $MsolLicenseOptions
    if($AudioConferencing){Set-MsolUserLicense -UserPrincipalName $MsolUPN -AddLicenses ($MsolDomain+":MCOMEETADV")} # Add Audio Conferencing if flagged
    Write-Host " Done" -ForegroundColor Gray
}
Posted in PowerShell | Tagged , , , , , , , , , , | Leave a comment

Search through Pwned Passwords with PowerShell

Troy Hunt recently released over 300 million SHA1 hashes of passwords that his Have I Been Pwned website has been collecting. The site allows you to search the database to see if your passwords are included in those from many data dumps and breaches. However, putting a valid password into a third party website, even one that’s claiming to do good things (and I’m sure it is) is a bad idea. The roughly 6GB of downloads allow you to search the cache of passwords yourself, on your own machine, which is much safer.

Loading these files into an editor to use the search function is not going to be easy though, so I wrote a script to search the file piece by piece.

At the moment there are three files, and I concatenated them using the Windows copy command and the /b switch:

copy file1.txt+file2.txt+file3.txt output.txt

How it works

This PowerShell script takes two parameters: The path to the password file, and the password to search for. It converts the password into a SHA1 hash, and then searches the file looking for that hash. It’s not fast, but does give you a very rough progress bar. Use an SSD, a fast processor (with turbo capability) and if you’re going to do multiple searches, more RAM than the size of the hashes text file plus plenty of room for your OS (Windows will cache the entire file in RAM if it can). The script reports if it’s found the hash of your password or not – you can test it with a password like qwerty or 123456 just to check as these are both in there.

Usage

Save the file, and specify the parameters on the command line:
.\SearchPwned.ps1 -PassFile = C:\users\me\documents\pwned-passwords.txt -Password “MySecretPassword”

Script

param([Parameter(Mandatory=$true)][string]$PassFile,[Parameter(Mandatory=$true)][string]$Password)

$StringBuilder = New-Object System.Text.StringBuilder 
[System.Security.Cryptography.HashAlgorithm]::Create("SHA1").ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Password)) | foreach{
    [Void]$StringBuilder.Append($_.ToString("x2")) 
} 
$Hash = $StringBuilder.ToString() 
Write-Host "Searching for $Hash" -ForegroundColor Gray

# Do some rough maths to give an idea of progress
$FileSize = (Get-ChildItem -Path $PassFile).Length
$HashSize = $Hash.Length
$ChunkSize = 2000
$ChunkLength = $HashSize * $ChunkSize

$Found = $false
Get-Content -Path $PassFile -ReadCount $ChunkSize | foreach{
    $ChunkLengthRead = $ChunkLengthRead + $ChunkLength
    Write-Progress -Activity "Searching" -PercentComplete ($ChunkLengthRead/$FileSize*100)
    if($_ -match $Hash){
        $Found = $true
        return
    }
}
Write-Progress -Activity "Searching" -Completed

if($Found){
    Write-Host "Found" -ForegroundColor Red
}else{
    Write-Host "Not Found" -ForegroundColor Green
}
Posted in PowerShell, Security | Tagged , , , , , , , | Leave a comment

GUI to log off Remote Desktop users by non-admins

I’ve blogged about the issues with the well-intentioned but ill-though-out Remote Desktop Management Server concept in Windows Server 2012 (inc R2) before, trying to come up with workarounds to all the things you used to be able to do easily with tsadmin in previous version, that you now just cannot do.

Like delegate non-admin users (e.g. helpdesk, expert users) the ability to log off other users.

So here’s a PowerShell script that falls back on the (very) old but thankfully still perfectly functional quser and logoff commands. My suggestion is to create a group, put the helpdesk users who need this functionality into the group, then grant the group permission via the following command:

wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSPermissionsSetting WHERE (TerminalName ="RDP-Tcp") CALL AddAccount "domain\group",2

You need to run that on all your RDS servers.

Once the helpdesk staff are in the group they’ll need to log off the RDS server and back on again. Now you can give them the script to run.

The script uses quser to get the current user sessions on the server where it’s being run, parses it and displays it in a GridView (with multi-select). Selected users are then logged off via the (also old) logoff Command.
Get your helpdesk user to right-click the script, select “Run with PowerShell”, then just select one or more users to log off and click “OK”.

# Log off RDS user sessions
# For regular users to be able to do this you need to grant them permission:
# wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSPermissionsSetting WHERE (TerminalName ="RDP-Tcp") CALL AddAccount "domain\group",2

# Get the list of users using good old quser (query user)
$QUser = &quser.exe
# Get rid of the Sessionname column because it is inconsistent (contains no data for disconnected sessions)
$QUser = $QUser -replace("rdp-tcp#\d+","")
# Remove header row
$QUser = $QUser -replace("username.+time","")
# Tidy up the spaces to leave one space separator only
$QUser = $QUser -replace("\s+"," ")
# Remove the current user line prefix
$QUser = $QUser -replace(">"," ")
# Split into an array, data starts at position 3, 7 items per line
$QUserArray = $Quser -split " "
# Make an array of objects
$CurrentUsers = New-Object System.Collections.ArrayList
for ($i = 3; $i -lt $QUserArray.Count; $i+=7){
    $ThisUser = New-Object -TypeName System.Object
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name "UserName" -Value $QUserArray[$i]
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name "ID" -Value $QUserArray[$i+1]
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name "State" -Value $QUserArray[$i+2]
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name "IdleTime" -Value $QUserArray[$i+3]
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name "LogonTime" -Value ($QUserArray[$i+4]+" "+$QUserArray[$i+5])
    $CurrentUsers.Add($ThisUser) | Out-Null
}
# Display the array in a gridview
$SelectedUsers = $CurrentUsers | Out-GridView -Title "Select users(s) to log off" -OutputMode Multiple
# Log off selected sessions
foreach($User in $SelectedUsers){
    Write-Host ("Logging off "+$User.UserName+" (session ID "+$User.ID+")... ") -NoNewline
    $x = &logoff.exe $User.ID
    Write-Host "Done"
}
Start-Sleep -Seconds 1
Posted in PowerShell, Remote Desktop, Windows | Tagged , , , , , , , , , , , | Leave a comment