You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Oezguer Kesim <ke...@math.fu-berlin.de> on 1998/11/12 11:40:10 UTC

Contribution: SuEXEC Options

Hello,

first of all, I kindly ask you to ignore the fact, that I'm quite new to this
mailinglist.  The issue I like to generate a discussion about is the suEXEC
feature of Apache.  So far, suEXEC can only be choosen at compiletime and then
only be used either for <Virtualhosts> or for _every_ ~user .  Furthermore,
the behaviour of suEXEC -- like followsymlinks -- is fixed.

Here are some examples, in which a different policy would be quite effective
and secure:

-    Consider a project with, let's say, n members, which work on an
     WWW-interface for they database.  They are all in one unix-group and each
     one needs write permission to the directory as well to the scripts --
     they share them.
     In that case, I would like to say to Apache:  For _this_ <Directory>,
     enable suEXEC _and_ allow (optionally!!) (sub-)directories beeing
     writable by _group_, as long as the script-owner is a member of it (so,
     no one could have put that script into this directory besides group
     members).
     An option for suEXEC, which allows scripts beeing group-writable (as long
     as the owner is a member of the group!), would be quite usefull, too.

-    Also, I like to tell suEXEC _optionally_, that it should take _secondary_
     groups into account -- since the groups members most likely will not have
     the mentioned group as primary one.
     
-    Following Symlinks for directories are forbidden.  But for scripts?  If
     one could have a _option_ for suEXEC, that for _this special_
     <Directory> it should follow it _as long as_:
     	- both, target and link, are _not_ in a symlinked directory.
	- the uid's of both are identical.
	- the gid's of both are identical, _or_ (optional!) the owner is a
	  member of _both_ groups.

-    At compiletime, I like to select a different DOC_ROOT for suEXEC, let's
     call it SUEXEC_CGI_ROOT, in order to cleanly split usual scripts an
     `trusted' ones -- but for me, whitout suEXEC there is a bigger security
     problem, since any data, which is readable for _one_ script, is readable
     for _every other_ script.

I made a implementation of all the things above.  With my patch applied, you
can choose between:
	1.)  No suEXEC at all  (i.e without a --enable-suexec)
	2.)  The original suEXEC behaviour  (i.e --enable-suexec and the other
	     original options)
	3.)  suEXEC with options (--with-suexec-opt)

In the last compile-case, you may put the following directives into
access.conf:

<Directory /foo/bar>
Options SuExec SuExecFollowSymLinks SuExecAllowDirectoryWritableByGroup
SuExecAllowProgamWritableByGroup SuExecTrySecondaryGroups
</Directory>

This would enable suEXEC for /foo/bar and change it's behaviour as mentioned
(of course, one has to check the source, to see what it would exactly do).

None of the options are set by default.  Other <Directories> wouldn't
"suEXEC"'lized.

I should point out, that I'm using my own code at a _large_ site (~800 users
and machines), whithout any problems.  I wrote it with respect and full
concentration on security concerns, but would like to let you check it again.

If there is any interest in my patch, the last question is:  Can I post a patch of about 11K bzip2'ed to this mailing list?

cheers,
  Oezguer Kesim

-- 
Oezguer Kesim       |
Unix Support        |  Email: Oec.Kesim@alcatel.de
Alcatel SEL Berlin  |

Re: Contribution: SuEXEC Options

Posted by Randy Terbush <ra...@Covalent.NET>.
A bit late in responding to some of these things.

Oezguer Kesim <ke...@math.fu-berlin.de> writes:
> Thus spake Randy Terbush (randy@Covalent.NET):
> 
> > suExec was intended to be hard to set up and great pains were taken to 
> > make the wrapper as simple as possible. 
> 
> You mean, the harder to configure the more secure?  Hm...

No. The fewer configuration options, the less chance of hanging
yourself.



Re: Contribution: SuEXEC Options

Posted by Oezguer Kesim <ke...@math.fu-berlin.de>.
Thus spake Randy Terbush (randy@Covalent.NET):

> suExec was intended to be hard to set up and great pains were taken to 
> make the wrapper as simple as possible. 

You mean, the harder to configure the more secure?  Hm...

> This was largely because Jason and I did not want our names implicated on
> a weekly CERT advisory along with Apache. 

The point is:  you are already.  Apache without suexec gives every member
of the network the possibility to explore information of others.  This is
the main security problem.  The usage of setuid root programs surely needs
an extra (huge!  I mean really _HUGE_) amount of checks, test and
workovers -- on the other hand, this is the only way, apache can garantee
security of data of their users.

In my network (about 800 developers in about 50 Projects) there is
definitely a need (and order!) for dataprotection together with
availability of the data -- WWW-Frontends tend to the leading frontend of
databases.  Those data must be protected, but also the admin needs full
control over how the data is accessed  -- this is not possible with (the
current version of) suexec.  Without my implementation apache would have
been out of question at our site.

Therefore I ask:  Is the Apache-Core willing to support/implement that kind
of dataprotection with a sophisticated interface or not?  Not that it is
important to me to see my piece of code in the official source, but I think
it´s usefull/important/neccessary for _many_ sites.

> I would urge people to give some thought to an API for this wrapper and
> allow other folks to go off and add security holes to their own wrapper
> projects until their hearts content.

Well, isn´t that what I have implemented?

cheers,
   oec

Re: Contribution: SuEXEC Options

Posted by Randy Terbush <ra...@Covalent.NET>.
Just to voice my concerns about suExec...

suExec was intended to be hard to set up and great pains were taken to 
make the wrapper as simple as possible. This was largely because Jason 
and I did not want our names implicated on a weekly CERT advisory
along with Apache. I would urge people to give some thought to an API
for this wrapper and allow other folks to go off and add security
holes to their own wrapper projects until their hearts content.

-Randy


>  With my patch applied, you
> > can choose between:
> > 	1.)  No suEXEC at all  (i.e without a --enable-suexec)
> > 	2.)  The original suEXEC behaviour  (i.e --enable-suexec and the other
> > 	     original options)
> > 	3.)  suEXEC with options (--with-suexec-opt)
> 
> OK, maybe I didn't make my point clear:
> 
> After my patch applied, one can choose at compiletime between the original
> behaviour and the new one.  Let me elaborate, what the new one actually
> does and which files are affected by the patch:
> 
>   - http_core.h has more OPT_* now.  For this, I had to change the typedef
>     allow_options_t from unsinged char to int.
>   
>   - http_core.c is changed in order to parse the new available options in
>     access.conf.
> 
>   - util_scrip.c is changed so that it calls suEXEC like in the two cases
>     in the original source (i.e ~user or <Virtualhost> with UID and GID
>     set) and now also when `SuExec' is set for this <Directory>.
> 
>     Also, create_argv(), has been changed.  All Options set for a specific
>     <Directory> are given as commandline argument to suEXEC.
> 
>   - Of course, suEXEC has changed:
>     
>     - I wrote a function findtarget(), which tries to find the target of a
>       symlink.  It expects an absolute path (the link) and returns either a
>       absolute path to the target, or NULL.
>     
>     - I wrote a function expand(), which stripes out ../'s, ./'s and /// out
>       from a path.  This function is used within findtarget().
> 
>     - suEXEC now also expects the options set for a <Directory> as
>       commandline argument.
> 
>     - Many if's are added to tune the behaviour of suEXEC in presence of
>       any options related to suEXEC, like:
>       	SuExecFollowSymLinks:
> 		Symlinks of _scripts_ will be followed, as long as
> 			- findtarget() returns a target.
> 			- this target is a regular file.
> 			- the inode and dev_id of target and the
> 			  stat-structure of the `stat()'ed link are
> 			  identical.
> 			- owner uid of link and target match.
> 			- group gid of link and target match, or the
> 			  SuExecTrySecondaryGroups was set and the owner of
> 			  the script is a member of both groups, or the
> 			  SuExecAllowOtherGroups was set.
> 			- both directories (of link and target) are not
> 			  symlinks.
> 			- both directories fullfill the requirements for
> 			  directories (i.e writability check, etc...)
> 
> 	SuExecTrySecondaryGroups:
> 		There are different places, in which suEXEC compares gid's
> 		of files and errors out, if they don't match.  When this
> 		option is set, the gid's may differ, as long as the owner
> 		is a member of both groups given by the gid's.
> 
> 	SuExecAllowDirectoryWritableByGroup:
> 		suEXEC will allow Directories to be writable by group, as
> 		long as the owner of the script is a member of it.  The
> 		SuExecAllowOtherGroups Option doesn't apply in this case
> 		(see below).
> 
> 	SuExecAllowProgramWritableByGroup:
> 		suEXEC will allow scripts to be writable by group, as long
> 		as the owner of the script is a member of it and the of the
> 		group of the directory.  The SuExecAllowOtherGroups Option
> 		doesn't apply in this case (see below).
> 		
> 	SuExecAllowOtherGroups:
> 		The last Option (SuExecAllowOtherGroups) is for
> 		compatibility with the original behavior of suEXEC, which
> 		has -- in my opinion -- a bug:  It doesn't check, wether
> 		the owner of a script is actually a member of the group of
> 		the script.  My implementation does, and errors out, when
> 		this is not the case _and_ SuExecAllowOtherGroups was _not_
> 		set.  In consequence of this mentioned `bug', initgroup()
> 		does _not_ set the _primary_ group of a user in the
> 		original source!
> 
> So, what do you think?  IMHO, this is an improvement over the original
> behavior of suEXEC, since sysadmin' have full control over suEXEC on a
> per-<Directory> basis.  Also, you may choose the original behaviour of
> suEXEC and change anything.
> 
> Sure, the code of suEXEC has changed significantly in complexity and size,
> but, hey:  This is a matter of testing.
> 
> cheers,
>   oec

Re: Contribution: SuEXEC Options

Posted by Oezguer Kesim <ke...@math.fu-berlin.de>.
Thus spake Marc Slemko (marcs@worldgate.com):

> >     Also, create_argv(), has been changed.  All Options set for a specific
> >     <Directory> are given as commandline argument to suEXEC.
> 
> suexec is designed so it does not trust anything passed to it on the
> command line, but verifies it all itself.  What stops anyone else who can
> get access to the user Apache runs as from calling suexec with whatever 
> arguments they want in your case?

Well, as I said in my last mail, the important fact is, that someone got
access to another userid -- this hasn't to do with suexec.

Anyway, to relax you about this, I would write a small parser for a
suexec.conf, in wich all the Options can be put into, per filesystem path.
The only thing wich would remain in the access.conf would be the Option
SuExec for which <Directory> suEXEC should be called -- this will also
reduce modifications in the source besides suexec.c to a minimum.

Then, again, suEXEC has full control about when and what it will execute
but still gaining a optimum of configurability for the admin -- without
option-handling over **argv.

Deal?
  
cheers,
  oec 
  who definitely needs the suEXEC options

Re: Contribution: SuEXEC Options

Posted by Oezguer Kesim <ke...@math.fu-berlin.de>.
Thus spake Marc Slemko (marcs@worldgate.com):

> >   - util_scrip.c is changed so that it calls suEXEC like in the two cases
> >     in the original source (i.e ~user or <Virtualhost> with UID and GID
> >     set) and now also when `SuExec' is set for this <Directory>.
> > 
> >     Also, create_argv(), has been changed.  All Options set for a specific
> >     <Directory> are given as commandline argument to suEXEC.
> 
> suexec is designed so it does not trust anything passed to it on the
> command line, but verifies it all itself.  What stops anyone else who can
> get access to the user Apache runs as from calling suexec with whatever 
> arguments they want in your case?

Be carefull.  The current implementation of suexec does not check, wether
the owner of a script is in the group of the script.

My opinion is:  On a machine, where a user can get access to the user
who is authorized to run suexec, is cracked anyway.  A attacker, who gains
access to user foo also could become bar or even root.  So don't blame
suexec if your machine is broken.

But, you are right, I can't verify the origin of the calling process.  On
the other hand, my patch isn't enabled per default.  It is designed for
situations, were access to the server running apache is restricted to root
and the webadmin, as in our network.  And this is, what a admin is
responsible for.  I say: If you want a full controled usage of suEXEC, just
feel free, but protect your machine carefully -- this should be fullfilled
anyway.

Hm... well, I will think about this again and will give a solution for the
problem you mentioned, which hopefully satisfies _you_.

cheers,
  oec

Re: Contribution: SuEXEC Options

Posted by Oezguer Kesim <ke...@math.fu-berlin.de>.
Thus spake Jim Jagielski (jim@jaguNET.com):

> My only comment on suEXEC is that, IIRC, it was designed to be as small
> and as "light" as possible. Sure, that made it somewhat restrictive and
> "less powerful" but easier to check out, security-wise. 

I know why suEXEC is build the way it is.  But I'm not talking about
`power', I'm talking about the necessary condition for our site can
start to use Apache.

And, hey, I'm not going to write a sendmail-like thing, we talk about a
software, which has no special data-structure, not more than three
functions, about four places, where a ?alloc occurs, about four places
where a snprintf or strncmp occurs, which almost everywhere says
"log_error(); exit();".  We _can_ test it.

It would be quite different to set httpd setuid root -- I don't ask for
that (No, no, no).

> If a hole exists in suEXEC, it gets placed right on Apache's door step,
> and that's another reason why it was designed the way it was: to reduce
> that possibility.  To increase the "power" and hence complexity of suEXEC
> does open Apache to just this scenario.

Well, if someone compiles suEXEC whit MAX_UID==0, and another exploits it,
the same thing will happen.  But it is not suEXEC's or Apache's fault.

> How about having these patches under 'contrib' or something a little
> bit more "removed" from the official source? There are other third-party
> programs (the best IMO being 'cgiwrap') which provide the extended capability
> and maybe this could be suEXEC+, which would also be 3rd party.

OK, the only thing I want to see in apache, is the possibility to say per
<Directory>:  Option SuExec.

The rest is up to the whatever wrapper.

cheers,
  oec

Re: Contribution: SuEXEC Options

Posted by Marc Slemko <ma...@worldgate.com>.
On Sat, 14 Nov 1998, Oezguer Kesim wrote:

>   - util_scrip.c is changed so that it calls suEXEC like in the two cases
>     in the original source (i.e ~user or <Virtualhost> with UID and GID
>     set) and now also when `SuExec' is set for this <Directory>.
> 
>     Also, create_argv(), has been changed.  All Options set for a specific
>     <Directory> are given as commandline argument to suEXEC.

suexec is designed so it does not trust anything passed to it on the
command line, but verifies it all itself.  What stops anyone else who can
get access to the user Apache runs as from calling suexec with whatever 
arguments they want in your case?


Re: Contribution: SuEXEC Options

Posted by Oezguer Kesim <ke...@math.fu-berlin.de>.
Thus spake Oezguer Kesim (kesim-apache@math.fu-berlin.de):

> I made a implementation of all the things above.  With my patch applied, you
> can choose between:
> 	1.)  No suEXEC at all  (i.e without a --enable-suexec)
> 	2.)  The original suEXEC behaviour  (i.e --enable-suexec and the other
> 	     original options)
> 	3.)  suEXEC with options (--with-suexec-opt)

OK, maybe I didn't make my point clear:

After my patch applied, one can choose at compiletime between the original
behaviour and the new one.  Let me elaborate, what the new one actually
does and which files are affected by the patch:

  - http_core.h has more OPT_* now.  For this, I had to change the typedef
    allow_options_t from unsinged char to int.
  
  - http_core.c is changed in order to parse the new available options in
    access.conf.

  - util_scrip.c is changed so that it calls suEXEC like in the two cases
    in the original source (i.e ~user or <Virtualhost> with UID and GID
    set) and now also when `SuExec' is set for this <Directory>.

    Also, create_argv(), has been changed.  All Options set for a specific
    <Directory> are given as commandline argument to suEXEC.

  - Of course, suEXEC has changed:
    
    - I wrote a function findtarget(), which tries to find the target of a
      symlink.  It expects an absolute path (the link) and returns either a
      absolute path to the target, or NULL.
    
    - I wrote a function expand(), which stripes out ../'s, ./'s and /// out
      from a path.  This function is used within findtarget().

    - suEXEC now also expects the options set for a <Directory> as
      commandline argument.

    - Many if's are added to tune the behaviour of suEXEC in presence of
      any options related to suEXEC, like:
      	SuExecFollowSymLinks:
		Symlinks of _scripts_ will be followed, as long as
			- findtarget() returns a target.
			- this target is a regular file.
			- the inode and dev_id of target and the
			  stat-structure of the `stat()'ed link are
			  identical.
			- owner uid of link and target match.
			- group gid of link and target match, or the
			  SuExecTrySecondaryGroups was set and the owner of
			  the script is a member of both groups, or the
			  SuExecAllowOtherGroups was set.
			- both directories (of link and target) are not
			  symlinks.
			- both directories fullfill the requirements for
			  directories (i.e writability check, etc...)

	SuExecTrySecondaryGroups:
		There are different places, in which suEXEC compares gid's
		of files and errors out, if they don't match.  When this
		option is set, the gid's may differ, as long as the owner
		is a member of both groups given by the gid's.

	SuExecAllowDirectoryWritableByGroup:
		suEXEC will allow Directories to be writable by group, as
		long as the owner of the script is a member of it.  The
		SuExecAllowOtherGroups Option doesn't apply in this case
		(see below).

	SuExecAllowProgramWritableByGroup:
		suEXEC will allow scripts to be writable by group, as long
		as the owner of the script is a member of it and the of the
		group of the directory.  The SuExecAllowOtherGroups Option
		doesn't apply in this case (see below).
		
	SuExecAllowOtherGroups:
		The last Option (SuExecAllowOtherGroups) is for
		compatibility with the original behavior of suEXEC, which
		has -- in my opinion -- a bug:  It doesn't check, wether
		the owner of a script is actually a member of the group of
		the script.  My implementation does, and errors out, when
		this is not the case _and_ SuExecAllowOtherGroups was _not_
		set.  In consequence of this mentioned `bug', initgroup()
		does _not_ set the _primary_ group of a user in the
		original source!

So, what do you think?  IMHO, this is an improvement over the original
behavior of suEXEC, since sysadmin' have full control over suEXEC on a
per-<Directory> basis.  Also, you may choose the original behaviour of
suEXEC and change anything.

Sure, the code of suEXEC has changed significantly in complexity and size,
but, hey:  This is a matter of testing.

cheers,
  oec