« August 2010 | Main | October 2010 »

6 posts from September 2010

09/10/2010

Groovy News: Gaelyk 0.4.4 Released

Gaelyk 0.4.4 was just released.  Get it from the Download section on the Gaelyk site.  New in this version, (copied/pasted from the announcement):

  • Updated the Google App Engine SDK to the latest 1.3.7 version
  • Jabber and incoming email groovlets now have their implicit logger (gaelyk.email and gaelyk.jabber)
  • Plugins are now impacting Jabber and incoming email groovlets as well
  • Fixed a bug the conversion of String to Datastore's Category type (thanks for the contribution!)
  • Internal refactorings of the caching logic
  • Added namespace support for multitenancy, added in SDK 1.3.7:
    • a namespace is added in the binding, pointing at NamespaceManager, the SDK class dealing with 
    • new method namespace.of("customerA") { ... } to execute a closure in the context of a specific namespace

Reblog: F5's 2048-Bit Key Transition Article

Posted today on F5's DevCentral site is a pretty nice article that talks about the Certificate Authorities transition from 1024-bit keys to 2048-bit keys.  Depending upon your vendor, it could come sooner than you were expecting and, sadly, we are going to see a lot of customer connectivity issues with our sites over the course of the next few years.  

Although, I would like to see more detail on the impact to us on the move to 2048 bit keys, F5's testing indicated up to 5x slower Transaction per Second performance, which indicates to me that ssl offloading is becoming more vital and the days of development saying "just encrypt the whole site" could be coming to an end.  Good Article:  F5 Friday: The 2048 bit keys to the kingdom



09/07/2010

CryptoNark v0.3.6 Released

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

This is just a small release, only adding a couple of new things and I cleaned up the output a little more.  This version add two additional URIs to the unsafe URL check:  a check for the ColdFusion administrator URL and a check for the tomcat status page.  I also added a small disclaimer to the output of the unsafe URL check because successes could be false positives--especially requests that result in 301 or 302 responses.

For people new to the site, CryptoNark is a perl-based PCI compliance remediation validation checker.  It's primary purpose is to allow an administrator to check to see whether configuration changes have been successfully implemented when fixing PCI Compliance related vulnerabilities. 

I added the SSLv3 tests back in.  Although SSLv3 and TLSv1 in openssl use the same cipher list, some TLSv1 ciphers won't work over an SSLv3 connection.

The only other encryption-related thing added is I'm reading the common name of the cert returned when connections are made over a secured channel.  I'm shooting to add some more interesting stuff in a version 0.4 release coming "soon". 

The main CryptoNark page has been updated and you can download the script from the downloads page.

#!/usr/bin/env perl

use Modern::Perl;

use Term::ANSIColor qw(:constants);
use Tie::Hash::Indexed;
use IO::Socket::SSL;
# The following three modules provide support for 
# displaying server type and TRACE and TRACK requests.
use LWP::UserAgent;
use HTTP::Headers;
use HTTP::Request;
# Core Module introducing command line options
use Getopt::Long; 

my $version = "0.3.6";

my ( $host, $port, $scheme );
my $useragent = "cryptonark-pci-auditor/v" . $version;

sub usage{
  say "Usage: cnark.pl [--host HOSTNAME --port PORT]";
  exit;
 }

usage() if ( ! GetOptions("host=s" => \$host, "port=s" => \$port,) or ( ! defined $host) or ( ! defined $port) );

my $key;
my $value;
my $ssl2client;
my $ssl3client;

if ( $port eq 443) {
 $scheme = 'https';
 }
else {
 $scheme = 'http';
 }

# Populate arrays with OpenSSL ciphers
# Note: TLSv1 ciphers and SSLv3 ciphers are 
# identical in OpenSSL

tie my %ssl2_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'
);

%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-DES-CBC3-SHA' => '168 bits, High Encryption, Anonymous Auth',
 '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-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',
 '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'
);

# Populate a hash of unsafe URLs
# i.e. URLs you would not want exposed
# to the Internet

tie my %bad_urls, 'Tie::Hash::Indexed';

%bad_urls = (
 'Apache mod_status page' => 'server-status',
 'Apache mod_info page' => 'server-info',
 'Apache mod_jk status page' => 'jk-status',
 'Apache mod_proxy_balancer' => 'balancer-manager',
 'ColdFusion Administrator' => 'CFIDE/administrator/index.cfm',
 'IIS Samples' => 'IISsamples',
 'IIS Scripts' => 'Scripts',
 'IIS MSADC Directory' => 'MSADC',
 'IIS Help' => 'IISHelp',
 'IIS Admin' => 'IISAdmin',
 'Tomcat Manager' => 'manager/html',
 'Tomcat Status Page' => 'manager/status',
 'Tomcat JSP Examples' => 'jsp-examples/index.html',
 'Tomcat Servlet Examples' => 'servlets-examples/index.html',
 'JBoss JMX Console' => 'jmx-console',
 'JBoss Tomcat Status Page' => 'status',
 'JBoss Web Console' => 'web-console',
 'JBoss 5.x Admin Console' => 'admin-console',
 );


sub get_server_type{
 my $url = "$scheme://$host/";
 my $ua = LWP::UserAgent->new;
  $ua->timeout(10);
  $ua->env_proxy;
  $ua->agent( $useragent );
   my $header = $ua->head( $url );
   print "\nWeb Server Type: " . $header->server . "\n\n";
 }

sub test_for_trace {
  my $url = "$scheme://$host/";

  my $method = "TRACE";
  my $ua   = LWP::UserAgent->new;
  $ua->timeout(10);
  $ua->env_proxy;
  $ua->agent( $useragent );
  
  my $request = HTTP::Request->new( $method => $url );
  $request->header(Header0 => "TRACE");
  $request->header(Header1 => "Test");

  my $response = $ua->request($request);

  given ( $response->code ) {
    when (200) {
      say "======this is what you sent======";
      say $response->content;
      say "=================================";
      say $method, " is enabled and working.";
    }
    when (301) {
      say "Redirect present. Retry request against ",
       $response->header('Location');
    }
    when (302) {
      say "Redirect present. Retry request against ",
       $response->header('Location');
    }
    when (307) {
      say "Redirect present. Retry request against ",
       $response->header('Location');
    }
    when (403) {
      say $response->status_line;
      say $method, " is forbidden.";
    }
    when (404) {
      say $response->status_line;
      say "This is an unexpected response";
    }
    when (405) {
      say $response->status_line;
      say $method, " is not permitted.";
    }
    when (501) {
      say $response->status_line;
      say $method, " is not implemented.";
    }
    default {
      say $response->status_line;
    }
  }
}

sub test_for_track {
  my $test = 'This is an HTTP TRACE test.';
  my $url = "$scheme://$host/";

  my $method = "TRACK";
  my $ua   = LWP::UserAgent->new;
  $ua->timeout(10);
  $ua->env_proxy;
  $ua->agent( $useragent );
  
  my $request = HTTP::Request->new( $method => $url );
  $request->header(Header0 => "TRACK");
  $request->header(Header1 => "Test");

  my $response = $ua->request($request);

  given ( $response->code ) {
    when (200) {
      say "======this is what you sent======";
      say $response->content;
      say "=================================";
      say $method, " is enabled and working.";
    }
    when (301) {
      say "Redirect present. Retry request against ",
       $response->header('Location');
    }
    when (302) {
      say "Redirect present. Retry request against ",
       $response->header('Location');
    }
    when (307) {
      say "Redirect present. Retry request against ",
       $response->header('Location');
    }
    when (403) {
      say $response->status_line;
      say $method, " is forbidden.";
    }
    when (404) {
      say $response->status_line;
      say "This is an unexpected response";
    }
    when (405) {
      say $response->status_line;
      say $method, " is not permitted.";
    }
    when (501) {
      say $response->status_line;
      say $method, " is not implemented.";
    }
    default {
      say $response->status_line;
    }
  }
}

sub scan_for_unsafe_urls{
 print "\n";
 say "Scanning for 'Unsafe' URLs...";
 say "NOTE: Successes could be false positives";
 sleep 2;
 my $response;
 my $request;
 
 while (($key,$value) = each(%bad_urls)) {
  my $url = "$scheme://$host/$value";
  my $ua = LWP::UserAgent->new;
   $ua->timeout(10);
   $ua->env_proxy;
   $ua->agent( $useragent );

  my $request = HTTP::Request->new( GET => $url );
  my $response = $ua->request($request);
 
 if ($response->code == '200') {
  print RED, "   " . $key . " -- /". $value . " url found" . "\n", RESET;
  }
  else {
   print GREEN, "   " . $key . " -- /" . $value . " url not found." . "\n", RESET;
   }
 }
}

sub shameless_plug{
  print "\n";
  print "For tips on PCI Remediation, visit my blog at: \n";
  print "  http://blog.techstacks.com/pci-compliance/\n";
  print "Thanks for using cnark!\n";
 }



sub is_weak{
 if ($key =~ /^EXP-|^NULL|^ADH-|DES-CBC-/) {
  print RED, "  " . $key . " -- " . $value . "\n", RESET;
 }
 else {
  print GREEN, "  " . $key . " -- " . $value . "\n", RESET;
 }
}

# Basic certificate checking
sub cert_info{
print "\nSSL Certificate Information...\n";
sleep 2;

my $certclient = IO::Socket::SSL->new(
 SSL_verify_mod => 0,
 SSL_version => 'TLSv1',
 SSL_cipher_list => 'RC4-MD5',
 PeerAddr => $host,
 PeerPort => $port,
 Proto => 'tcp',
 Timeout => '5'
 );
 my $cn = $certclient->peer_certificate("cn");
 say "Certificate Commmon Name: " . $cn;
}


sub test_ssl2_ciphers{

print "\nTesting SSLv2 Ciphers...\n";
sleep 2;
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'
  )
 && is_weak();
 }
}

sub test_ssl3_ciphers{

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


sub test_tls_ciphers{
print "Testing TLSv1 Ciphers...\n";
sleep 2;
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'
  )
 && is_weak(); 
 }
}

# Run through the subroutines
get_server_type();

say "Testing for HTTP TRACE...";
sleep 2;
test_for_trace();

say "\nTesting for HTTP TRACK...";
sleep 2;
test_for_track();

scan_for_unsafe_urls();

if ($port eq 443) {
 cert_info();
 test_ssl2_ciphers();
 test_ssl3_ciphers();
 test_tls_ciphers();
 }

shameless_plug();