I have a Perl script that is called either via Apache or on the command-line.
For testing purposes, I pass it the username I want the Perl script to operate with, and use POSIX::setuid
to set the uid
.
If I run the script from the command line, then the uid
is set properly:
use CGI::Pretty qw/:standard/;
use POSIX qw(setuid getuid);
...
my ($pwName, $pwCode, $pwUid, $pwGid, $pwQuota, $pwComment,
$pwGcos, $pwHome, $pwLogprog) = getpwnam($username);
if ((defined $pwUid) && (getuid() == $pwUid)) {
setuid($pwUid);
print header;
print Dumper $<;
}
else {
print header(-status => 401);
print "Could not setuid to correct uid (currently: )".getuid()."\n";
}
The command-line output shows the correct uid
of the specified $username
, instead of the uid
of the test account that started running the script.
If I call the script via Apache, then the uid
remains set to the id of the apache
user, and never changes.
I don't believe I can use suExec
here, because, after reading the documentation:
I can't put a copy of this script into http://www.example.com/~username
for every $username
. The script needs to run from one location, and I need to specify the uid
from within the script.
I need to have the script run as the specified username at runtime, and not as a single username specified once in a virtual host directive in an Apache configuration file. Changing this configuration file and restarting Apache every time a new user runs this script is not realistic.
How do I get a Perl script running as a cgi-bin to change the uid
correctly, when using setuid()
?
The only way you can setuid
to an arbitrary uid is to run as root.[1]
I don't know about you, but the idea of a CGI program running as root gives me nightmares.
What is this code supposed to actually do after changing uid? Perhaps there's a way to accomplish this without having to setuid
?
[1] Depending on your code and its security model, you may be able to collect the user's password and use su
/sudo
[2] to run a separate command-line program to run the actual operations outside of the web server environment, but su
/sudo
are able to do this because they're suid root and it would still open up most/all of the issues associated with running CGI code as root anyhow. Even if you filter out root as an invalid username, being able to masquerade as any arbitrary user opens up plenty of opportunities for abuse.
[2] sudo
could even be configured to allow it without requiring a password, but there be dragons down that path. Be sure you know what you're doing if you attempt it, lest you give your users free reign to impersonate each other at will.