Thread: C help
View Single Post
Old 05-09-07, 08:45 AM   #1
evilghost
Registered User
 
Join Date: Jul 2005
Posts: 3,606
Default C help

Background
We use SSHFS to dump images of our daughter (18 mo) to her website (my server). uid/guid ownership on the file is sshfs user:user and the uid www-data needs write access to the file so it can be converted/resized using Imagemagick.

The below code runs suid (4770) with root:www-data and is called from a PHP script. The PHP code checks fileowner() on the image and if the owner is not www-data the below C code is called via system().

The data is sanitized in PHP prior to being passed to the suid binary, however, I want additional security measures in place. For example, no content will be outside of /www/dlf/dlf-albums.

Here is an example argv[1] passed value:
/www/dlf/dlf-albums/12-24 Months/Big Bubble bath 1.JPG

Here is the PHP code snippet that calls the suid binary:
Code:
//Fix file permissions if they are invalid, 33 is UID of www-data, fixperms is SUID 4770 root:www-data
if (fileowner(realpath($cache_path.$this->get_files[$i]['real'])) != 33)
  system("/www/dlf/fixperms \"".realpath($cache_path.$this->get_files[$i]['real'])."\"");
Issues
I am not proficient in C by any stretch. I need the code modified to:
1) Check that argv[1] does not traverse outside of /var/www/dlf-albums
2) Use fprintf() instead of fputs() (isn't fputs less secure)?
3) For some reason asctime() is adding a newline character to the end of the string?
4) Be able to print output using something like fputs(fout,"%s\t%s\n",asctime(time(NULL)),argv[1]); without segfaulting
5) Create as secure code as possible.

I certainly appreciate any help someone can give me. Again, C is not my strong point by any stretch.

Code:
/* evilghost
 * May 8, 2007
 * SETUID binary to fix permissions with uploaded images if they are invalid.
 * Permissions on compiled binary must be 4770 with uid/gid root:www-data
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

#define wwwdata_GID 33
#define shared_GID 5140

FILE *fout;

int main(int argc, char **argv){
        time_t curtime;
        struct tm *loctime;

        // Get the current time & convert to local.
        curtime = time (NULL);
        loctime = localtime (&curtime);

        //Write audit trail.
        fout = fopen ("/www/dlf/fixperms.log", "a+");
        fputs(argv[1],fout);
        fputs("\t",fout);
        fputs(asctime(loctime),fout);
        fclose(fout);

        //Adjust permissions
        chown(argv[1], wwwdata_GID, shared_GID);
        chmod(argv[1], 0770);
        return(0);
}
evilghost is offline   Reply With Quote