exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

safeload.c

safeload.c
Posted Aug 17, 1999

SafeLoad is buffer overflow wrapper for suid programs.

tags | tool, overflow
systems | unix
SHA-256 | 8d29e7510ada3f3bfe07b9619cbbf60a5e613d09f89c9fe56aac6e3e3e24ded4

safeload.c

Change Mirror Download
/* SafeLoad v0.1
*
* Author: Willy Tarreau <tarreau@aemiaif.lip6.fr>
*
* THIS PROGRAM IS DISTRIBUTED WITH NO EXPRESSED OR IMPLIED SORT OF WARANTY.
* THE AUTHORS SHOULD NOT BE LIABLE FOR ANY DAMAGE OR LOSS CAUSED TO YOU,
* YOUR SYSTEM OR ANYBODY.
*
*/

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <grp.h>
#include <pwd.h>
#include <sys/types.h>
#include <time.h>


/* number of seconds to wait when an error has been detected in LLSTOP mode. */
#define WAITTIME 5

/* log levels */
#define LLNONE 0 /* don't log anything about this prog */
#define LL2LONG 1 /* log only if too long an arg is given */
#define LL2MANY 2 /* also log if too many args given */
#define LLCALL 3 /* also systematically log any call to the prog */
#define LLSTOP 4 /* wait and stop if any error occurs */

#define toend(p) {while(*p&&*p!=' '&&*p!='\t'&&*p!='\r'&&*p!='\n')p++;if(*p)*p++=0;}
#define tonext(p) {while(*p==' '||*p=='\t')p++;}


int i,j,s;

/* CAUTION ! Don't make the initial string longer than 1023 chars! */
char *suidtable="/etc/safeload.tbl";
char *logfile="/var/log/safeload.log";

void usage(char *name) {
close(1); dup(2);
printf("SafeLoad v0.1 - 1998/03/01 - Willy Tarreau <tarreau@aemiaif.lip6.fr>\n",name);
printf("\tSafeLoad is buffer overflow wrapper for suided programs.\n");
printf("\tThis program should never be called directly, but only with\n");
printf("\tthe name of the program it replaces. The simplest way to do\n");
printf("\tthis is to rename the insecure program and to replace it by\n");
printf("\ta symlink to safeload. SafeLoad will then look in the table file\n");
printf("\tfor a line containing this name, and will then execute the proper\n");
printf("\tprogram with proper euid, which must be, of course, non suided.\n");
printf("\tAll args will be truncated to a length specified in this file,\n");
printf("\tand all attempts to overflow any arg will be logged.\n");
printf("\nCompile-time configuration:\n");
printf("\ttable file: %s\n\tlog file: %s\n",suidtable,logfile);
exit(1);
}


int log(char *name, char *error, int verbose) {
FILE *logf;
time_t tim;
struct tm *tm;
/* let's open the log file */
if ((logf=fopen(logfile,"a+"))==NULL) {
fprintf(stderr,"safeload: error while opening log file %s:",logfile);
perror("");
fprintf(stderr,"Error was: %s for %s\n",error,name);
exit(1);
}
time(&tim); tm=localtime(&tim);
fprintf(logf,"%04d/%02d/%02d %02d:%02d: uid=%d, %s for %s\n",tm->tm_year+1900,tm->tm_mon,tm->tm_mday,tm->t
m_hour,tm->tm_min,
getuid(),error,name);
fclose(logf);
if (verbose)
fprintf(stderr,"SafeLoad logged this error:\n\t%s for %s\n",error,name);
return 1; /* just to give a value to a direct call to exit() */
}


int longwait() {
int s;
#ifdef LONGWAIT
for (s=0;s<32;s++)
signal(s,SIG_IGN);
sleep(WAITTIME);
for (s=0;s<32;s++)
signal(s,SIG_DFL);
#endif
return 1; /* give value to exit */
}

main(int argc, char **argv) {
FILE *tbl;
char *line, *myname;
char *p, *callname, *realname, *np, *nerr;
int euid, egid, nbargs, lmax, loglevel;

int i,j,s;

/* Make myname point to the name under which safeload was called, without the directory */
if (myname=strrchr(argv[0],'/'))
myname++;
else
myname=argv[0];

/* if safeload is called as-is it's an error so we tell the user how to use it */
if (!strcmp(myname,"safeload"))
usage(myname);

/* let's open the table */
if ((tbl=fopen(suidtable,"r"))==NULL) {
fprintf(stderr,"safeload: error while opening table file %s:",suidtable);
perror("");
exit(1);
}

/* now, search in the table for a line beginning with myname */
line=(char *)malloc(1024);
while (fgets(line,1024,tbl)) {
callname=p=line; toend(p);
if (*callname=='#')
continue;
if (!strcmp(myname,callname)) /* not the right name. We go on. */
break;
}
if (strcmp(myname,callname)) {
/* if we get here, this means that safeload has been called with a wrong
name. We have to log this because it can be the source of an attack. */

log(myname,"missing entry",1);
exit(1);
}

/* Ok, we got the right name. Let's discover what we have to do now. */

tonext(p); realname=p; toend(p);
if (!*realname) exit(log(myname,"incomplete entry",0));

tonext(p); np=p; toend(p);
if (!isalpha(*np)) {
euid=strtol(np,&nerr,0);
if (*nerr) exit(log(myname,"incorrect char in euid field",0));
if (getpwuid(euid)==NULL)
log(myname,"Warning: non-existing euid used",0);
}
else {
struct passwd *pw;
if ((pw=getpwnam(np))==NULL)
exit(log(myname,"Error: user unknown",0));
euid=pw->pw_uid;
}


tonext(p); np=p; toend(p);
if (!isalpha(*np)) {
egid=strtol(np,&nerr,0);
if (*nerr) exit(log(myname,"incorrect char in egid field",0));
if (getgrgid(egid)==NULL)
log(myname,"Warning: non-existing egid used",0);
}
else {
struct group *gr;
if ((gr=getgrnam(np))==NULL)
exit(log(myname,"Error: group unknown",0));
egid=gr->gr_gid;
}

tonext(p); np=p; toend(p); nbargs=strtol(np,&nerr,0)+1;
if (*nerr) exit(log(myname,"incorrect char in nbargs field",0));

tonext(p); np=p; toend(p); lmax=strtol(np,&nerr,0);
if (*nerr) exit(log(myname,"incorrect char in lmax field",0));

tonext(p); np=p; toend(p); loglevel=strtol(np,&nerr,0);
if (*nerr) exit(log(myname,"incorrect char in loglevel field",0));

/* Ouf !! */
/* First of all, we'll reduce the number of args if required */
if ((nbargs>=0) && (argc>nbargs)) {
if (loglevel>=LL2MANY)
log(myname,"too many args",1);
if (loglevel>=LLSTOP)
exit(longwait());

while (argc>nbargs)
argv[--argc]=NULL; /* we also make them disappear from the stack */
}

/* now, we'll truncate all args if required */
if (lmax>=0) {
int arg;
for (arg=1;arg<argc;arg++)
if ((strlen(argv[arg]))>lmax) {
argv[arg][lmax]=0;
if (loglevel>=LL2LONG)
log(myname,"argument too long",1);
if (loglevel>=LLSTOP)
exit(longwait());
}
}


/* Now, for each arg, */

if (loglevel>=LLCALL)
log(myname,"ready to go",0);

/* First, we'll set the egid to the required value if it's >=0. Only then, the euid */
if (egid>=0) setegid(egid);
if (euid>=0)
seteuid(euid);
else
seteuid(getuid()); /* restore the right uid so that the user no longer stays root :-) */

argv[0]=realname;
execvp(realname,argv);
fprintf(stderr,"execvp(%s):");
perror("");
exit(log(myname,"execution not completed",1));
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close