Forum Discussion
Cole_McDonald
Professor
7 years agoThis is posted with no warranty. Use at your own risk. Don't test it in a production environment:
# Requires "Credential Manager 2.0"
Import-Module credentialmanager
function test-credential {
param (
$credential
)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('domain')
write-output "$($DS.ValidateCredentials($cred.UserName,$cred.GetNetworkCredential().Password))"
}
function get-creds {
param (
$credName = "$env:USERDOMAIN\$env:USERNAME"
)
if ( $credName -eq "list" ) {
# Select stored user from a list
$credentials = Get-StoredCredential | ogv -PassThru
} else {
# Check for Stored Credentials
$credentials = Get-StoredCredential | ? username -eq $credName
}
if ( $credentials.count -eq 1 ) {
# Test to make sure creds work before moving forward
if ( test-credential $credentials[0] ) {
# They work, return the credentials
write-output $credentials[0]
} else {
# They don't work, have the user update the password
$cred = Get-Credential `
-UserName $credName `
-Message "Please update your password"
# Test to verify the new creds work
if ( test-credential -credential $cred ) {
# Update stored cred and return the credentials
Remove-StoredCredential `
-Target $credName
New-StoredCredential `
-Target $credName `
-UserName $cred.UserName `
-Password $cred.GetNetworkCredential().Password
write-output $cred
} else {
# Updated creds failed, return FALSE
write-output $false
}
}
} else {
# Need fresh creds to store for future use
$cred = Get-Credential `
-UserName $credName `
-Message "Enter account password"
# Test to verify the new creds work
if ( test-credential -credential $cred ) {
# Store cred and return the credentials
New-StoredCredential `
-Target $credName `
-UserName $cred.UserName `
-Password $cred.GetNetworkCredential().Password
write-output $cred
} else {
# creds failed, return FALSE
write-output $false
}
}
}
$Computer = "<1st-Hop Computer>"
$TestComputer = "<2nd-Hop Computer>"
# This was tested with a 'Domain.local' type of domain
$domain = "<Domain>"
$FQDN = "$Computer.$domain"
# These credentials need to have access to both computers
# (assumed, not tested - based on my understanding of the CredSSP token auth process)
$cred = get-creds
#region Enable-CredSSPDelegation
# write-host ""
$sessionRemote = New-PSSession $Computer
# write-host "get wsmancredssp from remote/delegate"
$remoteSetting = Invoke-Command `
-Session $sessionRemote `
-ScriptBlock {
Get-WSManCredSSP
}
# write-host "set wsmancredssp on remote"
Invoke-Command `
-Session $sessionRemote `
-ScriptBlock {
Enable-WSManCredSSP -Role Server -Force
}
# write-host "set wsmancredssp on local with remote as delegate"
Start-Process powershell.exe `
-Verb runas `
-ArgumentList "-command & {Enable-WSManCredSSP -Role Client -DelegateComputer $FQDN -Force}"
# write-host "Connecting WSMan to remote"
Connect-WSMan $FQDN
Set-Item WSMan:\$FQDN\Service\Auth\CredSSP -Value $True
sleep 15
# write-host "Starting CredSSP session"
$workingSession = New-PSSession `
-ComputerName $FQDN `
-Authentication Credssp `
-Credential $cred
#endregion
write-host "--- Starting Processing ---"
# This just looks for the print spooler service on the 2nd-Hop Computer
# It runs the invoke-command on the 1st-Hop Computer to do so
# This Scriptblock is where the payload goes
Invoke-Command `
-session $workingSession `
-ScriptBlock {
get-service *spool* -ComputerName $TestComputer
}
write-host "--- Finished Processing ---"
#region Disable-CredSSPDelegation
# write-host "Close Session"
Remove-PSSession -Session $workingSession
# write-host "Disconnecting WSMan from remote"
Set-Item WSMan:\$FQDN\Service\Auth\CredSSP -Value $False
Disconnect-WSMan $FQDN
# write-host "set wsmancredssp from local back to initial settings"
Start-Process powershell.exe `
-Verb runas `
-ArgumentList "-command & {Disable-WSManCredSSP -Role Client}"
# write-host "set wsmancredssp from remote/delegate back to initial settings"
if ( $remoteSetting -like "*is not configured*" ) {
Invoke-Command `
-Session $sessionRemote `
-ScriptBlock {
Disable-WSManCredSSP -Role Server
}
}
Remove-PSSession -Session $sessionRemote
#endregion
No, I'm not OCD, what makes you think that? I like neat vertical lines I can follow for reference in my code. This all collapses very nicely in Powershell ISE.