Skip Ribbon Commands
Skip to main content

Ondrej Sevecek's Blog

:

Engineering and troubleshooting by Directory Master!
Ondrej Sevecek's Blog > Posts > Testování TLS a SSL spojení a jeho bezpečnostních parametrů za pomoci PowerShell
leden 06
Testování TLS a SSL spojení a jeho bezpečnostních parametrů za pomoci PowerShell

Nedávno jsem tu uveřejňoval skript na vytváření a případně tedy i testování HTTP spojení pomocí jazyka PowerShell. Tak dneska zde mám skript na testování TLS (nebo jak se tomu v pravěku říkalo - SSL) spojení. To je takové to šifrování komunikace, které se používá pro zabezpečení protokolů, jako je HTTPS, LDAPS, RDP, SMTPS, pokud by někdo nevěděl.

TLS znamená Transport Layer Security a máte ho od Windows 7 a Windows 2008 R2 k dispozici ve verzích TLS 1.0, TLS 1.1 a TLS 1.2 (a navíc ještě jako DTLS, ale to je už jiná pohádka). Jedná se o to, že se nejprve ustaví TCP spojení na nějaký serverovský port (například právě 443 pro HTTPS, nebo 636 pro LDAPS). Na tomto TCP spojení se domluví TLS šifrování. A teprve až je ustaveno TLS šifrování, tak se teprve posílají vůbec aplikační data, jako je třeba právě HTTP GET, nebo HTTP POST a nebo SMTP EHLO.

To znamená, že testovat TLS spojení je možné na libovolném TCP portu, bez ohledu na to, jaká aplikace tam pracuje a jaká má svoje vlastní specifika. Uděláme TCP spojení a prostě ustavíme TLS. Tohle musí samo od sebe fungovat. Pokud tohle neprojde, ani pozdější aplikační komunikace by stejně nefungovala.

Takže juchů na to. Konkrétní algoritmy ani suitu si explicitně nevyberete, to se musí udělat pomocí registrových hodnot (o tom zase příště), ale můžete si zvolit algoritmus a můžete také zvolit, jestli se povoluje, nebo vyžaduje NULL šifrování - tzn. bez šifrování - zakázat což je jedno ze základních bezpečnostních nastavení.

Používám SslStream a rovnou jsem to umístil do funkce.

function global:Test-TLS (
  [string] $hostName,
  [int] $port = 443,
  [string] $clientCertThumbprint = $null,
  [System.Net.Security.EncryptionPolicy] $encryption = [System.Net.Security.EncryptionPolicy]::AllowNoEncryption,
  [bool] $chechRevocation = $false,
  [System.Security.Authentication.SslProtocols] $sslProtocol = [System.Security.Authentication.SslProtocols]::Default
  )
{
  # [System.Net.Security.EncryptionPolicy]
  #   AllowNoEncryption
  #   NoEncryption
  #   RequireEncryption

  # [System.Net.Security.SslProtocols]
  #   Default
  #   None
  #   Ssl2
  #   Ssl3
  #   Tls
  #   Tls11
  #   Tls12

  [bool] $result = $false

  echo ('Going to connect to: {0} | {1}' -f $hostName, $port)
  [System.Net.Sockets.TcpClient] $client = New-Object System.Net.Sockets.TcpClient $hostName, $port

  if ($client -ne $null) {

    echo ('Initialize SslStream object with encryption level: {0}' -f $encryption)
    [System.IO.Stream] $netStream = $client.GetStream()
    [System.Net.Security.SslStream] $sslStream = New-Object System.Net.Security.SslStream $netStream, $false, $null, $null, $encryption

    if ($sslStream -ne $null) {

      $clientCert = $null

      if ($clientCertThumbprint -ne '') {
 
        echo ('Open the client certificate with thumbprint: {0}' -f $clientCertThumbprint)
        $clientCert = Get-Item "Cert:\CurrentUser\My\$clientCertThumbprint"
      }

      echo ('Start SSL session: {0} | {1} | {2} | {3}' -f $hostName, $chechRevocation, $clientCert.Subject, $clientCert.Issuer)
      $sslStream.AuthenticateAsClient($hostName, $clientCert, $sslProtocol, $chechRevocation)

      if ($sslStream.IsAuthenticated) {

        $result = $true

        echo ('Protocol: {0}' -f $sslStream.SslProtocol)
        echo ('Cipher: {0} | {1}' -f $sslStream.CipherAlgorithm, $sslStream.CipherStrength)
        echo ('Hash: {0} | {1}' -f $sslStream.HashAlgorithm, $sslStream.HashStrength)
        echo ('Key exchange: {0} | {1}' -f $sslStream.KeyExchangeAlgorithm, $sslStream.KeyExchangeStrength)
  
        $sCer = $sslStream.RemoteCertificate

        if ($sCer -ne $null) {

          echo ('Server certificate thumbprint: {0}' -f $sCer.GetCertHashString())
          echo ('Server certificate subject: {0}' -f $sCer.Subject)
          echo ('Server certificate issuer: {0}' -f $sCer.Issuer)
          echo ('Server certificate not after: {0:s}' -f [DateTime]::Parse($sCer.GetExpirationDateString()))
          echo ('Server certificate not before: {0:s}' -f [DateTime]::Parse($sCer.GetEffectiveDateString()))
  
        } else {
 
          echo ('Server certificate: None')
        }

      } else {

        $result = $false
    
        echo ('Error authenticating to the server')
      }
  
      echo ('Close TLS session.')
      $sslStream.Dispose()
      $netStream.Dispose()
    }

    echo ('Close TCP connection.')
    $client.Dispose()
  }

  return $result
}

Když to chcete otestovat, můžete buď použít jednoduše Show-Command Test-Tls, nebo rovnou z příkazové řádky zadat následující:

Test-TLS -encryption AllowNoEncryption -hostName sss.google.com -chechRevocation $True -port 443 -sslProtocol Tls12

Tak pěkný nový rok!

Comments

There are no comments for this post.

Add Comment

Title


Pole Title nemusíte vyplňovat, doplní se to samo na stejnou hodnotu jako je nadpis článku.

Author *


Pole Author nesmí být stejné jako pole Title! Mám to tu jako ochranu proti spamu. Roboti to nevyplní dobře :-)

Body *


Type number two as digit *


Semhle vyplňte číslici dvě. Předchozí antispemové pole nefunguje úplně dokonale, zdá se, že jsou i spamery, které pochopily, že je občas potřeba vyplnit autora :-)

Email


Emailová adresa, pokud na ni chcete ode mě dostat odpověď. Nikdo jiný než já vaši emailovou adresu neuvidí.

Attachments