8 posts categorized "Disable TRACE"

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();

09/27/2009

New HOWTO Article on Disabling Trace and Track on a BigIP

I have just uploaded a new article for those of you looking to disable trace and track on your BigIP-managed VIPs onto my HOWTO mini-site. The article is located here.

10/14/2008

TRACE Method Handling - Disabling TRACE

I have many articles posted on this blog for handling http trace methods. Since they are amongst the most popular on this site, I thought it would be helpful to consolidate them into something better suited for reference. Also, since it is a vulnerability that frequently turns up on PCI Compliance scans, I thought it would be useful to provide one base page that searches can be directed to. Less page views for me but hopefully easier searching for everyone else.

To start, I updated the ruby script I wrote to test to see how a site responds to HTTP TRACE requests. The previous script can be found here and below is the update:

#!/usr/bin/env ruby
require 'net/http'

puts "\nEnter the URL for the site"
puts "(Format should be 'http://siteURL/')"
name = gets

url = URI.parse(name)
begin
req = Net::HTTP::Trace.new(url.path)
resp = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
rescue Errno::ECONNRESET, Errno::ECONNABORTED
puts "Your iRule Works!! Connection Dropped!"
exit
end

# Case statement - delivers response based on status code
# returned from site assuming irule not used or needed
statuscode = resp.code
result = case statuscode
when "200": "TRACE is **probably** enabled"
when "301": "Site is responding with a 301 - Redirect for \"/\""
when "302": "Site is responding with a 302 - Redirect for \"/\""
when "403": "TRACE is disabled. 403 Forbidden"
when "404": "TRACE is probably disabled. 404 Not Found"
when "405": "TRACE is disabled. 405 Method Not Allowed Response"
when "501": "TRACE is disabled. 501 Not Implemented Response."
else "Unexpected Response."
end

From what I've learned in my research over the past few months as well as experimentation on my own sites, you can expect several different types of responses to TRACE requests based upon site platform and site layout architecture.

If you are running IIS4 or IIS5 or any version of Apache, by default the TRACE method is enabled. The best way you can disable it in IIS4 and IIS5 is by installing URLScan. Remediation in apache can be done in two different ways. One method involves setting the TraceEnable directive to Off. This only works if you are running a more recent version, (Apache 1.3.34, 2.0.55 and later). The other mechanism that works on all apache versions that support mod_rewrite involves writing a condition and rule to forbid trace requests:

RewriteEngine on 
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]

If you are running IIS6 or IIS7, the TRACE method is disabled. If you are running Tomcat, Glassfish, or JBoss Application Server as the front-end for your sites, the TRACE method is disabled by default. The status code returned by IIS6/7 is different from tomcat, however. IIS responds with a 501 status code while tomcat responds with a 405 status code.

If you load-balance your websites with a BigIP, you can write an iRule that will discard all TRACE methods and assign that rule to all of your VIPs. A basic iRule that drops TRACE requests looks something like this:

when HTTP_REQUEST {
set default_pool [LB::server pool]
if { [HTTP::method] equals "TRACE" } {
reject
} else {
pool $default_pool
}
}

The action that the rule takes when the condition is met is to drop the packet. From a network sniffer standpoint, you will see the BigIP issue a connection reset when a TRACE request is sent to a VIP that is utilizing this particular iRule.

The script above allows me to determine which of my sites are vulnerable to TRACE requests and, depending upon the remediation steps taken, gives me a mechanism for validating those changes. Since all of my sites are front-ended with a BigIP, I can simply utilize the iRule to drop those requests and validate by trapping the connection reset but with the addition of better handling of responses pre- and post-remediation, the script becomes more portable to validate remediation actions for a larger number of possible site configurations. Want to validate that apache is responding as expected after setting TraceEnable to Off? This should do it. Do you want to verify that URLScan is working? This script should do it.

The script should not follow redirects, which is helpful in false-positive determination. However, when a redirect is issued, you should re-run the script against the redirect target. In other words, if "http://yoursite.yourdomain.com/" redirects to "http://yoursite.yourdomain.com/home/", running the script against the former should result in either a 301 or 302 response. So, execute the script against "http://yoursite.yourdomain.com/home/" directly instead.

Instead of coming out with a page for each platform and another page for updates, this page will serve as the anchor page for TRACE and any updates will be made directly to this page instead. All the other pages will be updated to link to this one.