#!/usr/local/bin/perl5 
# -- -*-perl-*-
#
##########################################################################
#  phf perl script used to try to find out as much info from the person
#   calling the script as possible.  Only reason for using phf on the
#   system is to exploit a bug to execute commands.
# 
#  contribitors:
#    Ray W. Hiltbrand	Jul 17 1996  Ray.W.Hiltbrand@Eng.Auburn.EDU
#    Doug Hughes		     doug@Eng.Auburn.EDU
#    Paul Danckaert		     pauld@lemur.org
#    Pierre Beyssac		     pb@hsc.fr
#    
#
#	Comments and orig source can be found at:
#       http://www.eng.auburn.edu/users/rayh/software/phf.html
#       ftp://ftp.eng.auburn.edu/pub/rayh/security/phf
#
#  All rights reserved.  1996
#
#  Email comments, changes, enhancements to Ray.W.Hiltbrand@Eng.Auburn.EDU
#
# Change Log:
#    19960715 Created
#    19960717 Added Ident support and safe_finger support
#    19960926 Added support for builtin finger or safe_finger
#	      Added ability to turn off parts of script 
#		(ie finger, ident, fake)
#	      Added fake PHF HTML code
#		From:Paul Danckaert <pauld@lemur.org>
#	      Added additional return type for fake PHF
#		From:Paul Danckaert <pauld@lemur.org>
#   19961016  Changed netstat to use IP only speed improvement -n option
#		From:Christopher Ellwood <chris@silicon.net> 
#   19961106  Converted to use perl5 
#   19961016 Action parsing fixes
#               From:Tom Perrine <tep@SDSC.EDU>
#   19961107  Added another expression to catch for on fake phf
#             Fixed exit to return in cat passwd expression in fakePHF
# 		From:Tom Perrine <tep@SDSC.EDU>
#
##########################################################################
require 5.002;
use Socket;
#
#Set this to the email address that will receive alert.
$SECUREADDRESS="username\@somewhere.domain";
#
# This should match the mail program on your system.
$mailprog = '/usr/lib/sendmail';
#
# Location of safe_finger or call builtin finger
#  Comment out $finger if you want to use the builtin finger.
#  Define $finger for location of finger. Ex below.
#  Set $finger to NONE if you don't wish to use finger.
#$finger="/etc/local/safe_finger -l";
#
#
# Uncomment if you do not want ident support
#$ident="NONE";
#
# Need netstat to find the port of the remote address
$netstat="/usr/bin/netstat -n -a -f inet";
#
# Need a grep to look for remote addres (This is lazy man way)
$grep="/usr/bin/fgrep";
#
# IP address  of machine web server running (Must be IP address)
$web_server="000\.000\.000\.000";
#
# Port web server runs on
$web_port="80";
#
# Uncomment if you do not want fakephf support.
#$fakephf="NONE";

#####End Configuration Section################################
#(nothing below should need to be changed except fake password file at the end
# if you are using the fakephf option)


# Call the fake PHF now
$action = "";
if ( "$fakephf" ne "NONE" ) { 
	$query = $ENV{'QUERY_STRING'};
	FakePHF();
}

#
#Initalize mail message to secureaddres
#
open (MAIL, "|$mailprog $SECUREADDRESS") or die "Can't open $mailprog!\n";
print MAIL "To: $SECUREADDRESS\n";
print MAIL "From: $SECUREADDRESS\n";
print MAIL "Subject: $ENV{'REMOTE_HOST'} phf access $action\n\n";
print MAIL "\n";
print MAIL  "------------------------------------------------------------\n";
#
#Send basic information
#
print MAIL "Remote host: $ENV{'REMOTE_HOST'}\n";
print MAIL "Remote IP address: $ENV{'REMOTE_ADDR'}\n";
print MAIL "Query String: $ENV{'QUERY_STRING'}\n";
print MAIL "Action Type: $action\n";

#
#Try to finger the host so we can try to get a list of users
# on the machine doing the probe
#
if ( "$finger" ne "NONE" ) { 
	print MAIL "Finger info: \n";
	if ("$finger" ne "") {
		$fingerinfo = `$finger \@$ENV{'REMOTE_ADDR'}`;
		print MAIL "$fingerinfo\n";
	} else {  #use builtin finger
		GetFingerInfo(); 
	}
}
#
# Call Ident stuff
#
if ("$ident" ne "NONE" ) {
       GetIdentInfo();
}
print MAIL "\n------------------------------------------------------------\n";

close (MAIL); 
exit; 



# Pseudo-Phf  -  A not-quite-real phf replacement that provides a warning
#                       against attacks, as well as presenting false
#                       information to the attacker.
#
# Paul Danckaert (pauld@lemur.org)
#
# Extended with fake "id" and "uname" info. <Pierre.Beyssac@hsc.fr>
#
###
sub FakePHF {

	print "Content-type: text/html\n\n";
	$hacker = 0;
        if ($query =~ /cat.*(\/|%2f)passwd/i) {
		$action = "Attempted Password Grab";
                ShowBadPass();
		$hacker = 1;
        } 
	if ($query =~ /whoami/i) {
                print "root\n";
                $action = "Attempted WHOAMI Command";
		$hacker = 1;

        } 
	if ($query =~ /(\/|%2f|%0a)id/i) {
		ShowBadId();
                $action = "Attempted ID Command";
		$hacker = 1;
        } 
	if ($query =~ /xterm/i) {
                print "Command not found.\n";
                $action = "Attempted XTERM Command";
		$hacker = 1;
        } 
	if ($query =~ /cat/i) {
                print "Command not found.\n";
                $action = "Trying to cat something";
		$hacker = 1;
	}	
	if ($query =~ /server/i) {
		print "/usr/local/bin/phf not found\n";
                $action = "Submit Form";
		$hacker = 1;
	}
	if ($hacker != 1) {
              $action = "Display Form";
	      ShowForm();
	}
}

#
# Procedure used to get Ident info....
#
sub GetIdentInfo {

	$remote = $ENV{'REMOTE_ADDR'};
	$port   = 113; 				#Ident port
	$iaddr  = inet_aton($remote);
	$paddr  = sockaddr_in($port, $iaddr);
	$proto	= getprotobyname('tcp');

	#Now lets check to see if system is ident capable. This takes
	# a little time.

	print MAIL "Ident: \n";
	$remport=`$netstat | $grep $ENV{'REMOTE_ADDR'} | $grep $web_server.$web_port | $grep ESTABLISHED`;
	$remport =~ s/.*$web_server\.$web_port.*$ENV{'REMOTE_ADDR'}\.([0-9]*).*/$1/s;
	$sendstr = "$remport , $web_port\r";
	socket(S, PF_INET, SOCK_STREAM, $proto) or  print MAIL "socket: $!\n";
	if (connect(S, $paddr)) {
    		send(S, $sendstr, 0) or print MAIL "data: $!\n";
    		recv(S, $recvstr, 180, 0) or print MAIL "receiving data: $!\n";
	
    		print MAIL "$recvstr\n";
	} else {
    		print MAIL "no ident info\n";
	}
}

#
# Get finger info if using builtin finger
#
sub GetFingerInfo {
#
#Setup socket stuff so we can use finger later
#
	$remote = $ENV{'REMOTE_ADDR'};
	$port   = 79; 				#Finger port
	$iaddr  = inet_aton($remote);
	$paddr  = sockaddr_in($port, $iaddr);
	$proto	= getprotobyname('tcp');
	$sendstr ="\n\@$ENV{'REMOTE_ADDR'}";
	socket(S, PF_INET, SOCK_STREAM, $proto) or  print MAIL "finger socket: $!\n";
	if (connect(S, $paddr)) {
    		send(S, $sendstr, 0) or print MAIL "data: $!\n";
    		recv(S, $recvstr, 180, 0) or print MAIL "receiving data: $!\n";
   		print MAIL "$recvstr\n";
	} else {
    		print MAIL "no finger info\n";
	}   
}
sub ShowForm {

print <<"EOF";
<TITLE>Form for CSO PH query</TITLE>
<H1>Form for CSO PH query</H1>
This form will send a PH query to the specified ph server.
<P>
<HR>
<FORM ACTION="/cgi-bin/phf">
PH Server:<INPUT TYPE="text" NAME="Jserver" VALUE="ns.uiuc.edu" MAXLENGTH="256">
<P>
<H3>At least one of these fields must be specified:</H3><UL>
<LI><INPUT TYPE="text" NAME="Qalias" MAXLENGTH="32">Alias
<LI><INPUT TYPE="text" NAME="Qname" MAXLENGTH="256">Name
<LI><INPUT TYPE="text" NAME="Qemail" MAXLENGTH="128">E-mail Address
<LI><INPUT TYPE="text" NAME="Qnickname" MAXLENGTH="120">Nickname
<LI><INPUT TYPE="text" NAME="Qoffice_phone" MAXLENGTH="60">Office Phone Number
<LI><INPUT TYPE="text" NAME="Qcallsign" MAXLENGTH="16">HAM Callsign
<LI><INPUT TYPE="text" NAME="Qproxy" MAXLENGTH="64">Proxy
<LI><INPUT TYPE="text" NAME="Qhigh_school" MAXLENGTH="30">High School
<LI><INPUT TYPE="text" NAME="Qslip" MAXLENGTH="256">SLIP Address
</UL>
<A HREF="/cgi-bin/phf?Jform=16"><H3>Show additional fields to narrow query</H3></A>
<P>
<A HREF="/cgi-bin/phf?Jform=1"><H3>Return more than default fields</H3></A>
<P>
<INPUT TYPE="submit">
</FORM>
<HR>
<ADDRESS>Questions, comments to: <a href="http://www.ncsa.uiuc.edu/SDG/People/jbrowne/jbrowne.html">Jim Browne</a>
</ADDRESS>
EOF

}

sub ShowBadId {
        print "uid=0(root) gid=0(wheel)\n";
}

sub ShowBadUname {
        print "FreeBSD ns.mysite.org 2.1.0-RELEASE FreeBSD 2.1.0-RELEASE #0: Sun May 26 22:17:58 MET DST 1996     root\@ns.mysite.org:/usr/src/sys/compile/VALERIAN  i386\n";
}

sub ShowBadPass {

print <<"EOF";
root:9IDv/CqdFuqWo:0:0:Super User:/:/bin/csh
sysadm:*:0:0:System V Administration:/usr/admin:/bin/sh
diag:*:0:996:Hardware Diagnostics:/usr/diags:/bin/csh
daemon:*:1:1:daemons:/:/dev/null
bin:*:2:2:System Tools Owner:/bin:/dev/null
uucp:*:3:5:UUCP Owner:/usr/lib/uucp:/bin/csh
fax:*:3:10:Fax:/var/spool/fax:/bin/sh
sys:*:4:0:System Activity Owner:/var/adm:/bin/sh
adm:*:5:3:Accounting Files Owner:/var/adm:/bin/sh
lp::9:9:Print Spooler Owner:/var/spool/lp:/bin/sh
nuucp::10:10:Remote UUCP User:/var/spool/uucppublic:/usr/lib/uucp/uucico
auditor:*:11:0:Audit Activity Owner:/auditor:/bin/sh
dbadmin:*:12:0:Security Database Owner:/dbadmin:/bin/sh
rfindd:*:66:1:Rfind Daemon and Fsdump:/var/rfindd:/bin/sh
demos::993:997:Demonstration User:/usr/demos:/bin/csh
OutOfBox::995:997:Out of Box Experience:/usr/people/tour:/bin/csh
guest::998:998:Guest Account:/usr/adm/guest:/bin/csh
nobody:*:60001:60001:Nobody:/dev/null:/dev/null
noaccess:*:60002:60002:uid no access:/dev/null:/dev/null
nobody:*:-2:-2:original nobody uid:/dev/null:/dev/null
www:*:20:10:The Web Slinger:/web/www:/bin/csh
webadmin:ecKu77KmsNALs:0:0:Sysadmin web account:/:/bin/sh
testact::1000:10:Test Account:/:/bin/sh
ftp:*:60001:60001:FTP ACCOUNT:/ftp:/dev/null
EOF

}
