• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1078
  • Last Modified:

how to use posix_setuid to do commands as root

I'm trying to make a shell script in php that'll allow me to do setuid behavior to run some commands as root. before you say it, I'm aware of the security risks associated with this. Thats not what I need right now.

What I need is to figure out why this isn't allowing me to posix_setuid. What happens when I run this script as root, is that it works fine. If I run it as a non-root user though, it fails, giving the error "Operation not permitted".

I have my file permissions like so:

-rwsr-xr-x    1 root     wheel        1264 Apr  8 13:57 privsep.php

I'm running command like:

./privsep.php

and using php version 4.2.2 on SuSE Linux 8.2

Any help MUCH appreciated.



#!/usr/bin/php
<?

$argv = $_SERVER['argv'];
$argc = $_SERVER['argc'];

//
// privsep.php
//

// Don't allow this script to be run from the web
if (isset($_SERVER['REQUEST_METHOD']))
{
   print "<br>This program is not intended to be run directly from the WWW.\n";
   return 1;
}

   // Original user ID
   $original_uid = posix_getuid();

   // Set our real user ID to root
   $success = posix_setuid(0);
   if (!$success)
   {
       print "Error: Cannot setuid().\n";
       print posix_strerror(posix_get_last_error());
       return 1;
   }

  //DO SOME STUFF HERE

  // Drop the real UID back to the calling user ID
   $success = posix_setuid($original_uid);
   if (!$success)
   {
       print "Error: Cannot setuid().\n";
       return 1;
   }

   // Drop the effective UID as well
   $success = posix_seteuid($original_uid);
   if (!$success)
   {
       print "Error: Cannot seteuid().\n";
       return 1;
   }

   print "Success!\n";
   return 0;
?>
0
umbrae
Asked:
umbrae
  • 2
2 Solutions
 
minnirokCommented:
Hi umbrae, before I answer allow me to say: there are some serious security risks here with what you're trying to do!   ;)

The problem is, that you're logged in as a regular user when you're running the script and forcing a change to root without providing credentials.  Obviously, linux has to reject this - imagine if I had an account on your system, I could run this PHP script on your machine and use poxis_setuid(0) to hijack the box!  So for security reasons, only root has the authority to poxis_setuid(0)...

The best solution would be to add executable group privileges for each command you're trying to envoke and then add the user trying to run the script to that group...  This way you are also watching out for your security by explicity specifying which users may run certain commands.
0
 
minnirokCommented:
IE, your problem lies not within PHP but with permission levels of linux :_)
0
 
umbraeAuthor Commented:
I was under the impression that if the file was owned by root, had the setuid bit (whichshould be set by root only ever), it was fully intended to do restricted root behavior with a normal user.

But I'll check out things further and if nobody else comes up with a better solution, I'll give you the points.
0
 
Marcus BointonCommented:
This isn't quite what you're doing, but it may be helpful anyway. I use a daemon script that forks a new process, detaches from a terminal, and switches IDs from a root account to one with lower privs:

//Fork a child process
$pid = pcntl_fork();
if ($pid == -1)
      die('Could not fork');
else if ($pid)
      exit(); //we are the parent, so exit
//Detach child from terminal
if (!posix_setsid())
      die('Could not detach from terminal.');
$pid = posix_getpid(); //get our new process ID
//Write out our PID somewhere for other processes to see (before we setuid)
if ($pidfile = fopen('/var/run/myprocess.pid', 'w')) {
      fwrite($pidfile, "$pid");
      fclose($pidfile);
}
//Get user and group IDs we want
$groupinfo = posix_getgrnam("myuser");
$userinfo = posix_getpwnam("mygroup");
if ($userinfo == FALSE or $groupinfo == FALSE)
      die('Target user and/or group don\'t exist.');
//Set GID and UID (in that order)
$g = posix_setgid($groupid = $groupinfo["gid"]);
$u = posix_setuid($userinfo["uid"]);
if (!($u and $g))
      die('Problem switching uid/gid.');

setuid does do what you say, so just make sure you're doing it right:

http://www.evolt.org/article/UNIX_File_Permissions_and_Setuid_Part_2/18/263/
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now