If you work in a fairly large organization or manage a large number of heterogeneous servers like I do, there is a very good chance you're going to have some IIS 5.0 sites hanging around. If you've been involved in PCI remediation activities, chances are also very good that you've been tagged with the "WebDAV HTTP Method PROPFIND Enabled" vulnerability.
WebDAV HTTP Method PROPFIND Enabled is an information disclosure issue. A malformed request will result in the internal IP address (and port) of your web server being displayed, which is something the Information Security & Compliance folks get antsy over. The 'malformed' request required to prove the existence of the vulnerability isn't all that sophisticated—it is simply an HTTP PROPFIND request to the root of the web site with an empty Host request header and a content length set to 0. Send that along to your vulnerable IIS 5.x web site and you've got yourself an internal IP address (and port if not bound to a well-known port).
Mitigation is pretty easy but, as is all too often the case, a bit draconian. Disable WebDAV entirely. The Microsoft KB Article: How to disable WebDAV for IIS 5.x contains all the information you need to disable WebDAV on IIS 5, so I won't go into details on how to do it in this post. However, you might be interested in seeing the issue for yourself and verifying that it is not a false positive or maybe your company's change management procedures require you to verify your change was successful. If so, the script below may help (or grab it off the downloads page).
Execute with the host and port arguments. If server is vulnerable, it will display an HTTP 207 status code along with the internal IP Address found. This is still version 0.1—it works but I could be making modifications to it again in the future. This version has been tested on Perl 5.10 and is dependent on LWP::UserAgent and XML::LibXML.
UPDATE: (July 27, 2011) - Version 0.1.1 released, which sets a port number on all requests so you can run this script successfully against ports other than well-known ports.
#!/usr/bin/env perl
use strict;
use warnings;
use feature ':5.10';
use LWP::UserAgent;
use HTTP::Headers;
use XML::LibXML;
use HTTP::Request;
use HTTP::Response;
my $host = $ARGV[0];
my $port = $ARGV[1];
my $scheme;
my $help = "Usage: $0 <hostname> <port>";
if ( !@ARGV ) {
print $help . "\n";
exit 0;
}
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:$port/";
my $method = "PROPFIND";
my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->env_proxy;
$ua->agent('propfind-pci-auditor/v0.1.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 "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.";
}
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;
}
}