27 posts categorized "tools"

07/31/2011

CryptoNark v0.4.6 Released

I'm releasing an update to CryptoNark today, which is a maintenance release that fixes a few bugs that have been sitting out there for a little while now.  No new SSL/TLS testing functionality is in this release.  The three changes in this release are:

  1. Modified cryptonark to utilize a port number in all $url variable assignments.  This was an easy way for me to allow cryptonark to perform the extended http scanning when those http hosts were not using well-known port numbers.  This functionality may also change in the future as I retool things to accomodate SSL listeners that run on ports other than 443.
  2. Sometime in an earlier v0.4.x release, non-ssl host tests were still getting ssl tests sent to it.  This release fixes that issue.
  3. The get_server_type function has been fixed as well so it now properly sets the global variable that was supposed to be assigned the value of the HTTP Server header.  My "discovery" that the HTTP PROPFIND method test was broken in the previous release drove this fix.

The Downloads page on this site has been updated with the new version.  Because the script is now over 600 lines long, I do not post the source in release posts any longer.

07/24/2011

Update - Adding iTerm2 Themes

The previous post became outdated when newer versions of iTerm2 updated the Preferences UI, so this post is meant to cover iTerm2 version 1.0 (and newer).

The iTerm2 Color Gallery page is the centralized repository for iTerm2 themes and provides links to available themes if you want to know where to go to find iTerm2 themes, (although most of the links will take you either to the author's personal site or to GitHub).  If you find a theme you like, download it or save it as a text file somewhere.

To manage your installed iTerm2 themes, click the iTerm menu and then the Preferences... menu item.  Click on the Profiles preference category and then the Colors tab.  A window like the one below will be displayed:

Iterm2ProfilesPrefs

There is a drop down at the bottom of this tab labeled Load Presets....  This is where you will go to install or remove iTerm2 themes.  

To install an iTerm2 theme, click the Import... command from the Load Presets... drop down list and then select the file you downloaded from the Color Gallery.  It will then be available in the list of available themes, separated from the five system themes that ship with a default iTerm2 install (Dark Background, Light Background, Pastel, Tango Dark, and Tango Light).  

To uninstall or remove a previously installed theme, click the Delete Preset... command from the Load Presets... drop down list.  A drop down list of all the themes that you've imported will display and you can then select the theme you'd like to delete.  Please note that you can not delete the five system themes that ship with iTerm2.

05/03/2011

CryptoNark v0.4.5 Released

I'm happy to announce a new update to CryptoNark today:  Version 0.4.5 is out now.  This version incorporates the HTTP PROPFIND vulnerability scanning from my recent post on that subject:  Verifying 'WebDAV HTTP Method PROPFIND Enabled' Remediation was Successful.

Refer to that link for more details but cryptonark will only perform the HTTP PROPFIND scan if run with the -xl/--kitchen-sink arguments and only if Microsoft IIS is seen in a server response header.

The CPAN module, XML::LibXML, is used, which enables the script to parse the xml in the response and allows the script to echo back the data in question. So, you get to see just what it is that the pci scanners are complaining about when the WebDAV HTTP Method PROPFIND Enabled information disclosure vulnerability is reported on one of your sites. Once again, a reminder that cryptonark's purpose is to provide a mechanism for the site administrator to validate both that a vulnerability exists and to validate that remediation activities were successfully implemented. The tool was not intended to be used for evil. :)

The other change added in this update was the change in how redirection is handled during the Unsafe URL scans. I've defaulted LWP::UserAgent to not follow redirects, since following redirects seems to be a source for some false positives that I was experiencing when scanning some of my sites. Let me know if the change is causing you more trouble then it was.

Download CryptoNark v0.4.5 from the downloads page or you can just copy it from the source code below.

#!/usr/bin/env perl

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

use feature 'state';

my $version = "v0.4.5";

my ( $host, $port, $scheme );
my $insecure = '';
my $xl = '';
my $verifymode = 2;
my $useragent = "cryptonark-pci-auditor/" . $version;

sub usage{
    say "Usage: cnark.pl -h|--host  -p|--port  \n\t\t[-i|--insecure] [-xl|--kitchen-sink]";
    exit;
  }

usage() if ( ! GetOptions("h|host=s" => \$host, "p|port=s" => \$port, "i|insecure" => \$insecure, "xl|kitchen-sink" => \$xl ) or ( ! defined $host) or ( ! defined $port) );

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

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

if ($insecure eq 1 ) {
  $verifymode = 0;
  }


# 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";
      our $server_type = $header->server;
  }

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: This isn't perfect yet.\nSuccesses could be false positives\nMany are caused by redirection";
  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 );
      $ua->max_redirect(0);

    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 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(
  PeerHost => "$host:$port",
  SSL_ca_file => Mozilla::CA::SSL_ca_file(),
  SSL_verify_mode => $verifymode,
  SSL_version => 'TLSv1',
  SSL_cipher_list => 'RC4-SHA',
  Proto => 'tcp',
  Timeout => '5',
  ) 
    || die("Certificate Peer Verification Failed\nCertificate not trusted (but could be due to server misconfiguration)\nRun with the --insecure switch if you wish to test with no certificate verification\n\n");

  $certclient->verify_hostname($host, "http")
    || die("Hostname Verification Failed.\n$host does not match certificate's common name.\n\n");

  my $cn = $certclient->peer_certificate("cn");
  say "Certificate with Commmon Name " . $cn . " appears to be valid.\n";
}

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 => 0x00,  
    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 $ssl3client = IO::Socket::SSL->new(
    SSL_verify_mode => 0x00,
    SSL_version => 'SSLv3',
    SSL_cipher_list => $key,
    PeerAddr => $host,
    PeerPort => $port,
    Proto => 'tcp',
    Timeout => '5'
    )
  && is_weak();
  }
}


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

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

my $message;

# Will set content-length to zero
my $content_length = 0;
# Will set an empty Host header
my $host_header = "";

my $objHeader = HTTP::Headers->new;
  $objHeader->header('Host' => $host_header);
  $objHeader->header('Content_Length' => $content_length);

my $url = "$scheme://$host/";

    my $method = "PROPFIND";
    my $ua  = LWP::UserAgent->new;
    $ua->timeout(10);
    $ua->env_proxy;
    $ua->agent('propfind-pci-auditor/v0.1');
    
    my $request = HTTP::Request->new( "PROPFIND", $url, $objHeader, $message );

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

    given ($response->code ) {
        when (207) {
            my $parser = XML::LibXML->new();
            my $doc = $parser->load_xml( string => $response->content );
            say RED, "Response Status Code: " . $response->status_line;
            say "Internal Web Server Address: " . $doc->findvalue('//a:href') . "\nSite Appears to be Vulnerable to \'WebDAV HTTP Method PROPFIND Enabled\'\n  information disclosure issue.", RESET;
        }
        when (301) {
            say "Redirect Present.  Potential False Positive";
            say "Retry request against: " . $response->header('Location');
        }
        when (302) {
            say "Redirect Present.  Potential False Positive";
            say "Retry request against: " . $response->header('Location');
        }
        when (307) {
            say "Redirect Present.  Potential False Positive";
            say "Retry request against: " . $response->header('Location');
        }
        when (403) {
            say $response->status_line;
            say "This is not an expected response code."
            }
        when (404) {
            say $response->status_line;
            say "This is not an expected response code."
            }
        when (405) {
            say $response->status_line;
            say "HTTP Method PROPFIND is not permitted.";
            say "This is good!";
            }
        when (501) {
            say $response->status_line;
            say "HTTP Method PROPFIND is not implemented.";
            say "This is good!";
            }
        default {
            say $response->status_line;
            }
        }
    }


if ($xl eq 1 ) {
  # 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();

say "\nScanning for well-known, unsafe URLs...";
sleep 2;
scan_for_unsafe_urls();

if ($main::server_type =~ /^Microsoft-IIS/) {
  say "Scanning for HTTP PropFind Vulnerability...";
  sleep 2;
  scan_for_propfind();
}


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

  }
  else {
   cert_info();
   test_ssl2_ciphers();
   test_ssl3_ciphers();
   test_tls_ciphers();
}
__END__

=head1 TITLE

CryptoNark (aka cnark.pl)

=head1 VERSION

Version 0.4.1

=head1 DATE

March 28, 2011

=head1 AUTHOR

Chris Mahns  Contact me at: techstacks [at] gmail [dot] com.

=head1 ATTRIBUTION

CryptoNark was based on sslthing.sh by blh [at] blh [dot] se

=head1 DESCRIPTION

CryptoNark (aka 'cnark.pl') is a PCI Compliance remedition verification script.  Primarily, it's purpose was to verify whether sslv2, null, weak, and anonymous ciphers had been successfully disabled on a web site after a web site administrator had implemented the necessary mitigation.  In addition, passing the -xl switch enables some additional checks like testing to see whether HTTP TRACE or TRACK is enabled or testing if certain known "unsafe" URLs are available over the INternet.

=head1 USAGE

./cnark.pl -h|--host  -p|--port  [-xl|--kitchen-sink] [-i|--insecure]

=head1 DEPENDENCIES

CryptoNark runs in both perl 5.10 and perl 5.12.  It makes use of perl functionality that was first introduced in Perl 5.10.  CyrptoNark also relies upon many CPAN modules: Modern::Perl, Term::ANSIColor, Tie::Hash::Indexed, IO::Socket::SSL, Mozilla::CA, LWP::UserAgent, HTTP::Headers, HTTP::Request, and Getopt::Long.  CryptoNark most likely will not work and has not been tested under perl 5.8.X or without the required modules.


=head1 VERSION HISTORY

=head2 VERSION 0.1

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. Works best if used to validate PCI-DSS compliance--to check that null, anonymous and weak ciphers are disabled.  

It probably will not run right "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.

=head2 VERSION 0.2

+ Added Color Coded output. Good ciphers are green, bad ones are red.
 
=head2 VERSION 0.2.1

- Removed the SSLv3 Tests.  (Actually, just commented them out for now.)  SSLv3 and TLSv1 utilize the same ciphers so the tests are redundant.

+ Added a message after the display of cipher levels providing links to my site so that you can get information on disabling ciphers

=head2 VERSION 0.2.5

+ Added a HEAD request to display web server type.  Uses some addition modules:  LWP::UserAgent and HTTP::Headers

=head2 VERSION 0.3

+ "Upgraded" cnark to use perl 5.10 features.  Perl 5.10 is now required.

+ Modified script so that it uses command line options using Core Module Getopt::Long.  --host and --port should now be used.

- Removed exception catch on check_server_type() function. I don't think HEAD requests should ever fail but some sites restrict that method too for some reason.

+ cnark now tests for existence of HTTP Methods: TRACE and TRACK.

+ cnark will skip ssl scans if a non ssl port is used.

=head2 VERSION 0.3.1

- Code Clean up
     
+ Modern::Perl is now required

=head2 VERSION 0.3.5

+ Now scans for commonly used "unsafe" URLs. More to come.

=head2 VERSION 0.3.6
     
- Moved some stuff around.

+ Added SSLv3 tests back in.  This functionality was useful to some folks who were looking for output from specific protocols.

+ Added ColdFusion Administrator to unsafe URL check
     
+ Added Tomcat Status URL to unsafe URL Check

+ Tweaked the output for the unsafe URL Check to reduce some redundancy and add a false positive disclaimer. I Should be able to get rid of the disclaimer when better false positive checks are added

+ Added some basic certificate parsing

=head2 VERSION 0.4

+ Added option -xl|--kitchen-sink  By default, cnark.pl now performs ssl-only tests.  The -xl|kitchen-sink will put cryptonark in full betrayal mode.

+ Added Certificate Peer Verification (enabled by default) This causes cryptonark to fail on expired certs, missing root certificates, self-signed certs, and (I hope) invalid certificate chains. Certificate Validation is due to the inclusion of the ca-bundle.crt CA certificate bundle from mod_ssl.

+ Added --insecure option to disable peer verification if you so desire.

- Removed shameless plug

=head2 VERSION 0.4.1

+ There really is a CPAN module for everything!  Added Mozilla::CA, which enables me to utilize Certificate Peer Verification without having to re-distribute and maintain a cacerts file.

+ Added Hostname Validation.  CryptoNark will now fail if you attempt to connect to a site where the hostname does not match the $host argument.  For example, 

+ Doc Cleanup.  embedded pod.  You can now run 'perldoc cnark.pl' for an embedded man page

- Removed code for shameless plug subroutine.

=head2 VERSION 0.4.5

+ Added HTTP PropFind Test, which is executed if the -xl option is specified.

+ Add supporting module:  XML::LibXML

+ Disabled rediretion onthe unsafe URL checks.  This was creating some false positives.