enable safer CGI in shared hosting environments #32
Loading…
Reference in New Issue
There is no content yet.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may exist for a short time before cleaning up, in most cases it CANNOT be undone. Continue?
My goal is to make CGI work in shared hosting environments where it's essentially untenable right now because spawned CGI programs execute as the same user as the molly-brown server.
The docs mention that go doesn't support setuid and "there is no way to work around this", but maybe with the right workaround go doesn't need to setuid. In the daemontools/runit/s6/etc approach to daemon management, a typical worker (say for tcpserver) would look something like:
They make heavy use of wrapper programs like chroot or setuidgid which simply reduce privileges of their environment in various ways, and then
exec(3)
some other program.This is of course possible today, but every individual cgi program has to initialize itself using priv-dropping wrappers like the above command, requiring "good behavior" from the users in the shared hosting environment.
As a first step to make admin-enforced privilege dropping at least possible, I propose a config variable
CGICommand
which, whenever a suitable cgi program is found for a URL, will be run in place of the cgi program itself. Crucially, it will still get the CGI environment variables, so it should be expected at some point toexec $SCRIPT_PATH
.Would you be open to a patch implementing this?
enable safe CGI in shared hosting environmentsto enable safer CGI in shared hosting environmentsGo supports setuid as of a little while ago:
https://go.dev/doc/go1.16
It may be possible to allow safer CGI execution now without resorting to tricksy implementations. It'd be nice to see this implemented, as CGI scripts are off right now in the tilde I'm at due to what I assume are general security concerns.
Hmm...this is an interesting workaround, but in order for the
CGICommand
to be able tochroot()
orsetuid()
before doingexec $SCRIPT_PATH
, it would need to be running as root, right? Which would mean Molly Brown would need to be running as root. That would probably make shared hosting admins less happy, not more!The exception to this is on Linux where
setcap
could be used to "bless" theCGICommand
binary to let it do those things even while running as an unprivileged user. I guess it has some value in that setting.But as per the discussion in issue #16,
setuid()
is possible on Linux with Go 1.16 and later (and, it turns out, was possible on other unixes all along, which I failed to realise). I am working on taking advantage of that, which I guess reduces the motivation for this kind of "tricksy" workaround.If you can make a good case for why this might still be useful even with
setuid()
now on the table I will consider it, but I think I would prefer the more conventional approach.I'm pretty sure you can use
setuid
without running the command as root. This is howsudo
works I believe. See https://news.ycombinator.com/item?id=34455094, or more directly: https://en.wikipedia.org/wiki/SetuidAh, of course, the helper could be a setuid variable. Not sure how I overlooked that (have literally tested that Molly works nicely in that exact configuration!), sorry. Okay, this is definitely very viable, but I still think that a direct solution is preferable.
What something like a
CGICommand
uniquely enables is a resource barrier that's specific to CGIs, and separate from the molly-brown server itself.So for instance molly-brown could be running as an unprivileged user, but CGIs could still be enforced to execute as the user in whose directory they are found. As an unprivileged user, molly-brown can't run setuid any longer itself, but a root-owned
CGICommand
with the setuid bit and which drops privileges could accomplish this.There are all kinds of ways an administrator might want to limit CGIs specifically, but that is by no means the same set of limitations they'll want to place on the whole molly-brown server.
Okay, I am convinced that this feature would be valuable even once the other stuff I'm doing to address #16 is also finished. I'd be happy to accept a PR. Also happy to try to implement it myself but it may not be a top priority for a little while.