« Bling v0.4 Released - Blog Ping Tool | Main | Another Bling Release: v0.4.1 - So Long, Technorati »

11/04/2009

Testing for Trace and Track

I am modifying cryptonark to report on more commonly-reported PCI findings than just SSL cipher strength. Another popular issue reported during PCI Scans is the "Web Server HTTP Trace/Track Method Support Cross-Site Tracing Vulnerability". The wording of this particular error has been a small thorn in my side mainly because "Trace/Track" can, and has, been interpreted as meaning "trace and track", "trace or track", or "trace and/or track".  The modifications I've made to this script proved to be so useful, I thought breaking it out and sharing it might be useful to others as well.  

The truth is, with most modern web servers and application servers, this vulnerability notification really means:  "trace is enabled unless you're running a fairly old version of IIS—like IIS4—then it is **probably** track".  

The script below uses Perl 5.10 and LWP::UserAgent.  I've already got Net::SSLeay and Crypt::SSLeay installed, so I did not need to declare or install them in order for LWP to be able to connect to ssl-encrypted web sites.  The script is a little bit cooler than others that I have written because not only does it attempt an HTTP Trace request and report back success, failure, or other information but it also tests for HTTP Track.  The script right now only assumes that you'll be testing against a well known ssl port, unfortunately, so your web server will need to be running ssl on port 443.  Otherwise, the port is assumed to be an HTTP port.   It should help you satisfy those security and compliance administrators who demand proof that both methods are disabled, (even though TRACK does not really exist anywhere any more).

This script is now available on the Downloads page and test4trac.pl has it's own information page now.

#!/usr/bin/perl 
#===============================================================================
#
#         FILE:  test4trace.pl
#
#        USAGE:  ./test4trace.pl  
#
#  DESCRIPTION:  The "UI" for this script may not
#                make sense but this is a sub
#                routine of a future version of my
#                cryptonark script that tests for
#                the existence of the TRACE method
#                on a web site.  That's why,
#                syntactically, this script follows
#                cryptonark's syntax and version
#                numbering.
#
#      OPTIONS:  ---
# REQUIREMENTS:  Perl 5.10 & LWP::UserAgent
#         BUGS:  None Found Yet
#        NOTES:  ---
#       AUTHOR:  Chris Mahns
#      COMPANY:  Blogging Techstacks
#      VERSION:  0.3
#      CREATED:  11/03/2009 21:45:30
#     REVISION:  ---
#===============================================================================

use strict;
use warnings;
use feature ':5.10';

use LWP::UserAgent;

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

my $help = "Usage:  $0  ";

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

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

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

    my $method = "TRACE";
    my $ua     = LWP::UserAgent->new;
    $ua->timeout(10);
    $ua->env_proxy;
    $ua->agent('test4trace-pci-auditor/v0.3');
    
    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('test4trace-pci-auditor/v0.3');
    
    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;
        }
    }
}
say "First we test for Trace...";
sleep 2;
test_for_trace();

say "\nNow we test for Track...";
sleep 2;
test_for_track();

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a01156fbc6fe6970c0120a6a82200970c

Listed below are links to weblogs that reference Testing for Trace and Track:

Comments