« BigIP: Logging SSL Version and Cipher Information | Main | Apache: Forcing the Server's SSL Cipher on the Client »

07/16/2009

cryptonark v0.1: My Perl Port of sslthing.sh

CryptoNark 0.4.1 is the most recent version. See the Release Announcement for more details.

I have posted before that sslthing.sh is a pretty useful tool for scanning and reporting on all available ciphers that a remote host supports.  Since it hasn't been updated, as far as I know, since 2004 and my shell scripting skills are not worth blogging about, I ported it over to Perl recently. My main reasons for doing this was two-fold,  the first being purely academic—to learn Perl better. The second reason for doing it was that I recently had to scan a site that required Windows Challenge Response authentication on the root of the site and since sslthing.sh connects to and performs an HTTP GET /, it wouldn't work. I've named my port 'cryptonark' (crypto nark).

Version 0.1 of cryptonark.pl is almost a direct port of sslthing, although you will need to install additional dependencies like Tie::Hash::Indexed and IO::Socket::SSL (and possibly the dependencies these modules depend on!) in order to get it working.   There are three additional features that I have added to my port that don't presently reside in sslthing (again, as far as I know).

  1. Scans for ALL ciphers available in OpenSSL including Null and Anonymous.  sslthing does not appear to do this today.
  2. Provides slightly expanded text detailing the strength level of encryption and whether or not that particular cipher supports ADH (anonymous) authentication.
  3. Since it doesn't send any data over the channel, it can even scan hosts that normally require a user id and password to retrieve content.

With this initial release, output is almost identical to sslthing's.  Here is some sample output from a recent scan of one of my highly insecure test sites running locally:
Testing SSLv2 Ciphers...
Testing SSLv3 Ciphers...
 ADH-AES256-SHA -- 256 bits, High Encryption, Anonymous Auth
 DHE-RSA-AES256-SHA -- 256 bits, High Encryption
 AES256-SHA -- 256 bits, High Encryption
 ADH-AES128-SHA -- 128 bits, High Encryption, Anonymous Auth
 DHE-RSA-AES128-SHA -- 128 bits, High Encryption
 AES128-SHA -- 128 bits, High Encryption
 EDH-RSA-DES-CBC3-SHA -- 168 bits, High Encryption
 DES-CBC3-SHA -- 168 bits, High Encryption
 ADH-DES-CBC3-SHA -- 168 bits, High Encryption, Anonymous Auth
 RC4-SHA -- 128 bits, Medium Encryption
 RC4-MD5 -- 128 bits, Medium Encryption
 ADH-RC4-MD5 -- 128 bits, Medium Encryption, Anonymous Auth
 EDH-RSA-DES-CBC-SHA -- 56 bits, Low Encryption
 DES-CBC-SHA -- 56 bits, Low Encryption
 ADH-DES-CBC-SHA -- 56 bits, Low Encryption, Anonymous Auth
 EXP-ADH-DES-CBC-SHA -- 40 bits, Export-Grade Encryption
 EXP-ADH-RC4-MD5 -- 40 bits, Export-Grade Encryption
 EXP-EDH-RSA-DES-CBC-SHA -- 40 bits, Export-Grade Encryption
 EXP-DES-CBC-SHA -- 40 bits, Export-Grade Encryption
 EXP-RC2-CBC-MD5 -- 40 bits, Export-Grade Encryption
 EXP-RC4-MD5 -- 40 bits, Export-Grade Encryption
As you can see from the above output, I've expanded the descriptions a little bit to include some additional information on encryption type and have marked those ciphers that also utilize ADH authentication (anonymous authentication).  I will probably tackle the display of this output in the next version because I'm not that happy with it yet.

As a PCI Compliance assessment tool, cryptonark.pl is good for when you need to remediate against vulnerabilities that show up in your assessment scans like: "SSL Server Allows Anonymous Authentication Vulnerability", "SSL Server Has SSLv2 Enabled Vulnerability", or "SSL Server Supports Weak Encryption Vulnerability".  Scanning your site with cryptonark.pl, you will get a list of all the ciphers that a server supports and as you remediate, you can re-run the scan quickly and easily to see the effect your remediation actions have had.  Ultimately, your mitigation goal is achieved when no ciphers other than the Medium and High grade encryption are reported back (excluding the anonymous auth ciphers) using this tool.

Below is the cryptonark.pl script (new release, v0.2, available here, main CryptoNark page available here):
#!/usr/bin/env perl -w
# Usage: ./cryptonark.pl host port
# based on sslthing.sh by blh [at] blh.se
# ported to perl by Chris M - techstacks.com
#
# cryptonark: version 0.1 - Initial Version
#
# almost a direct port, this version also tests
# null and anonymous ssl ciphers and reports 
# accordingly. A little more information is provided
# in the output. Used best if used to validate PCI-DSS
# compliance--to check that null, anonymous and weak ciphers
# are disabled. 
#
# It probably will not run straight out of the box--it requires
# IO::Socket::SSL. Tie::Hash::Indexed, although not strictly required
# is nice to have in order to order the hash lists from strongest to 
# weakest. Otherwise, the order could be random making the results a
# bit harder to read.

use strict;
use warnings;

use Tie::Hash::Indexed;

use IO::Socket::SSL;

my $host = $ARGV[0];
my $port = $ARGV[1];

my $help = "Usage: $0 <hostname> <port>";

my $key = "empty";
my $value = "empty";

my $ssl2client = "empty";
my $ssl3client = "empty";

if ( !@ARGV ) {
 print $help . "\n";
 exit 0;
}



# Populate array with OpenSSL ciphers
# Note: TLSv1 ciphers and SSLv3 ciphers are identical
# but I'm running separate checks any way.

tie my %ssl2_ciphers, 'Tie::Hash::Indexed';
tie my %ssl3_ciphers, 'Tie::Hash::Indexed';
tie my %tls1_ciphers, 'Tie::Hash::Indexed';

%ssl2_ciphers = (
 'DES-CBC3-MD5' => '168 bits, High Encryption',
 'RC2-CBC-MD5' => '128 bits, Medium Encryption',
 'RC4-MD5' => '128 bits, Medium Encryption',
 'DES-CBC-MD5' => '56 bits, Low Encryption',
 'EXP-RC2-CBC-MD5' => '40 bits, Export-Grade Encryption',
 'EXP-RC4-MD5' => '40 bits, Export-Grade Encryption'
);

%ssl3_ciphers = (
 'ADH-AES256-SHA' => '256 bits, High Encryption, Anonymous Auth',
 'DHE-RSA-AES256-SHA' => '256 bits, High Encryption',
 'DHE-DSS-AES256-SHA' => '256 bits, High Encryption',
 'AES256-SHA' => '256 bits, High Encryption',
 'ADH-AES128-SHA' => '128 bits, High Encryption, Anonymous Auth',
 'DHE-RSA-AES128-SHA' => '128 bits, High Encryption',
 'DHE-DSS-AES128-SHA' => '128 bits, High Encryption',
 'AES128-SHA' => '128 bits, High Encryption',
 'EDH-RSA-DES-CBC3-SHA' => '168 bits, High Encryption',
 'EDH-DSS-DES-CBC3-SHA' => '168 bits, High Encryption',
 'DES-CBC3-SHA' => '168 bits, High Encryption',
 'ADH-DES-CBC3-SHA' => '168 bits, High Encryption, Anonymous Auth',
 'RC4-SHA' => '128 bits, Medium Encryption',
 'RC4-MD5' => '128 bits, Medium Encryption',
 'ADH-RC4-MD5' => '128 bits, Medium Encryption, Anonymous Auth',
 'EDH-RSA-DES-CBC-SHA' => '56 bits, Low Encryption',
 'EDH-DSS-DES-CBC-SHA' => '56 bits, Low Encryption',
 'DES-CBC-SHA' => '56 bits, Low Encryption',
 'ADH-DES-CBC-SHA' => '56 bits, Low Encryption, Anonymous Auth',
 'EXP-ADH-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-ADH-RC4-MD5' => '40 bits, Export-Grade Encryption',
 'EXP-EDH-RSA-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-EDH-DSS-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-RC2-CBC-MD5' => '40 bits, Export-Grade Encryption',
 'EXP-RC4-MD5' => '40 bits, Export-Grade Encryption',
 'NULL-SHA' => 'Null cipher, No Encryption',
 'NULL-MD5' => 'Null cipher, No Encryption'
);

%tls1_ciphers = (
 'ADH-AES256-SHA' => '256 bits, High Encryption, Anonymous Auth',
 'DHE-RSA-AES256-SHA' => '256 bits, High Encryption',
 'DHE-DSS-AES256-SHA' => '256 bits, High Encryption',
 'AES256-SHA' => '256 bits, High Encryption',
 'ADH-AES128-SHA' => '128 bits, High Encryption, Anonymous Auth',
 'DHE-RSA-AES128-SHA' => '128 bits, High Encryption',
 'DHE-DSS-AES128-SHA' => '128 bits, High Encryption',
 'AES128-SHA' => '128 bits, High Encryption',
 'EDH-RSA-DES-CBC3-SHA' => '168 bits, High Encryption',
 'EDH-DSS-DES-CBC3-SHA' => '168 bits, High Encryption',
 'DES-CBC3-SHA' => '168 bits, High Encryption',
 'ADH-DES-CBC3-SHA' => '168 bits, High Encryption, Anonymous Auth',
 'RC4-SHA' => '128 bits, Medium Encryption',
 'RC4-MD5' => '128 bits, Medium Encryption',
 'ADH-RC4-MD5' => '128 bits, Medium Encryption, Anonymous Auth',
 'EDH-RSA-DES-CBC-SHA' => '56 bits, Low Encryption',
 'EDH-DSS-DES-CBC-SHA' => '56 bits, Low Encryption',
 'DES-CBC-SHA' => '56 bits, Low Encryption',
 'ADH-DES-CBC-SHA' => '56 bits, Low Encryption, Anonymous Auth',
 'EXP-ADH-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-ADH-RC4-MD5' => '40 bits, Export-Grade Encryption',
 'EXP-EDH-RSA-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-EDH-DSS-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-DES-CBC-SHA' => '40 bits, Export-Grade Encryption',
 'EXP-RC2-CBC-MD5' => '40 bits, Export-Grade Encryption',
 'EXP-RC4-MD5' => '40 bits, Export-Grade Encryption',
 'NULL-SHA' => 'Null cipher, No Encryption',
 'NULL-MD5' => 'Null cipher, No Encryption'
);

print "Testing SSLv2 Ciphers...\n";

while (($key,$value) = each(%ssl2_ciphers)) {
 my $ssl2client = IO::Socket::SSL->new(
 SSL_verify_mode => 0,
 SSL_version => 'SSLv2',
 SSL_cipher_list => $key,
 PeerAddr => $host,
 PeerPort => $port,
 Proto => 'tcp',
 Timeout => '5'
 )
 && print " " . $key . " -- " . $value . "\n";
}

print "Testing SSLv3 Ciphers...\n";

while (($key,$value) = each(%ssl3_ciphers)) {
 my $ssl3client = IO::Socket::SSL->new(
 SSL_verify_mode => 0,
 SSL_version => 'SSLv3',
 SSL_cipher_list => $key,
 PeerAddr => $host,
 PeerPort => $port,
 Proto => 'tcp',
 Timeout => '5'
 )
 && print " " . $key . " -- " . $value . "\n";
}

print "Testing TLSv1 Ciphers...\n";

while (($key,$value) = each(%tls1_ciphers)) {
 my $tls1client = IO::Socket::SSL->new(
 SSL_verify_mode => 0,
 SSL_version => 'TLSv1',
 SSL_cipher_list => $key,
 PeerAddr => $host,
 PeerPort => $port,
 Proto => 'tcp',
 Timeout => '5'
 )
 && print " " . $key . " -- " . $value . "\n";
}

TrackBack

TrackBack URL for this entry:
https://www.typepad.com/services/trackback/6a01156fbc6fe6970c011572288487970b

Listed below are links to weblogs that reference cryptonark v0.1: My Perl Port of sslthing.sh:

Comments