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: [EMAIL PROTECTED]
   "   from the digest: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to