Skip to content

Instantly share code, notes, and snippets.

@ToroNZ
Created July 12, 2022 10:01
Show Gist options
  • Save ToroNZ/dbcc18b6ee70b4d20a2d043b9dcd9abb to your computer and use it in GitHub Desktop.
Save ToroNZ/dbcc18b6ee70b4d20a2d043b9dcd9abb to your computer and use it in GitHub Desktop.
Powershell - Check/Get SSL/TLS Certificate
using namespace System.Net.Sockets
using namespace System.Net.Security
using namespace System.Security.Cryptography.X509Certificates
function Test-ServerSSLSupport {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]$HostName,
[UInt16]$Port = 443
)
process {
$RetValue = New-Object psobject -Property @{
Host = $HostName
Port = $Port
SSLv2 = $false
SSLv3 = $false
TLSv1_0 = $false
TLSv1_1 = $false
TLSv1_2 = $false
KeyExhange = $null
HashAlgorithm = $null
}
"ssl2", "ssl3", "tls", "tls11", "tls12" | %{
$TcpClient = New-Object Net.Sockets.TcpClient
$TcpClient.Connect($RetValue.Host, $RetValue.Port)
$SslStream = New-Object Net.Security.SslStream $TcpClient.GetStream(),
$true,
([System.Net.Security.RemoteCertificateValidationCallback]{ $true })
$SslStream.ReadTimeout = 15000
$SslStream.WriteTimeout = 15000
try {
$SslStream.AuthenticateAsClient($RetValue.Host,$null,$_,$false)
$RetValue.KeyExhange = $SslStream.KeyExchangeAlgorithm
$RetValue.HashAlgorithm = $SslStream.HashAlgorithm
$status = $true
} catch {
$status = $false
}
switch ($_) {
"ssl2" {$RetValue.SSLv2 = $status}
"ssl3" {$RetValue.SSLv3 = $status}
"tls" {$RetValue.TLSv1_0 = $status}
"tls11" {$RetValue.TLSv1_1 = $status}
"tls12" {$RetValue.TLSv1_2 = $status}
}
# dispose objects to prevent memory leaks
$TcpClient.Dispose()
$SslStream.Dispose()
}
$RetValue
}
}
function Get-ADDomainControllerCertificate
{
<#
.SYNOPSIS
Retrieves the LDAPS certificate properties.
.PARAMETER ComputerName
Specifies the Active Directory domain controller.
.PARAMETER Domain
Specifies the Active Directory DNS name.
.PARAMETER Port
LDAPS port for domain controller: 636 (default)
LDAPS port for global catalog: 3269
.DESCRIPTION
The cmdlet 'Get-ADDomainControllerCertificate' retrieves the LDAP over TSL/SSL certificate properties.
.EXAMPLE
Get-ADDomainControllerCertificate -ComputerName DC01
.EXAMPLE
Get-ADDomainControllerCertificate -ComputerName DC01,DC02 | Select ComputerName,Port,Subject,Thumbprint
.EXAMPLE
Get-ADDomainControllerCertificate DC01,DC02
.EXAMPLE
Get-ADDomainControllerCertificate DC01 -Port 3269
.EXAMPLE
Get-ADDomainControllerCertificate -Domain domain.local
.EXAMPLE
Get-ADDomainControllerCertificate -Domain domain.local | Select-Object ComputerName,Port,Subject,Thumbprint
.EXAMPLE
Get-ADDomainControllerCertificate -Domain domain.local -Port 3269 | Select-Object ComputerName,Port,Subject,Thumbprint
#>
[Cmdletbinding(DefaultParameterSetName='ComputerName')]
param(
[Parameter(ParameterSetName='ComputerName',Mandatory,Position=0)]
[Alias('CN')]
[string[]]$ComputerName,
[Parameter(ParameterSetName='DomainName',Mandatory,Position=0)]
[string]$Domain,
[Parameter(Position=1)]
[UInt16]$Port = 443,
[ValidateSet('Base64', 'X509Certificate')]
[string]$As = 'X509Certificate'
)
function ConvertFrom-X509Certificate {
param(
[Parameter(ValueFromPipeline)]
[X509Certificate2]$Certificate
)
process {
@(
'-----BEGIN CERTIFICATE-----'
[Convert]::ToBase64String(
$Certificate.Export([X509ContentType]::Cert),
[Base64FormattingOptions]::InsertLineBreaks
)
'-----END CERTIFICATE-----'
) -join [Environment]::NewLine
}
}
if($ComputerName)
{ $DomainDCs = $ComputerName | Get-ADDomainController | Sort-Object -Property Name }
if($Domain)
{ $DomainDCs = Get-ADDomainController -Server $Domain -Filter * | Sort-Object -Property Name }
foreach($DC in $DomainDCs)
{
$Server = $DC.HostName
try
{
$Connection = New-Object System.Net.Sockets.TcpClient($Server,$Port)
$TLSStream = New-Object System.Net.Security.SslStream($Connection.GetStream(), $false, {$true})
# Try to validate certificate, break out if we don't
try
{
$TLSStream.AuthenticateAsClient($Server, $null, [System.Net.SecurityProtocolType]'Tls, Tls12', $false)
$Status = "Validated"
}
catch
{
$Status = "Validation Failed"
$Connection.Close
Break
}
#Export as Base64 or PS Object
if ($As -eq 'Base64') {
return $TLSStream.RemoteCertificate | ConvertFrom-X509Certificate
}
else {
#Grab the Cert and it's Basic Properties
$RemoteCert = New-Object system.security.cryptography.x509certificates.x509certificate2($TLSStream.get_remotecertificate())
# Advanced Properties
try { $SAN = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '2.5.29.17'}).Format(0)} catch{}
try { $AppPolicies = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '1.3.6.1.4.1.311.21.10'}).Format(0)} catch{}
try { $V1TemplateName = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '1.3.6.1.4.1.311.20.2'}).Format(0)} catch{}
try { $V2TemplateName = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '1.3.6.1.4.1.311.21.7'}).Format(0)} catch{}
try { $SKI = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '2.5.29.14'}).Format(0)} catch{}
try { $AKI = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '2.5.29.35'}).Format(0)} catch{}
try { $BKU = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '2.5.29.15'}).Format(0)} catch{}
try { $EKU = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '2.5.29.37'}).Format(0)} catch{}
try { $CDP = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '2.5.29.31'}).Format(0)} catch{}
try { $AIA = ($RemoteCert.Extensions | Where-Object {$_.Oid.Value -eq '1.3.6.1.5.5.7.1.1'}).Format(0)} catch{}
# Object creation
New-Object -TypeName PSObject -Property ([ordered]@{
ComputerName = $Server
Port = $Port
Status = $Status
Subject = $RemoteCert.Subject
SAN = $SAN
FriendlyName = $RemoteCert.FriendlyName
Issuer = $RemoteCert.Issuer
ValidFrom = $RemoteCert.NotBefore
ValidTo = $RemoteCert.NotAfter
Thumbprint = $RemoteCert.Thumbprint
SignatureAlgorithm = $RemoteCert.SignatureAlgorithm.FriendlyName
AIA = $AIA
AKI = $AKI
BKU = $BKU
CDP = $CDP
EKU = $EKU
SKI = $SKI
AppPolicies = $AppPolicies
V1TemplateName = $V1TemplateName
V2TemplateName = $V2TemplateName
})
}
}
catch { $Status = 'Connection Failed' }
finally { $Connection.Close() }
}
}
#Example-Func1
"COMPUTER1.contoso.com" | Test-ServerSSLSupport -Port 636
#Example-Func2
Get-ADDomainControllerCertificate -ComputerName COMPUTER1.contoso.com -Port 636
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment