Test remote server cert against locally stored cert before trusting - powershell

I have some code that I use to connect to a web server that we own. The server has a self signed certificate. I am currently connecting with the trust any cert
[System.Net.ServicePointManager]::ServerCertificateValidationCallback {$true}.
How can I change this so that I can either test the remote server with custom code or against a cert in my local store? For example can I change the code above to
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$customValidator}
What I would like to do is, instead of trusting any/all certs, I would like to trust it only if it matches with the public key cer file I have or I would like to test the certificate using custom code. The thing I am not very clear on is how to handle the custom verification and at what point in the code. Do I need to write an entire class to handle custom SSL validation or is there a better way to do this?
$url = "https://myWebServer"
$web = New-Object Net.WebClient
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
//[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { customSslCertValidation } #I would like to do something like this
$output = $web.DownloadString($url)
Write-Host $output

Try something like this:
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {
$c = [System.Security.Cryptography.X509Certificates.X509Certificate2]$args[1]
($c.Thumbprint -eq "StoredOrRetrievedHash")
}
This checks the Thumbprint of the certificate returned as part of the request against the string "StoredOrRetrievedHash". You would want to replace that with the details from your certificate loaded in dynamically. It is worth noting that the first line of the scriptblock delegate casts the second element of the $args array to be an object of type X509Certificate2, as the bare X509Certificate object doesn't expose the Thumbprint property.
Note: this only works in PowerShell v2 and later - in v1 assigning an arbitrary scriptblock to a delegate was a lot of extra work and quite frankly, just not worth the effort typically.

Related

Is there a way to use Powershell to read local IE 11 cookies and replicate their data to other users on the same system?

I have a web based system that is called by a local PC system. The web system allows/controls interaction with a IP accessible device. Due to the simplistic nature of the base application interface to the web system (of which I have no control over), I have had to create a local cookie (using a web based configuration form) that stores site/install specific configuration information that is then used by the web system to interact with the internet accessible device for the installed site. The configuration is somewhat complicated. All of this already works and has been deployed to the initial customer site.
The issue is the PCs that are involved could be used by multiple people (in this instance 10 PCs that can be used by 10 or more employees each) with distinct logins to the PC(s) in question. This means setting up this complicated web configuration on each PC, 10 times. Lots of tedious room for errors.
I understand that I can not just copy a Win10 IE11 cookie from one user to another on a PC BUT is it possible to use Powershell to read the initial cookie that is built, extract the cookie information, and replicate/create a new cookie for all other users on that PC loading the new cookie with the same information in the base cookie?
I understand that I would likely need to run this from a user account with local admin right (in order to access the cookie area of other users) and can live with that if it avoids all the repetitive setup.
Is it possible to use Powershell and .Net to read a local cookie (given the URL) and extract the data from that cookie to be used to build new cookies for all other users on that PC for the initial URL?
Can't use IE plug-ins. Have not tried much else.
No code to show.
I am hoping for some code examples that demonstrate how to read from an existing cookie and how to write/create a cookie and load it with data, from Powershell.
You can refer examples of powershell scripts below will help you to read cookies.
$url = "https://www.linkedin.com"
$webrequest = Invoke-WebRequest -Uri $url -SessionVariable websession
$cookies = $websession.Cookies.GetCookies($url)
# Here, you can output all of $cookies, or you can go through them one by one.
foreach ($cookie in $cookies) {
# You can get cookie specifics, or just use $cookie
# This gets each cookie's name and value
Write-Host "$($cookie.name) = $($cookie.value)"
}
And if you're using PowerShell 2.0 and below, use System.Net.HTTPWebRequest
$url = "https://www.linkedin.com"
$cookiejar = New-Object System.Net.CookieContainer
$webrequest = [System.Net.HTTPWebRequest]::Create($url);
$webrequest.CookieContainer = $cookiejar
$response = $webrequest.GetResponse()
$cookies = $cookiejar.GetCookies($url)
# Here, you can output all of $cookies, or you can go through them one by one.
foreach ($cookie in $cookies) {
# You can get cookie specifics, or just use $cookie
# This gets each cookie's name and value
Write-Host "$($cookie.name) = $($cookie.value)"
}
Reference:
Getting Cookies using PowerShell
I did not get any examples for creating new cookie file from the existing files and share that cookie files with other users.

Unable to access ssl certificate from octopus library as X509Certificate2 object using powershell

I am trying to create a jwt token using a pfx which,I have stored in Octopus library. For this I have to create an object of X509Certificate2, which takes certificate path and password as input. Can someone please suggest a way to do this using powershell?
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certpath,'password')
I have been through some documents as per how to access certificate variables in octopus but how can I use them to create an object of X509Certificate2.
https://octopus.com/docs/deployment-process/variables/certificate-variables
After going through Microsoft and Octopus documentation I have managed to get it to work. Octopus store the certificate as a base64 encoded string in a variable named as Cert.Pfx and constructor of X509Certificate2 takes a byte array as a first parameter. So as a first step I just needed to convert the base64 encoded string to byte array.
$certbytearray=[System.Convert]::FromBase64String($OctopusParameters["Cert.Pfx"])
$CertPassKey="password"
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certbytearray,$CertPassKey)
#Biplab Thanks for posting your solution; it saved me a lot of headache! I had a slightly different situation without a password and I found that the X509Certificate2 constructor interpreted the byte array as a file name when I tried to call without the password even though the documentation indicates it should accept just a byte array.
I got it to work without the password by doing an import instead.
$certbytearray=[System.Convert]::FromBase64String($OctopusParameters["mycert.Pfx"])
$mycert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$mycert.import($certbytearray)
write-host $mycert.ThumbPrint
if ($mycert.HasPrivateKey)
{ write-host "has private key"}

How to add ADFS Relying Party Trust SAMLAssertionConsumer using New-ADFSSamlEndpoint

I'm trying to build a script with powershell that will ask for a new uri to be added to an existing list of Relying Party Trust SAML Assertion Consumer Endpoints.
I've used this:
$samlEndpoint1 = New-ADFSSamlEndpoint -Protocol 'SAMLAssertionConsumer' -Uri 'https://moo.mydomain.local/samlprp-0/' -Binding 'POST' -IsDefault $false -Index 3
Set-ADFSRelyingPartyTrust -TargetName "ExistingRPT" -SamlEndpoint #($samlEndpoint1)
However this seems to remove the existing ones that are there and just leaves this new one. Therefore I was hoping this just added it to the existing list.
Does anyone please have any suggestions? Do I have to export the existing ones to some kind of array and then add to it?
Thanks for your time

How to do LDAP query using Powershell and PKI

I'm new to Powershell, and I'm trying to do a secure LDAP query using PKI authentication. I'm getting stuck on how to set the certificate and key. Based on Googling/research, I have some of the basics, e.g.:
$connection = new-object System.DirectoryServices.Protocols.LDAPConnection('$domainName:$portNum')
[string[] $get] = "$attribute1", "$attribute2", "attribute3"
$request = new-object System.DirectoryServices.Protocol.SearchRequest("$targetOu", "$filter", "subtree", $get)
$response = new-object $connection.SendRequest($request)
Like I said, I'm getting stuck on how to set/send the certificate and key. I thought I could do $connection.ClientCertificates = $path, but that property is read-only. I also thought I had to do something with $System.Net.NetworkCredential, but I'm not sure if the cert and key actually correspond to username and password. I referred to a Perl script that did an LDAP query and used PKI, and you could do:
clientcert => '/path/to/cert.pem'
clientkey => '/path/to/key.pem'
What's the equivalent for Powershell? Do I have to do something with System.Security.Cryptography.X509Certificates.X509Certificate?
Any help would be appreciated!
$connection.ClientCertificates.Add($cert)
the $cert must be X509Certificate class
and get certificates from store using
$allPersonalCerts = #( Get-ChildItem -Path 'Cert:\CurrentUser\my' )
It returns array of X509Certificate objects (or X509Certificate2 which is child class for X509Certificate )
NB: When doing PowerShell programming, you can always search for help by googling C# or VB.net solutions. This is .Net and examples on .net-oriented languages just differ on syntax

Invoke-WebRequest GetSystemWebProxy()

Under PowerShell 2.0 I know that you can set the proxy you would like to use without knowing the exact proxy settings by doing something like the following:
$proxy = [System.Net.WebRequest]::GetSystemWebproxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
Now, my question is if I don't know the proxy settings can I use the above and combine it with a PowerShell 3.0 Invoke-WebRequest. Here's what I was hoping to be able to do:
$proxy = [System.Net.WebRequest]::GetSystemWebproxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$WS.Proxy = $proxy
$login = Invoke-WebRequest https://website.com/login_form.html -SessionVariable WS
However, when I attempt to do this I get an error, (apparently from my company proxy) indicating that my credentials cannot be verified. I'm hoping that this will ultimately work, but perhaps I'm just making a simple mistake.
Maybe this can help, I keep it in my profile. It is using the new the $PSDefaultParameterValues preference variable to set the default proxy values for the new web cmdlets. The code detects if I'm in my office environment and set the settings accordingly. This saves me specifying the settings each time I use those commands.
if(Test-Connection myCorpProxy -Count 1 -Quiet)
{
$global:PSDefaultParameterValues = #{
'Invoke-RestMethod:Proxy'='http://myCorpProxy:8080'
'Invoke-WebRequest:Proxy'='http://myCorpProxy:8080'
'*:ProxyUseDefaultCredentials'=$true
}
}
Use can use this code :
$dest = "http://www.google.fr"
$proxyurl = ([System.Net.WebRequest]::GetSystemWebproxy()).GetProxy($dest)
Invoke-WebRequest $dest -Proxy $proxyurl -ProxyUseDefaultCredentials
The actual problem with your code above (even though Shay's is more elegant) is that you're trying to set a property on a variable before it exists. The SessionVariable "$WS" doesn't exist before you call Invoke-WebRequest but you're trying to set the .Proxy property above it.
If it worked at one point, you had probably created an instance of $WS previously and therefore were able to work with the object during testing but on a fresh/dry run when the script was processing top-down, it didn't yet exist.