Code Tips and Snippets


Not yet member?
Click here to register.
Only members can post comments
Run php (or other) scripts with suid root permission
Posted by pk on Sunday, September 07 2014 - 12:45:15
5 stars levelC Languagephp languageLinux operating system

Who never had the need to run some php (or other) scripts, which require access to data with root privilege, in the context of unprivileged users ( apache for an example ).

In fact, it is very easy to achieve this with a C program.

But in recent Linux distributions, for a script (other than bash/sh/...), it is now forbidden for so-called security considerations.

Maybe this would be justified on a server where multiple users have local access, with permissions that are uncontrolled by the administrator…

On a personal server, where only services (web, email, etc.) are offered to the public, I think that it is completely unfounded!

Let's see how to bypass totalitarian restrictions of current distributions.

The key lies in the fact that it is very easy to do this with a  C program!
So we have just to write a small C program that will launch our script as root!

Let's start by seeing how it goes for a C program:
It must have the following two lines in his code:

 
    setuid(0);    // set effective user  id 0 (root uid)
    setgid(0);    // set effective group id 0 (root gid)

Please refer to man setuid and man setgid for these functions reference manual.
Then, once your my_prog program is compiled, you have to assign it the root uid and gid, and also the "set user or group id on execution" bit.
As root type the following commands:

chown root my_prog
chgrp root my_prog
chmod a+s  my_prog

Now that we have understood the principle, here is the complete code of the program that I named pk_suid_wrapper.
You can see that the number of lines is ridiculous ... (small but strong)

I will not further comment this code, it is simple enough to be understood by anyone who has an interest in this article ....
Please understand that it manages all the necessary security controls...

 
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
#include < sys/types.h >
#include < sys/stat.h >

main(int argc, char**argv)
{
    int ok = 0;
    int uid,gid;
    struct stat statbuf;

    setuid(0);
    setgid(0);

    if (stat(argv[1],&statbuf))				{ fprintf(stderr,"cannot stat %s\n",argv[1]);			exit(-1); }
    if (statbuf.st_uid || statbuf.st_gid)	{ fprintf(stderr,"[%s] must be root root\n",argv[1]);	exit(-2); }

    if (stat(argv[2],&statbuf))				{ fprintf(stderr,"cannot stat %s\n",argv[2]);			exit(-1); }
    if (statbuf.st_uid || statbuf.st_gid)	{ fprintf(stderr,"[%s] must be root root\n",argv[2]);	exit(-2); }
    if (!(statbuf.st_mode & S_ISGID))		{ fprintf(stderr,"[%s] must be sgid root\n",argv[2]);	exit(-3); }
    if (!(statbuf.st_mode & S_ISUID))		{ fprintf(stderr,"[%s] must be suid root\n",argv[2]);	exit(-4); }

    for(;;)
    {
        if (!strcmp(argv[1],"/usr/bin/php"))	break;				// Authorized program...

        fprintf(stderr,"setuid forbidden for [%s]!\n",argv[1]);
        exit(-5);
    }

    execv(argv[1],argv+1);
}

To use this little program, just compile it and then run (as root) the chown, chgrp, chmod commands, as described above.

Then, to make your script (php here, but you can adapt) executable by root:

  1. apply the same chown,chgrp,chmod commands to your script.
  2. change the first line of the script
    #!/usr/bin/php
    by
    #!/the_file_path/pk_suid_wrapper /usr/bin/php

Be carefull with your script permissions, in order to allow only authorized persons to modify it !!!
Otherwise, anyone could change it, and run anything with root permissions on your system!

 

yakpro rulez!

Site has been updated on Thursday, May 25 2017 - 09:16:27