On Thu, Jul 28, 2005 at 10:28:09AM -0400, Dan Mahoney, System Admin wrote: > On Thu, 28 Jul 2005, Brian Candler wrote: > > If you don't have a shell, then your system runs /bin/echo, no? No. Firstly, suexec calls execv(), which does not do a search in $PATH. Secondly, "echo foo" is treated as a single argument, that is, it's not split into "echo" and "foo". It would run a program called "echo foo" in the current directory, if there were an executable file with that name. I've done a bit of research (since the reasoning doesn't seem to be documented), and I think I can see why this is the case. Suppose you passed the shell to suexec like this: suexec brian brian /bin/sh -c echo foo ^^^^^ ^^^^^ ^^^^^^^ ^^ ^^^^^^^^ user group arg1 arg2 arg3 The current suexec policy would refuse to execute it for several reasons. arg1 is an absolute path (it starts with /); /bin/sh is not under the Apache document root; and /bin/sh is not owned by user 'brian' So, suppose you modified suexec so that it accepted '/bin/sh' as a trusted executable, and would run it with those arguments? The trouble is then that anyone who breaks into the webserver (i.e. runs code as the webserver user) can then automatically run any arbitrary command as any arbitrary user on the system. e.g. suexec fred fred /bin/sh -c "sh -i" would give them a nice interactive shell as that user. The current suexec security model means that a user who breaks into the system as the Apache user can only run scripts which already exist, AND which are within the webroot, AND run them as the user who wrote the script. In other words, they can more or less only run the same things as people contacting the webserver from outside via HTTP can run. There may be holes in the scripts themselves they can exploit to escalate privilege, but it requires more work. So, I'm pretty much resigned to setting IncludesNOEXEC. A longer description I was typing as I was researching this is attached below, in case it's of any use to anyone. I did have an idea for a better solution, and that's attached too. Cheers, Brian. PROBLEM DESCRIPTION ------------------- The specification for shtml (server-parsed) files includes the feature for command execution: <!--#exec cmd="echo foo"--> In normal use, this is run under a shell [extract from main/util_script.c]: if (shellcmd) { execle(SHELL_PATH, SHELL_PATH, "-c", argv0, NULL, env); } However, when suexec is active, it is not: if (ap_suexec_enabled ... if (shellcmd) { execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, argv0, NULL, env); } As a result, the semantics of #exec cmd="..." are changed, and scripts which would work without suexec will break with it. Even the simple examples given at http://httpd.apache.org/docs/1.3/howto/ssi.html will fail: <pre> <!--#exec cmd="ls" --> </pre> The user would have to work around it like this: <!--#exec cmd="foo.sh"--> and create foo.sh containing #!/bin/sh ls and set the +x bit. POSSIBLE SOLUTION? ------------------ Pass the shell to suexec: if (shellcmd) { execle(SUEXEC_BIN, SUEXEC_BIN, execuser, grpname, SHELL_PATH, "-c", argv0, NULL, env); } However, the current suexec binary would reject this under its security model. Specifically, it violates: 4. Does the target program have an unsafe hierarchical reference? Does the target program contain a leading '/' or have a '..' backreference? These are not allowed; the target program must reside within the Apache webspace. 13. Is the directory within the Apache webspace? If the request is for a regular portion of the server, is the requested directory within the server's document root? 18. Is the target user/group the same as the program's user/group? It would be possible to make a hardcoded exception which says that SHELL_PATH can skip these tests. Would that be considered an unacceptable security risk? It seems so. The problem is that if you break into a webserver (i.e. become the webserver owner), then this would allow you to run arbitary code as an arbitary user. Without this feature, suexec would only let you run every CGI script in the system as the script author (although on a typical system, there would be plenty of holes in those scripts to exploit :-) A STRONGER SOLUTION ------------------- Process .shtml pages in an entirely separate CGI program, started by a wrapper which sets userid to the owner of the .shtml page (a la cgiwrap). This is a secure but heavyweight solution for pages which don't require <!--exec cmd...-->. It could, however, be invoked only for pages which contain that construct. Does such a standalone CGI version of mod_includes already exist? A MIDDLEWEIGHT SOLUTION? ------------------------ When Apache is scanning an SSI file and comes across #exec cmd, it could invokes a suexec wrapper with: - the name of the .shtml file - an index (0, 1, 2...) for which #exec cmd instance is required. The wrapper does the same checks as suexec: i.e. it checks that the .shtml file and the directory containing it are owned by the target user, and that it is within the Apache document root. After switching to the target uid/gid, it then re-parses the .shtml file looking for the n'th instance of <!--#exec cmd="...."--> and executes it it using /bin/sh -c "...." Alternatively, the wrapper could be passed an offset into the file. The wrapper would check that the data at this offset starts <!--#exec cmd="..."> and reject if not. I think this is reasonably secure; the chances of this sequence of characters appearing in a file which is *not* a .shtml file are pretty low. However if somebody creates a documentation file foo.txt within their webspace, containing Here's a useful example: <!--#exec cmd="sh -i"--> then someone running as the webserver user could use suexec to run it :-| --------------------------------------------------------------------- The official User-To-User support forum of the Apache HTTP Server Project. See <URL:http://httpd.apache.org/userslist.html> for more info. To unsubscribe, e-mail: users-unsubscribe@xxxxxxxxxxxxxxxx " from the digest: users-digest-unsubscribe@xxxxxxxxxxxxxxxx For additional commands, e-mail: users-help@xxxxxxxxxxxxxxxx