Category Archives: Microsoft

Microsoft related posts.

SSH from PowerShell with Posh-SSH

For more information on Posh-SSH:  https://github.com/darkoperator/Posh-SSH

This module is for Windows PowerShell 3.0 or above. It is compiled for .NET Framework 4.5.

Install-Module -Name Posh-SSH

Here’s a simple script that grabs credentials from a file.  See this other article for more on password management.  It uses the credentials to open a new SSH session to the remote computer and execute the pwd command and returns the results of that command.  Then, it closes the SSH session.

$computerName = "computername.domain.com"
$userId = "myUserId"
$pwd = Get-Content "$PSScriptRoot\$userId.Pw.txt" | ConvertTo-SecureString
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $userId, $pwd

try {
    "Attempting SSH to $computerName"
    $sshSession = New-SSHSession -ComputerName $computerName -Credential $creds -AcceptKey -ConnectionTimeout 10 -ErrorAction Stop
    $sessionId = $sshSession.SessionId
    "Session $sessionId opened."
    $command = "pwd"
    "Command: {0}" -f $command
    $sshOut = (Invoke-SSHCommand -SessionId $sessionId -Command $command).Output
    "Results: '{0}'" -f $sshOut
    Remove-SSHSession -SessionId $sessionId | Out-Null
    "Session $sessionId closed."
}
catch {$_.exception.Message}

Script to set an encrypted password for later use

Periodically passwords on service accounts need to be updated as all information security best practices recommend.  Many shops may not have automated tools that would do this for all their scripts.  Many PowerShell scripts may be set to read an encrypted password file.  Naturally, this would break after a password update.  I needed a quick tool for administrators to quickly update these password files by allowing them to do the input it twice to prevent typos method.  So here it is.  The file is stored in a text file ending with “.Pw.txt”

# Input and validate password and store encrypted in file for later use.

$userId= "myUserID"
$pwFile = "$PSScriptRoot\$userId.Pw.txt"

do {
    $password1 = Read-Host "$tryAgain`Enter $adminId Password: " -AsSecureString
    $password2 = Read-Host "Verify $adminId Password: " -AsSecureString
    $check1 = ([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password1)).ToString()
    $check2 = ([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password2)).ToString()
    if ($check1.SubString(0,($check1.Length)-4) -eq $check2.SubString(0,($check2.Length)-4)) {$pwMatch = $true}
    else {$tryAgain = "Passwords did not match, try again.`n"; $pwMatch = $false}
}
Until ($pwMatch)

$password1 | ConvertFrom-SecureString | Out-File $pwFile -Force

If you really need to make sure the password was properly encrypted, then you can use this script to recover it back into plain text. Use this sparingly and don’t leave the script lying around to be used. One may choose to use NTFS to lock down read to the password file even further. However, here it is:

# get the iLO password and convert to plain text
$userId= "myUserID"
$pwFile = "$PSScriptRoot\$userId.Pw.txt"

$SecurePassword = Get-Content $pwFile | ConvertTo-SecureString
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

$UnsecurePassword

Here’s an example to securely pull the password into a credential pair for use in many commandlets as $creds:

$userId= "myUserID"
$pwFile = "$PSScriptRoot\$userId.Pw.txt"
$pwd = Get-Content $pwFile | ConvertTo-SecureString
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $userId, $pwd

Credentials Management in PowerShell

This blog is plagiarized from the best article I’ve ever found on this subject.  Full credit to Kris Powell for this amazing article found here.

Here are my condensed notes for my use.  If you find it useful, give a shout out to Kris Powell.

We now know how to convert a SecureString to an encrypted standard string. We can take any method we like to get a SecureString, convert it to a standard string and then save it to a file. Here is an example of each:

Exporting SecureString from Plain text

"P@ssword1" | `
ConvertTo-SecureString -AsPlainText -Force | `
ConvertFrom-SecureString | `
Out-File "C:\Temp 2\Password.txt"

Exporting SecureString from Get-Credential

(Get-Credential).Password | `
ConvertFrom-SecureString | `
Out-File "C:\Temp 2\Password.txt"

Exporting SecureString from Read-Host

Read-Host "Enter Password" -AsSecureString |  `
ConvertFrom-SecureString | `
Out-File "C:\Temp 2\Password.txt"

Anyone of these examples should provide you with a Password.txt file that has an encrypted standard string the represents the password.

When you need to use this encrypted password, you simply reverse the process by importing the data from your file and use ConvertTo-SecureString. If all you need is a SecureString, you can stop there. You could even take it a step further and create a PSCredential object.

Creating SecureString object

$pass = Get-Content "C:\Temp 2\Password.txt" | ConvertTo-SecureString

Creating PSCredential object

$User = "MyUserName"
$File = "C:\Temp 2\Password.txt"
$MyCredential=New-Object `
-TypeName System.Management.Automation.PSCredential `
-ArgumentList $User,
(Get-Content $File | ConvertTo-SecureString)

Get a certificate with Subject Alternative Names using certreq

If one needs to use certreq to obtain a certificate, but the certificate signing request does not explicitly ask for it, here’s the command to get it anyway:

certreq -f -q -submit -attrib “CertificateTemplate:WebServer\nSAN:dns=<hostname>&dns=<hostname>.mydomain.com&ipaddress=<IP Address>” -config “<Config Name>” <Certificate Request File>.csr <Certificate File>.cer

The key part is in the attrib string following the new line “\n” bit where SAN: is then defined.  In this example, three are defined: the hostname, fully qualified domain name and the IP address.

Active Directory Integrated DNS Wildcard Search

So NSLOOKUP is the typical way one may query DNS.  Ever wanted to just grab the results as objects while using a wildcard filtered search?  If your DNS is Active Directory integrated, then it’s really pretty simple.  After all, each DNS entry is essentially an AD Object.  Why not query AD like we do for so many other things?  Basically, you just need the Distinguished name for the DNS zone and tell Get-ChildItem to look at Active Directory.  For example, if you wanted to find all host records ending in “-DC” in example.com:

Get-ChildItem "AD:DC=example.com,CN=MicrosoftDNS,CN=System,DC=example,DC=com" -Filter "name=*-dc"

By the way, if you get an error stating something similar to this:

Cannot find drive. A drive with the name 'ad' does not exist.

Then you may need to import the Active Directory module.

Import-Module ActiveDirectory

A quick test is to do a change directory to AD.

cd ad:

and the prompt should read “PS AD:\>”

Get-WinEvent vs. Get-EventLog

So, these two appear to be very similar at first glance.  However, depending on the data one wants to filter in on, one is significantly better than the other.  For me, the bottom line is using Get-Eventlog for filtering the Security Event Log is much faster.  That’s what I needed to know.

An article by Mark Berry was very helpful:

PowerShell: Get-WinEvent vs. Get-EventLog

Conclusions

  1. If you’re writing a PowerShell script to handle events from Vista or Server 2008, avoid the Get-WinEvent –FilterHashtable parameter; use –FilterXML instead.
  2. Even on Vista and beyond, consider using Get-EventLog if you need to filter the Security log for Audit Failures.

Error 14098 the Component Store has been corrupted

When the OS is serviced, the component store is updated. It is part of Windows Imaging and Servicing stack. If you got the error 14098 ‘The component store has been corrupted’, it means that something went wrong with Windows updates and its packages.

To fix the component store, you can use DISM – Deployment Image Servicing and Management tool.

/RestoreHealth: This checks for component store corruption, records the corruption to C:\Windows\Logs\CBS\CBS.log and fixes the corruption using Windows Update or using your Windows installation source.

Dism /Online /Cleanup-Image /RestoreHealth

Clean up the WinSxS folder on Windows 2012 R2

Use the /AnalyzeComponentStore to analyze the size of the Component Store (WinSxS folder) in Windows. The AnalyzeComponentStore option is available in Windows 8.1 Windows Server 2012 R2.

dism.exe /online /Cleanup-Image /AnalyzeComponentStore

Dism.exe removes superseded and unused system files from a system with the /StartComponentCleanup parameter.

dism.exe /online /Cleanup-Image /StartComponentCleanup

Using the /ResetBase switch with the /StartComponentCleanup parameter of dism.exe, all superseded versions of every component in the component store is removed.  All existing service packs and updates cannot be uninstalled after this command is completed. This will not block the uninstallation of future service packs or updates.

dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase

The /SPSuperseded parameter removes any backup components needed for de-installation of a service pack. The service pack cannot be uninstalled after this command is completed.

dism.exe /online /Cleanup-Image /SPSuperseded