[sudo-users] security bug -- sudo undefines functions in environment

L. A. Walsh sudo at tlinx.org
Tue Aug 5 19:14:18 MDT 2014

Todd C. Miller wrote:
> Please understand that exported bash functions are just strings in
> the environment.  There is no such thing as a read-only environment
> variable--it is the shell that enforces attributes like read-only.
> As far as I know, the read-only attribute is not preserved in
> sub-shells as there is no way to specify in the environment that a
> variable should be read-only.
    Yes... but in a given shell instance if I've defined a var or functions
R/O, it isn't going to be redefined in a subscript -- they are propagated to
subscripts, as that's the main reason for the R/O existence -- to force
some values to be pervasively (or perversively) available.  The same
can go for functions.

    I do abnormal things with my bash...

for example I have some language macros read in out of my BASH_ENV,
so that things like

an "include" statement work in shell files that will search the path
like source, but will also do so when your "include" dir has subdirectories
(and prevent dup includes).

I even have a handy macro that only works for me (because i'm green
listed in the sudoer's file) where I can do

include lib/Needroot

and it will raise the script to run as root.

As for what I want -- just add a flag that says "environment preserving
applies to functions as well" -- then it can work in the whitelist or the
blacklist case.  I.e. it would have complete forward compatibility (nothing
new enabled by default), but would allow functions in the environment
to have the same status as variables.  i.e. either whitelisting by name
foobar() snore()  andthisonetoo(), or blanket approval and blacklisting if
someone wants blacklisting.

Almost every security model people put in automatic enforcements
for in linux supports the single-root-user paradigm, whereas I try
to flexibly use groups ACLS and more recently, FSCAPS.

But I hate progs that assume that only security is "user-owned" (I like
the group 'wheel' security to some extent... though wouldn't want all privs
automatically in wheel, just easy to access.  I also had to have different
UID's for local and domain maps in my windows groups -- but wanted them
to share the same doc files and home dirs... again -- common group was
the way, but sendmail was stubborn(but configurable), and ssh took patching.

Some people don't see that the things that other must go through to get 
alll these "helpful" security restrictions are notably less secure.

I still am annoyed at the samba folks renaming my client-controlled 
symlinks --
i.e. if you had unix extensions, and wide links (across or outside of 
share boundaries),
then someone decided that was a security problem.   But several sites 
had policies
that used the windows credentials to log into the server -- so the users 
already had server
access and could create symlinks there by logging in. -- so no extra 
privileges were
being given away -- just the possibility of more convenient access or 
of symlinks on a server, from a win-client.  Eventually the samba folks 
took in my patch
to re-enable them, but renamed the option to 'insecure wide-links' -- 
when they
were not insecure if the win-users already had server access, but 
apparently samba
got a black eye over that because someone had a cow....

Almost all of my unix/linux access is done remotely, as I use a win 
desktop and linux backend.
My win -station has no direct internet access, so things that clean out
my environment tend to disrupt that (like reusing pam_env to reset env, 
clears out DISPLAY & REMOTEHOST if it is called other than at the initial
contact)...(so I had to undo that damage that suse did there...)...

If I had a bunch of users, I'd probably try configuring smack (in the linux
kernel) for sensitivity and integrity... seems like it would be less 
than selinux if I did it right...

> For instance, the following bash function:
>     foo () {
> 	echo bar
>     }
> is stored in the environment as follows when exports:
>     foo=() { echo bar; }
> (In practice, there is a newline in there instead of a semicolon
> but it is easier to talk about a single line).
    A recent bash change -- was better when they were stored as 1 line
as you could sort and search on them more easily.
> The reason sudo doesn't pass through such environment variables is
> that sudo does its environment matching based on the variable name.
And here I thought it was something like:
--- plugins/sudoers/env.c 2013-06-04 02:48:29.000000000 -0700
+++ plugins/sudoers/env.c 2014-08-05 15:39:00.923728871 -0700
@@ -801,7 +802,7 @@
      /* Skip variables with values beginning with () (bash functions) */
      if ((cp = strchr(*ep, '=')) != NULL) {
-   if (strncmp(cp, "=() ", 3) == 0)
+   if (strncmp(cp, "### ", 3) == 0)
> So there is no way to distinguish between an environment variable
> "foo" and a "foo" that bash will interpret as a function.  Since
> functions get run in preference to commands on disk, you can see
> how this has security ramifications.
    Benefits if I am the one su'ing to root and don't want to read in 
versions of files. 
> In order to allow bash functions to be passed through safely, we
> need a way to preserve these variables that also matches on the
> beginning of the variable's value.  In other words, on the beginning
> "() {".
Hope you go with simple like the addtional global switch and just
have funcs match func()... if someone wants specific matching...

Then they can have it anyway they want -- which used to be what
unix was famous for... vs. other OS's and MS, being rather



More information about the sudo-users mailing list