#!/bin/bash RAMENFINDVERSION="0.4" #TODO: #- Testing on a number of infected, partially infected, and uninfected systems. #- merge delete requests together? #- askfirst logging? #Handled in V0.4: #- New ramen variant. *sigh* # - creates /usr/sbin/update, which kills off the trojan lpd and restarts it. # - Doesn't remove index.html's # - new crontab entry: run update every minute of the first day of the month # - new crontab entry: nuke synscan every minute of 1am. # - mail /etc/shadow off to "chicha" and "libero" accounts and wipe entries from maillog # - Runs "2", which appears to mail off notices to two email accounts # - /usr/bin/lpd run on future boots from rc.sysinit. # - move netstat to /usr/lib/ldlibns.so # - replace netstat with a wrapper c app that discards certain lines: # "/usr/lib/ldlibns.so {parameters} | grep -v ftp | grep -v 28593 | grep -v 212.102 # | grep -v b92 | grep -v 147.91 | grep -v grep | grep -v ldlibns|grep -v -- -i" # - Move ps to /usr/lib/ldlibps.so # - replace ps with a wrapper c app that discards certain lines: # "/usr/lib/ldlibps.so {parameters} | grep -v tail | grep -v ipsc | grep -v synscan | # grep -v .sh | grep -v grep | grep -v ldlibps | grep -v -- -i" # - Move /bin/login to /usr/lib/ldliblogin.so and replaces it with a trojan # - copies "td" to /usr/bin/lpd (normal path is /usr/sbin/lpd) and runs it. # - Stacheldracht agent. Ugh. # - Did I say "Ugh." already? # - From binary: "Ports are set to send and receive on port 179" (bgp) # - Minor changes to scan.sh (no changes needed to Ramenfind). #Notes: #netstat -tlnp #Careful; netstat may have been trojanized. #netstat -ulnp #lsof -i TCP:27374 #Banner. echo '====' Ramenfind '====' echo Version $RAMENFINDVERSION echo A script to report on the existence of the Ramen worm and optionally echo archive and/or remove the it from the current system. echo Copyright 2001 William Stearns \, echo Released under the GNU General Public License \(GPL\). echo Updated versions may be found at the echo Institute for Security Technology Studies echo \(http://www.ists.dartmouth.edu/IRIA/knowledge_base/tools/ramenfind.html\), echo and SANS \(http://www.sans.org/y2k/ramen.htm\), and echo Linuxlock \(http://www.linuxlock.org/features/ramenfix.html\) echo Many thanks to Justin Mason for the perl port connect code. echo Usage help may be obtained with \"$0 -h\". OFFENDINGFILES="" OFFENDINGDIRS="" RAMENPATHPIDS="" SHELLPIDS="" ALLPIDS="" DISTRIBUTION="" RESPONSE="" ARCHIVE="NO" DELETE="NO" CONFIRM="NO" RPMUPGRADE="NO" KILL="NO" OLDUMASK="" TMPFILE="" MISSINGAPPS="" ALLDATAFILES="" BADRPMS="" VULNERABLERPMS="" RPMLIST="" ORGREP="" TAILPIDS="" FTPUSERS="" INETDASP="" ROOTUPDATE="" RCSYSINITSTART="" FTPUSERSANONYMOUS="" #Hi, I'm Bill, and I'm an ftp user. RCSYSINITLPD="" SUSPICIOUSFILES="/etc/xinetd.d/asp /usr/src/.poop/* /usr/src/.poop/.[a-zA-Z0-9]* /tmp/ramen.tgz /usr/sbin/asp /sbin/asp /usr/sbin/update /usr/bin/lpd" SUSPICIOUSDIRS="/usr/src/.poop/" NASTYAPPS="asp asp62 asp7 bd62.sh bd7.sh getip.sh hackl.sh hackw.sh index.html l l62 l7 lh.sh randb randb62 randb7 s s62 s7 scan.sh start.sh start62.sh start7.sh synscan synscan62 synscan7 w62 w w7 wh.sh wu62" #The above list contains one command - w - that might reasonably be running on a Linux system. #As this is generally run as a transient shell command, I'm not too concerned about killing it. if [ "$EUID" = "0" ]; then PRECOMMAND="eval" else if type -path sudo >/dev/null ; then PRECOMMAND="eval sudo" else echo This script is not running as root and the sudo command is not echo available. Please install the sudo command or run it as root. echo $0 exiting. exit 1 fi fi if [ ! -d /proc/1 ]; then echo WARNING! Proc filesystem not supported or not mounted. Please fix and restart. echo $0 exiting. exit 1 fi askfirst () { #- Asks the user if they would like to perform the command given as #parameters or on stdin (call with sole paremeter of "-"). #- Return code is the return code of the command, #127 if no command or 126 if user chooses to not run the command. #- All user IO is done on stderr; something like: # askfirst ls -al "2>&1" | tee -a /tmp/teefile #allows you to log all output from the command. #- Set ASKFIRSTHELP to some hint as to why you're asking the user to #run this. No problem if left blank. It should be the answer to the #question, "Why do you want me to run this?" #- If your sudo command is something other than "sudo", set #SUDO="/path/to/sudo" #- askfirst can be used in any step of a pipeline. It can even #be used in multiple steps, but the user prompts get mixed together. unset DOTHIS if [ $# -eq 0 ]; then echo 'askfirst invoked without any parameters; use at least "-" to read ' >/dev/stderr echo 'command from stdin.' >/dev/stderr else if [ "z$*" = 'z-' ]; then #command given on stdin - we hope ;-) read DOTHIS else DOTHIS="$*" fi fi if [ -z "$DOTHIS" ]; then return 127 fi SUDO=${SUDO:-"sudo"} AVAILABLEOPTIONS="(Y/N/" SUDOHELP="" if [ "$EUID" != "0" ]; then #Little point in asking root if they want to use sudo. #Cannot put quotes around "sudo *"; use backslash escape instead case "$DOTHIS" in #No point in asking for sudo if sudo already there. $SUDO\ *|/usr/bin/sudo\ *) : ;; *) AVAILABLEOPTIONS="${AVAILABLEOPTIONS}S/" SUDOHELP="S\tRun the command under sudo" ;; esac fi AVAILABLEOPTIONS="${AVAILABLEOPTIONS}E/?)" unset FINISHED while [ "$FINISHED" != "YES" ]; do echo " Shall I run \"$DOTHIS\"" >/dev/stderr echo -n " as $USER in `pwd` ${AVAILABLEOPTIONS}:" >/dev/stderr unset CHOICE #Reading from stderr falls in the "decidedly cheesy" category and would probably #give the POSIX group heart murmurs, but it does work on Linux and frees up stdin #for feeding in the command to run. read CHOICE /dev/stderr AFRETVAL=126 #False; command failed, in a sense. FINISHED="YES" ;; S|s) eval "$SUDO $DOTHIS" AFRETVAL="$?" FINISHED="YES" ;; E|e) echo " NOT running \"$DOTHIS\"" >/dev/stderr echo " $0 exiting at user request." >/dev/stderr exit 1 ;; ?) echo " " >/dev/stderr if [ -n "$ASKFIRSTHELP" ]; then echo " Here is why you're being asked to run this:" >/dev/stderr echo " $ASKFIRSTHELP" >/dev/stderr fi echo " Here are your options:" >/dev/stderr echo -e " Y\tYes, run the command" >/dev/stderr echo -e " N\tNo, do not run the command" >/dev/stderr if [ -n "$SUDOHELP" ]; then echo -e " $SUDOHELP" >/dev/stderr fi echo -e " E\tExit the program completely and don't run the command" >/dev/stderr echo -e " ?\tShow this help" >/dev/stderr ;; *) echo " Unrecognized choice." >/dev/stderr ;; esac done return $AFRETVAL } checkforline () { #Looks for known bad line(s) added to normally good system files and warns if the lines are there. #Parameters: file_to_check, line_to_look_for, how_to_make_changes_take_effect #Return value: 0 if file exists and line(s) there, 1 if file exists and lines not there, 2 if file not there. if ASKFIRSTHELP="Check if $1 exists - needs to be run as root if only root can see it." $PRECOMMAND test -f "$1" ; then if $PRECOMMAND cat "$1" | egrep -q "$2" ; then echo Your $1 file contains a line containing \"$2\". if [ "$DELETE" = "NO" ]; then echo You are strongly encouraged to remove this line. if [ -n "$3" ]; then echo $3 fi else #DELETE=YES echo This line will be removed in a moment. fi CFRETVAL=0 else #$1 exists, but doesn't have this line. echo Your $1 does not have the \"$2\" line, good. CFRETVAL=1 fi else echo Your system does not have the \"$1\" file. CFRETVAL=2 fi return $CFRETVAL } delline() { #Params: $1 File that needs the line removed, $2 line to remove (may be a partial line). #Example: delline somefile '.*' #Remove all lines, essentially ">somefile" but using sudo. if [ "$#" != "2" ]; then echo Incorrect number of arguments to delline! >/dev/stderr else if ASKFIRSTHELP="Check if $1 exists - needs to be run as root if only root can see it." $PRECOMMAND test ! -f "$1" ; then echo "$1" doesn\'t exist, can\'t remove \"$2\". >/dev/stderr elif $PRECOMMAND cat "$1" | grep -q "$2" ; then echo "Removing \"$2\" from $1" >/dev/stderr OLDUMASK=`umask` umask 177 TMPFILE=`mktemp -q /tmp/delline.XXXXXX` umask $OLDUMASK if [ $? -ne 0 ]; then echo "$0: Can't create temp file, exiting..." exit 1 fi $PRECOMMAND cat "$1" >$TMPFILE cat "$TMPFILE" | grep -v "$2" | $PRECOMMAND dd of="$1" '2>/dev/null' /bin/rm -f "$TMPFILE" else echo \"$2\" is not in "$1" - not removing. >/dev/stderr fi fi } restorefrombackup () { #This function restores a file from a backup. #Parameters: Bad_Original_file, Good_Backup_file if ASKFIRSTHELP="Check if $2 exists - needs to be run as root if only root can see it." $PRECOMMAND test -f "$2" ; then echo Restoring \"$1\" from \"$2\" backup. if ASKFIRSTHELP="Check if $1 exists - needs to be run as root if only root can see it." $PRECOMMAND test -f "$1" ; then ASKFIRSTHELP="Remove likely corrupted $1 ." $PRECOMMAND rm "$1" fi ASKFIRSTHELP="Restore $1 from $2 backup." $PRECOMMAND mv "$2" "$1" #else #$2 doesn't exist # echo \"$2\" doesn\'t exist - cannot restore \"$1\". fi } showhelp () { echo Usage: $0 [options] echo -e '\t-a\tArchive offending files.' echo -e '\t-c\tConfirm each command that affects the system before running it.' echo -e '\t-d\tDelete offending files and kill running processes.' echo -e '\t-r\tRpm upgrade only rpms vulnerable to Ramen.' echo -e '\t-h\tHelp' echo If invoked without any options, Ramenfind will simply report echo on whether ramen was detected on the current system and indicate echo what needs to be done to remove it, without performing any action echo on the system. echo To remove ramen from the filesystem, the following is recommended: echo $0 -c -d -r echo $0 does NOT need to be run as root, as long as the user under echo which it is run has sudo rights to run cat, ls, grep, sed, tr, echo egrep, awk, ps, sort, uniq, find, lsattr, rpm, test, and nc or perl echo \(and, depending on options, mktemp, tar, rm, rmdir, dd, kill, echo killall and touch\). } tcpportopen () { #Parameters: ip/hostname, tcp port #Returns 0 (True) if port open, 1 (False) if port closed, 2 if unable to check. if type -path nc >/dev/null ; then echo | ASKFIRSTHELP="Attempt to connect to tcp port $2 on $1 to see if a daemon is listening - does not need to be run as root." $PRECOMMAND nc $1 $2 '>/dev/null' '2>/dev/null' case $? in 0) return 0 ;; 1) return 1 ;; *) return 2 ;; esac elif type -path perl >/dev/null ; then #The following is a fallback if the quoting on the inline perl fails to work. #TMPFILE=`mktemp -q /tmp/perl_socket_test.XXXXXX` #if [ $? -ne 0 ]; then # echo "$0: Can't create temp file, exiting..." # exit 1 #fi #echo ' # sub echoconn { # use Socket; # my ($remote, $port, $string) = @_; # my $iaddr = inet_aton($remote) or die "no host: $remote"; # my $paddr = sockaddr_in($port, $iaddr); # my $proto = getprotobyname("tcp"); # socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; # connect (SOCK, $paddr) or die "connect: $!"; # print SOCK $string; # close SOCK or die "close failed: $!"; # } # echoconn (@ARGV); #' > $TMPFILE #ASKFIRSTHELP="Attempt to connect to tcp port $2 on $1 to see if a daemon is listening - does not need to be run as root." $PRECOMMAND perl $TMPFILE $1 $2 "" '>/dev/null' '2>/dev/null' #_DO_ _NOT_ touch the quoting; getting it correct is a pain. ASKFIRSTHELP="Attempt to connect to tcp port $2 on $1 to see if a daemon is listening - does not need to be run as root." $PRECOMMAND perl -e \'' sub echoconn { use Socket; my ($remote, $port, $string) = @_; my $iaddr = inet_aton($remote) or die "no host: $remote"; my $paddr = sockaddr_in($port, $iaddr); my $proto = getprotobyname("tcp"); socket (SOCK, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; connect (SOCK, $paddr) or die "connect: $!"; print SOCK $string; close SOCK or die "close failed: $!"; } echoconn (@ARGV); '\' $1 $2 "" '>/dev/null' '2>/dev/null' case $? in 0) return 0 ;; 1) echo The call to perl returned 1; is there any chance you do not have echo sudo rights to `type -path perl` ? return 2 ;; 111) return 1 ;; *) return 2 ;; esac else echo Neither nc nor perl was found on this system; unable to check if echo tcp port $2 is open on $1. return 2 fi } #All the following needed even for checking the system. NEEDEDAPPS="cat ls grep sed tr egrep awk ps sort uniq find lsattr rpm test" #We check for nc / perl in a minute. #Check for command line parameters. until [ -z "$*" ]; do case "$1" in -[Aa]) ARCHIVE="YES" echo \"Archive\" option chosen. shift NEEDEDAPPS="$NEEDEDAPPS mktemp tar" ;; -[Cc]) CONFIRM="YES" PRECOMMAND="askfirst" echo \"Confirm\" option chosen. shift ;; -[Dd]) DELETE="YES" KILL="YES" echo \"Delete files and kill processes\" option chosen. shift #Gee, we risk whining about mktemp twice. Sue me. :-) NEEDEDAPPS="$NEEDEDAPPS rm rmdir mktemp dd kill killall touch mv" ;; -[Hh]|--[Hh][Ee][Ll][Pp]) showhelp echo $0 Exiting. exit 1 ;; -[Rr]) RPMUPGRADE="YES" echo \"RPM upgrade only Ramen vulnerable rpms\" option chosen. shift ;; *) echo Unknown command line parameter "$1" showhelp echo $0 Exiting. exit 1 ;; esac done for ONEAPP in $NEEDEDAPPS ; do if ! type -path $ONEAPP >/dev/null ; then MISSINGAPPS="$MISSINGAPPS $ONEAPP" fi done if type -path nc >/dev/null ; then : elif type -path perl >/dev/null ; then : else MISSINGAPPS="$MISSINGAPPS nc-or-perl" fi if [ -n "$MISSINGAPPS" ]; then echo This script needs the following support apps which do not appear to be echo installed on your system. echo $MISSINGAPPS #I want to provide a way out in case their terminal does not support Ctrl-C's break. echo Do you wish to continue? If so, simply press Enter. If not, press echo Ctrl-C \(or type \"QUIT\" without the quotes\), install these support echo apps, and restart $0 . read RESPONSE case $RESPONSE in [Qq][Uu][Ii][Tt]) echo Exiting at user request. Usage help is available by typing: echo "$0 -h" exit 1 ;; esac RESPONSE="" fi #If the user selected _any_ options, double check that they chose the ones they want. #If they selected no options, the script won't actually _do_ anything, so I won't #stop them to ask. if [ "$ARCHIVE" = "YES" ] || [ "$CONFIRM" = "YES" ] || [ "$DELETE" = "YES" ] || [ "$KILL" = "YES" ]; then if [ "$ARCHIVE" = "NO" ]; then echo \"Archive\" option NOT chosen. fi if [ "$CONFIRM" = "NO" ]; then echo \"Confirm\" option NOT chosen. fi if [ "$DELETE" = "NO" ]; then echo \"Delete\" option NOT chosen. fi if [ "$KILL" = "NO" ]; then echo \"Kill\" option NOT chosen. fi if [ "$RPMUPGRADE" = "NO" ]; then echo \"RPM upgrade only Ramen vulnerable rpms\" option NOT chosen. fi echo Are these the choices you wanted? If so, press enter. If you would echo like to reselect your options, press Ctrl-C or type \"QUIT\" without echo the quotes and press Enter. read RESPONSE case $RESPONSE in [Qq][Uu][Ii][Tt]) echo Exiting at user request. Usage help is available by typing: echo "$0 -h" exit 1 ;; esac fi if [ -f /etc/redhat-release ] && [ "`cat /etc/redhat-release`" = "Red Hat Linux release 6.2 (Zoot)" ]; then echo Redhat Linux 6.2 system detected. DISTRIBUTION="RH62" BADRPMS="nfs-utils-0.1.6-2 wu-ftpd-2.6.0-3" elif [ -f /etc/redhat-release ] && [ "`cat /etc/redhat-release`" = "Red Hat Linux release 7.0 (Guinness)" ]; then echo Redhat Linux 7.0 system detected. DISTRIBUTION="RH70" BADRPMS="LPRng-3.6.22-5" else echo This system does not appear to be a Redhat 6.2 or 7.0 system. echo As these two distributions are specifically targeted by Ramen, this echo system is less likely to be infected. Proceeding anyways. echo Note - this script will not be able to perform rpm upgrades. RPMUPGRADE="NO" fi #RH 6.2 or 7.0? echo Locate Ramen related files and directories... for ONEFILE in $SUSPICIOUSFILES ; do if [ -e $ONEFILE ]; then OFFENDINGFILES="$OFFENDINGFILES $ONEFILE" fi done for ONEDIR in $SUSPICIOUSDIRS ; do if [ -d $ONEDIR ]; then OFFENDINGDIRS="$OFFENDINGDIRS $ONEDIR" fi done #If the program executable was run from one of the SUSPICIOUSDIRS, it's a prime candidate for killing. echo Check for programs run from $SUSPICIOUSDIRS... if [ "$PRECOMMAND" = "eval sudo" ]; then echo The sudo command may ask you for your regular password. fi if [ "$PRECOMMAND" = "askfirst" ] && [ "$EUID" != "0" ]; then echo If you agree that you would like to run a particular command, echo you should probably choose \"S\" to run it under sudo echo rather than \"Y\" to run it as yourself. Most of the echo upcoming commands need to be run as root to collect complete echo information or run at all. fi LSSTORE="`ASKFIRSTHELP='I need to run ls as root to see all users processes.' $PRECOMMAND ls -al '/proc/[0-9]*/exe' '2>/dev/null' | grep '\->' | sed -e 's@.*/proc/@@'`" for ONEPATH in $SUSPICIOUSDIRS ; do if [ -n "`echo \"$LSSTORE\" | grep \" $ONEPATH\" | sed -e 's@/exe .*@@'`" ]; then RAMENPATHPIDS="$RAMENPATHPIDS `echo \"$LSSTORE\" | grep \" $ONEPATH\" | sed -e 's@/exe .*@@'`" fi done ORGREP=\(`echo $NASTYAPPS | tr ' ' '|'`\) #Convert list of apps to search for into a list of apps egrep can parse. if [ -f /usr/lib/ldlibps.so ]; then echo WARNING - /bin/ps has likely been replaced with a trojan. I echo will use the backed up version, /usr/lib/ldlibps.so . SHELLPIDS=`/usr/lib/ldlibps.so ax | egrep "[^a-zA-Z\.]$ORGREP$" | awk '{print $1}'` #The following regex should catch only the Ramen tails. TAILPIDS=`/usr/lib/ldlibps.so ax | grep 'tail -f \.[lw]$' | awk '{print $1}'` else echo It does not appear that /bin/ps has been replaced by a trojan, good. SHELLPIDS=`ps ax | egrep "[^a-zA-Z\.]$ORGREP$" | awk '{print $1}'` #The following regex should catch only the Ramen tails. TAILPIDS=`ps ax | grep 'tail -f \.[lw]$' | awk '{print $1}'` fi #Report on what was found. if [ -n "$OFFENDINGFILES$OFFENDINGDIRS" ]; then echo The following suspicious files or directories were found: echo $OFFENDINGFILES $OFFENDINGDIRS else #No suspicious files or dirs found - good! echo None of the following suspicious files or directories were found: echo $SUSPICIOUSFILES $SUSPICIOUSDIRS echo To the best of my knowledge, the Ramen worm is NOT on this filesystem. fi #Suspicious files or dirs found? ALLPIDS="`echo $RAMENPATHPIDS $SHELLPIDS $TAILPIDS | tr ' ' '\012' | sort -n | uniq`" if [ -n "$ALLPIDS" ]; then echo $0 looked for any programs that had been run from $SUSPICIOUSDIRS, #echo was involved in any conversation on tcp port 27374, was listening on that port echo had an executable name matching one in the echo Ramen worm package, or was a tail command invoked by the worm and echo found the following PIDS: if [ -f /usr/lib/ldlibps.so ]; then echo \(WARNING - /bin/ps has likely been replaced with a trojan. I echo will use the backed up version, /usr/lib/ldlibps.so \). #Actually, it appears one does not need to run ps as root: #ASKFIRSTHELP='I need to run ps as root to see all users processes' $PRECOMMAND /usr/lib/ldlibps.so $ALLPIDS else ps $ALLPIDS fi #Add netstat to needed apps list if you reenable the following. #ALSO! netstat may have been trojanized. #ASKFIRSTHELP='I need to run netstat as root to see all users processes' $PRECOMMAND netstat -anp | grep '^tcp' | grep ':27374' echo Note that the test used may be incomplete if you or a previous echo invocation of this script already deleted the programs from echo $SUSPICIOUSDIRS . else #No suspicious pids found - good! echo $0 looked for any programs that had been run from $SUSPICIOUSDIRS, #echo were involved in any conversation on tcp port 27374, were listening on that port echo had an executable name matching one in the Ramen worm package, or echo was a tail command invoked by the worm and did not find any. Note echo that the test used may not work correctly if you or a previous invocation echo of this script already deleted the programs from $SUSPICIOUSDIRS . fi #any PIDS found? checkforline /etc/inetd.conf "^asp[^a-zA-Z0-9]" "You should also restart the inet service." ; INETDASP=$? checkforline /var/spool/cron/root '/usr/sbin/update|killall -9 synscan' "You should also restart the cron service." ; ROOTUPDATE=$? checkforline /etc/rc.d/rc.sysinit "/usr/src/.poop/start[267]*\.sh" "You should also restart the system." ; RCSYSINITSTART=$? checkforline /etc/rc.d/rc.sysinit "/usr/bin/lpd" 'You should also "killall -9 /usr/bin/lpd."' ; RCSYSINITLPD=$? echo Searching filestem for 373 byte index.html\'s. On a full system, echo this may take a while. ALLINDEXES="`ASKFIRSTHELP='Use the find command to find all 373 byte index.html files.' $PRECOMMAND find / -name index.html -a -size 373c`" if [ -n "$ALLINDEXES" ]; then echo The following 373 byte index.html file or files should be checked as they echo may have been replaced by a hacked version. Note - you need to handle these echo by hand as this script does not have access to the originals. echo "$ALLINDEXES" else echo No 373 byte index.html files found, good. fi echo Searching filesystem for .w and .l files. Please be patient. ALLDATAFILES="`ASKFIRSTHELP='Use the find command to find all .w and .l files.' $PRECOMMAND find / -name .w -o -name .l`" if [ -n "$ALLDATAFILES" ]; then echo The following data files, probably created by Ramen, were echo found on your system: echo "$ALLDATAFILES" if [ "$DELETE" = "NO" ]; then echo You are strongly encouraged to remove these files. else #DELETE=YES echo These files will be removed in a moment. fi else #No .w or .l files found echo No .w or .l files were found, good. fi #.w or .l found? if [ ! -f /etc/hosts.deny ]; then echo Your /etc/hosts.deny file has been deleted. You will need to echo recreate this by hand as this script does not have access to the echo original. else #hosts.deny exists if [ -n "`ASKFIRSTHELP="Check to see whether hosts.allow and hosts.deny have been set immutable." $PRECOMMAND lsattr /etc/hosts.allow /etc/hosts.deny | grep '^...i'`" ]; then #If set immutable echo /etc/hosts.deny exists, but one of both of /etc/hosts.allow echo and /etc/hosts.deny has been set immutable. This may be echo an intentional act on your part or may have been performed echo by Ramen \(unconfirmed possibility\). Either way, this may echo hinder your efforts if you need to modify these files. echo The chattr command sets this attribute - see \"man chattr\" echo for more details. else #not immutable echo /etc/hosts.deny exists, good. fi #immutable? fi #hosts.deny exists? #Check versions of nfs-utils, wu-ftpd, LPRng RPMLIST="`ASKFIRSTHELP='The rpm command will report installed software versions, from which I can identify vulnerable packages.' $PRECOMMAND rpm -qa`" for ONERPM in $BADRPMS ; do if [ -n "`echo \"$RPMLIST\" | grep $ONERPM`" ]; then VULNERABLERPMS="$VULNERABLERPMS `echo \"$RPMLIST\" | grep $ONERPM`" fi done if [ -n "$VULNERABLERPMS" ]; then echo The following vulnerable rpm\(s\) were found on your system. echo $VULNERABLERPMS if [ "$RPMUPGRADE" = "YES" ]; then echo This script will attempt to install new versions in a moment. else echo You should pull down the replacement rpms from a Redhat mirror site echo and install them. fi else #No Ramen vulnerable rpms found. if [ -n "$BADRPMS" ]; then echo None of the following known vulnerable rpms were found on your echo system: \"$BADRPMS\". While this is good news, there may still echo be rpms on this system that need to be updated. You should still echo regularly check the Redhat mirrors sites for new rpms to fix echo security issues and sign up for the Redhat-announce mailing list. else echo This script was not able to determine what, if any, rpms on echo your system might be vulnerable to attack by Ramen. You are echo strongly encouraged to regularly visit the mirror site for your echo distribution and install any new packages that fix security holes. echo Signing up for your distribution\'s security announcements list echo may make this easier. fi fi #Any Ramen vulnerable rpms found? #Try to connect to localhost:27374 and report server. tcpportopen localhost 27374 case $? in 0) echo Port 27374 may be listening for incoming requests. Bad news. ;; 1) echo The tcp port 27374 check seems to indicate that the port is echo closed - good. ;; *) #Technically the only other return code is 2. echo Unable to determine if tcp port 27374 is open. ;; esac if [ -f /usr/lib/ldlibns.so ]; then echo /bin/netstat has probably been moved to /usr/lib/ldlibns.so echo and replaced by a hacked version. if [ "$DELETE" = "NO" ]; then echo You should copy /usr/lib/ldlibns.so back over /bin/netstat echo or perhaps restore /bin/netstat from the net-tools rpm. else #DELETE=YES echo This file will be restored in a moment. fi else echo /bin/netstat has probably not been tampered with, good. fi if [ -f /usr/lib/ldlibps.so ]; then echo /bin/ps has probably been moved to /usr/lib/ldlibps.so echo and replaced by a hacked version. if [ "$DELETE" = "NO" ]; then echo You should copy /usr/lib/ldlibps.so back over /bin/ps echo or perhaps restore /bin/ps from the procps rpm. else #DELETE=YES echo This file will be restored in a moment. fi else echo /bin/ps has probably not been tampered with, good. fi if [ -f /usr/lib/ldliblogin.so ]; then echo /bin/login has probably been moved to /usr/lib/ldliblogin.so echo and replaced by a hacked version. if [ "$DELETE" = "NO" ]; then echo You should copy /usr/lib/ldliblogin.so back over /bin/login echo or perhaps restore /bin/login from the util-linux rpm. else #DELETE=YES echo This file will be restored in a moment. fi else echo /bin/login has probably not been tampered with, good. fi echo \(Please note that the \"ftp\" and \"anonymous\" lines can be echo legitimately added to /etc/ftpusers.\) checkforline /etc/ftpusers '(^ftp$|^anonymous$)' "" ; FTPUSERSANONYMOUS=$? echo Note: Both Ramen variants known as of Feb. 9, 2001 email notices echo from attacked machines to email accounts owned by the attacker. echo This script does not attempt to do anything about that as these echo notices have almost certainly left the system. You may still wish echo to check the outgoing mail queue with the \"mailq\" command to see echo if these messages are still there and delete them if so. Note that echo the /var/log/maillog should not be trusted as Ramen2 wipes any echo record of these mails from that log. echo Also: At least one variant mails off your /etc/shadow file, which echo contains encoded versions of all your users passwords, including echo roots password. You should change all user passwords and roots echo password _now_. if [ "$ARCHIVE" = "NO" ] && [ "$DELETE" = "NO" ] && [ "$KILL" = "NO" ] && [ "$RPMUPGRADE" = "NO" ] ; then if [ -n "$OFFENDINGFILES$OFFENDINGDIRS$ALLPIDS$VULNERABLERPMS$ALLINDEXES$ALLDATAFILES" ]; then echo This script was not instructed to do anything based on the above echo information. Run \"$0 -h\" for help on how to archive or remove echo the offending files and running programs and/or perform rpm upgrades echo on any Ramen vulnerable rpms. fi echo $0 exiting. exit 0 fi #No action requested? #The script exits here unless the user asks for some action. #NO ACTION MAY BE PERFORMED ON THE SYSTEM ABOVE THIS LINE. #==== End of "report only" section. ==== #==== Start of cleanup section. === #Pack up the files about to be deleted if the user requested this. if [ "$ARCHIVE" = "YES" ]; then if [ -n "$OFFENDINGFILES$ALLDATAFILES" ]; then OLDUMASK=`umask` umask 177 TMPFILE=`mktemp -q /tmp/ramenarchive.tar.gz.XXXXXX` if [ $? -ne 0 ]; then echo "$0: Can't create temp file, exiting..." exit 1 fi #FIXME - check if all readable. #FIXME - .w and .l's will be archived twice, cosmetic. ASKFIRSTHELP="Tar may need to be run as root if any of the files are not readable by $USER" $PRECOMMAND tar -czf - $OFFENDINGFILES $ALLDATAFILES >>$TMPFILE echo An archive containing the following Ramen files was created as $TMPFILE : echo $OFFENDINGFILES $ALLDATAFILES echo Please move this file to its intended destination. umask $OLDUMASK else #No files to archve. echo Archive option chosen, but no files located to archive. echo No archive will be created. fi #Any offending files? else echo You requested no archive of the offending files, no problem. fi #ARCHIVE=YES case "$RCSYSINITLPD" in 0) #File exists and line(s) there. echo Your /etc/rc.d/rc.sysinit file contains a \"/usr/bin/lpd\" line. if [ "$DELETE" = "YES" ]; then delline /etc/rc.d/rc.sysinit '/usr/bin/lpd' #If it's running, we have to hit killall before /usr/bin/lpd is deleted from the system. ASKFIRSTHELP="Kill off any running Stacheldracht agents." $PRECOMMAND killall -9 /usr/bin/lpd fi #They were warned above if DELETE=NO ;; 1) #File exists but no bad lines in it. echo Your /etc/rc.d/rc.sysinit does not contain a \"/usr/bin/lpd\" line, good. ;; 2) #File not there. echo Your system does not have an /etc/rc.d/rc.sysinit file - this echo is probably a problem on RedHat and derivative systems. ;; esac if [ -n "$OFFENDINGFILES$OFFENDINGDIRS$ALLDATAFILES" ]; then if [ "$DELETE" = "YES" ]; then for ONEFILE in $OFFENDINGFILES $ALLDATAFILES ; do echo Deleting $ONEFILE. ASKFIRSTHELP="Deleting $ONEFILE permanently from the system." $PRECOMMAND rm -f $ONEFILE done for ONEDIR in $OFFENDINGDIRS ; do echo Removing $ONEDIR. ASKFIRSTHELP="Removing the $ONEDIR directory permanently from the system." $PRECOMMAND rmdir $ONEDIR done else echo This script was NOT instructed to remove any files from the echo system, but the following files or directories remain. You echo are strongly encouraged to remove the following: echo $OFFENDINGFILES $ALLDATAFILES $OFFENDINGDIRS fi #DELETE=YES else #Nothing to delete. echo No files to delete. fi #Any offending files? if [ -n "$ALLPIDS" ]; then if [ "$KILL" = "YES" ]; then for ONEPID in $ALLPIDS ; do echo Killing PID $ONEPID. ASKFIRSTHELP="The kill command generally needs to be run as root." $PRECOMMAND kill -9 $ONEPID done else #User didn't want to kill processes. echo This script was NOT instructed to kill any processes, but the echo following PIDS are suspect. You are strongly encouraged to echo inspect, and if necessary, kill the following: echo $ALLPIDS fi #Kill running processes? else #Nothing to kill echo No suspect PIDS were found to kill. fi #Anything to kill? case "$INETDASP" in 0) #File exists and line(s) there. echo Your /etc/inetd.conf file contains a line starting with \"asp\" if [ "$DELETE" = "YES" ]; then delline /etc/inetd.conf '^asp[^a-zA-Z0-9]' ASKFIRSTHELP="Signal inetd to read its cleaned configuration file." $PRECOMMAND killall -HUP inetd fi #They were warned above if DELETE=NO ;; 1) #File exists but no bad lines in it. echo Your /etc/inetd.conf does not have the line to start asp, good. ;; 2) #File not there. echo Your system does not have an /etc/inetd.conf, no problem. ;; esac case "$ROOTUPDATE" in 0) #File exists and line(s) there. echo Your /var/spool/cron/root file contains either the /usr/sbin/update or echo killall -9 synscan lines. if [ "$DELETE" = "YES" ]; then delline /var/spool/cron/root '/usr/sbin/update' delline /var/spool/cron/root 'killall -9 synscan' ASKFIRSTHELP="Signal cron to reread its cleaned configuration file." $PRECOMMAND touch /var/spool/cron #Note - this is /var/spool/cron, not /var/spool/cron/root. See man cron. fi #They were warned above if DELETE=NO ;; 1) #File exists but no bad lines in it. echo Your /var/spool/cron/root has neither the /usr/sbin/update nor echo killall -9 synscan lines, good. ;; 2) #File not there. echo Your system does not have a /var/spool/cron/root, no problem. ;; esac case "$RCSYSINITSTART" in 0) #File exists and line(s) there. echo Your /etc/rc.d/rc.sysinit file contains a \"start62.sh\" or \"start7.sh\" line. if [ "$DELETE" = "YES" ]; then delline /etc/rc.d/rc.sysinit '/usr/src/.poop/start[267]*\.sh' echo Reminder, the system should be restarted. fi #They were warned above if DELETE=NO ;; 1) #File exists but no bad lines in it. echo Your /etc/rc.d/rc.sysinit contains neither a \"start62.sh\" echo nor a \"start7.sh\" line, good. ;; 2) #File not there. echo Your system does not have an /etc/rc.d/rc.sysinit file - this echo is probably a problem. ;; esac if [ -d /etc/xinetd.d ] && [ -n "`echo $OFFENDINGFILES | grep -q '/etc/xinetd.d/asp'`" ]; then echo /etc/xinetd.d/asp was handled above. Xinetd will now be instructed to echo not start this service in the future. ASKFIRSTHELP="Instruct xinetd to reread its configuration files" $PRECOMMAND killall -USR1 xinetd fi #if /etc/xinetd.d/asp was one of the yanked files. if [ -n "$VULNERABLERPMS" ]; then echo The following known Ramen vulnerable RPMS were found on your system: echo $VULNERABLERPMS if [ "$RPMUPGRADE" = "YES" ]; then echo This script will attempt to install new versions of these packages. echo Please watch the error messages carefully - if any of the attempts echo fail, you will need to retry the upgrade yourself or find a new mirror echo site. Also watch to see if any of your configuration changes need to echo be carried over to the new rpm. for ONERPM in $VULNERABLERPMS ; do case $ONERPM in LPRng*) ASKFIRSTHELP="Install the LPRng rpm update." $PRECOMMAND rpm -Uvh 'ftp://ftp.varesearch.com/pub/mirrors/redhat/redhat/updates/7.0/i386/LPRng*.rpm' ;; nfs-utils*) ASKFIRSTHELP="Install the nfs-utils rpm update." $PRECOMMAND rpm -Uvh 'ftp://ftp.varesearch.com/pub/mirrors/redhat/redhat/updates/6.2/i386/nfs-utils*.rpm' ;; wu-ftpd*) ASKFIRSTHELP="Install the wu-ftpd rpm update." $PRECOMMAND rpm -Uvh 'ftp://ftp.varesearch.com/pub/mirrors/redhat/redhat/updates/6.2/i386/wu-ftpd*.rpm' ;; *) echo This script does not know how to upgrade $ONERPM. You will echo have to do this by hand. ;; esac done else echo You have chosen NOT to perform automatic upgrades. You should echo manually install, at the very least, updates for these vulnerable echo packages. fi else echo This script was not able to automatically identify any Ramen echo vulnerable RPMS on your system. fi echo You are encouraged to regularly check your distribution\'s mirror echo sites regularly for updates. Remember that no attempt was made to echo upgrade any rpms but those known to be vulnerable to Ramen. #Try to connect to localhost:27374 and report server. tcpportopen localhost 27374 case $? in 0) echo Port 27374 may still be listening for incoming requests. Bad news, echo as the previous actions should have shut that server down. echo Please investigate. Rebooting this machine may help close this echo port for good. It may also be the case that some other program echo is listening on this port. ;; 1) echo The final tcp port 27374 check seems to indicate that the port is echo closed - good. ;; *) echo Unable to determine if tcp port 27374 is still open. ;; esac case "$FTPUSERSANONYMOUS" in 0) #File exists and line(s) there. echo \"ftp\" and \"anonymous\" lines were added to /etc/ftpusers. if [ "$DELETE" = "YES" ]; then echo Removing these lines. delline /etc/ftpusers '^ftp$' delline /etc/ftpusers '^anonymous$' else echo This script was not instructed to remove the \"ftp\" and echo \"anonymous\" lines from /etc/ftpusers. If you wish to echo provide anonymous ftp access to this system, you should echo remove these lines yourself. fi ;; 1) #File exists but no bad lines in it. echo /etc/ftpusers has neither \"ftp\" nor \"anonymous\", so anonymous echo ftp access is enabled. ;; 2) #File not there. echo /etc/ftpusers does not exist, but probably should if you serve files echo via ftp from this system. ;; esac restorefrombackup /bin/netstat /usr/lib/ldlibns.so restorefrombackup /bin/ps /usr/lib/ldlibps.so restorefrombackup /bin/login /usr/lib/ldliblogin.so echo $0 finished, exiting. exit 0