Get the TLS ciphers suite order

Last year, Microsoft published an advisory about a vulnerability in Schannel where weak/insecure ciphers were used in TLS sessions. More recently Microsoft also published an Update to add new cipher suites to Internet Explorer and Microsoft Edge in Windows.

In the above advisory, they introduced a GPO setting where you can set a new ciphers suite order. Nice, I love it.
But wait, without that GPO setting,…

  • How do I know what is the order of ciphers being used?

The question was answered on this stackoverflow.com forum page
Unfortunately it doesn’t work with PowerShell 2.0 (default version) on Windows 7 and I get the following error
inptrsize-operator

  • What about newer systems?

The code proposed on the stackoverflow.com forum page works in Windows 8.1 and PowerShell 4.0. There’s also a module called TLS but it doesn’t have the Get-TlsCipherSuite cmdlet ๐Ÿ˜ฆ
tls-module-on-windows81

On Window 10, you’ve got more in the TLS module and the Get- TlsCipherSuite is available ๐Ÿ™‚

On Windows 10 to get the order of ciphers, you simply do

(Get-TlsCipherSuite).Name
  • How can I get the order of ciphers whatever the operating system and its version of PowerShell?

I’ve slightly changed the code proposed on the stackoverflow.com forum page : line 49 replaced by 48 ๐Ÿ˜Ž

Try {
# http://stackoverflow.com/questions/19695623/how-to-call-schannel-functions-from-net-c
if (-not ([System.Management.Automation.PSTypeName]'ConsoleApplication4').Type) {
Add-Type -TypeDefinition @'
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication4
{
public class Program
{
[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
static extern uint BCryptEnumContextFunctions(uint dwTable, string pszContext, uint dwInterface, ref uint pcbBuffer, ref IntPtr ppBuffer);
[DllImport("Bcrypt.dll")]
static extern void BCryptFreeBuffer(IntPtr pvBuffer);
[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
static extern uint BCryptAddContextFunction(uint dwTable, string pszContext, uint dwInterface, string pszFunction, uint dwPosition);
[DllImport("Bcrypt.dll", CharSet = CharSet.Unicode)]
static extern uint BCryptRemoveContextFunction(uint dwTable, string pszContext, uint dwInterface, string pszFunction);
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_CONTEXT_FUNCTIONS
{
public uint cFunctions;
public IntPtr rgpszFunctions;
}
public const uint CRYPT_LOCAL = 0x00000001;
public const uint NCRYPT_SCHANNEL_INTERFACE = 0x00010002;
public const uint CRYPT_PRIORITY_TOP = 0x00000000;
public const uint CRYPT_PRIORITY_BOTTOM = 0xFFFFFFFF;
public static void DoEnumCiphers()
{
uint cbBuffer = 0;
IntPtr ppBuffer = IntPtr.Zero;
uint Status = BCryptEnumContextFunctions(
CRYPT_LOCAL,
"SSL",
NCRYPT_SCHANNEL_INTERFACE,
ref cbBuffer,
ref ppBuffer);
if (Status == 0)
{
CRYPT_CONTEXT_FUNCTIONS functions = (CRYPT_CONTEXT_FUNCTIONS)Marshal.PtrToStructure(ppBuffer, typeof(CRYPT_CONTEXT_FUNCTIONS));
IntPtr pStr = functions.rgpszFunctions;
for (int i = 0; i < functions.cFunctions; i++)
{
Console.WriteLine(Marshal.PtrToStringUni(Marshal.ReadIntPtr(pStr)));
pStr = new System.IntPtr((pStr.ToInt64()+(IntPtr.Size))) ;
// pStr += IntPtr.Size;
}
BCryptFreeBuffer(ppBuffer);
}
}
}
}
'@ -ErrorAction Stop
} else {
Write-Verbose -Message "Type already loaded" -Verbose
}
# } Catch TYPE_ALREADY_EXISTS
} Catch {
Write-Warning -Message "Failed because $($_.Exception.Message)"
}
[ConsoleApplication4.Program]::DoEnumCiphers()

Additional links
Documented ciphers suites per OS
Update to enable TLS 1.1 and TLS 1.2 as a default secure protocols in WinHTTP in Windows
BCryptEnumContextFunctions function
CRYPT_CONTEXT_FUNCTIONS structure
BCryptFreeBuffer function

2 thoughts on “Get the TLS ciphers suite order

  1. Hi,

    Great script. It just returns all the information I need independent which version of powershell is used.
    The only thing I do not know how to manage is how to get the output into a variable. I want to extract and check the information returned.

    A simple:
    $results = [ConsoleApplication4.Program]::DoEnumCiphers()
    …does not work.

    Tried several things, but the output seems only to put on screen/console and not parsed into a variable. Hope someone can help me solve this.

    Thanks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.