Tuesday, May 29, 2012

sudo changes PATH - why?


This is the PATH variable without sudo:




$ echo 'echo $PATH' | sh

/opt/local/ruby/bin:/usr/bin:/bin



This is the PATH variable with sudo:




$echo 'echo $PATH' | sudo sh

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin



As far as I can tell, sudo is supposed to leave PATH untouched. What's going on? How do I change this? (This is on Ubuntu 8.04).



UPDATE: as far as I can see, none of the scripts started as root change PATH in any way.



From man sudo:




To prevent command spoofing, sudo checks ``.'' and ``'' (both denoting current directory) last when searching for a command in the user's PATH (if one or both are in the PATH). Note, however, that the actual PATH environment variable is not modified and is passed unchanged to the program that sudo executes.



Source: Tips4all

14 comments:

  1. This is an annoying function of sudo on ubuntu.
    Note this doesn't happen on fedora for example
    as sudo is not built with the --with-secure-path option there.

    To work around this "problem" on ubuntu I do
    the following in my ~/.bashrc

    alias sudo='sudo env PATH=$PATH'


    Note the above will work for commands that don't reset the $PATH themselves.
    However `su' resets it's $PATH so you must use -p to tell it not to. I.E.:

    sudo su -p

    ReplyDelete
  2. In case someone else runs accross this and wants to just disable all path variable changing for all users.
    Access your sudoers file by using the command:visudo. You should see the following line somewhere:


    Defaults env_reset


    which you should add the following on the next line


    Defaults !secure_path


    secure_path is enabled by default. This option specifies what to make $PATH when sudoing. The exclamation mark disables the feature.

    ReplyDelete
  3. 'PATH' is an environment variable, and as such is by default reset by sudo.

    You need special permissions to be permitted to do this.

    From Man Sudo


    -E The -E (preserve environment) option will override the env_reset
    option in sudoers(5)). It is only available when either the match-
    ing command has the SETENV tag or the setenv option is set in sudo-
    ers(5).



    Environment variables to be set for the command may also be passed on
    the command line in the form of VAR=value, e.g.
    LD_LIBRARY_PATH=/usr/local/pkg/lib. Variables passed on the command
    line are subject to the same restrictions as normal environment vari-
    ables with one important exception. If the setenv option is set in
    sudoers, the command to be run has the SETENV tag set or the command
    matched is ALL, the user may set variables that would overwise be for-
    bidden. See sudoers(5) for more information.


    An Example of usage:


    cat >> test.sh
    env | grep "MYEXAMPLE" ;
    ^D



    # sh test.sh
    #
    # MYEXAMPLE=1 sh test.sh
    MYEXAMPLE=1
    #
    # MYEXAMPLE=1 sudo sh test.sh
    #
    # MYEXAMPLE=1 sudo MYEXAMPLE=2 sh test.sh
    MYEXAMPLE=2
    #


    update

    man 5 sudoers :

    env_reset If set, sudo will reset the environment to only contain
    the LOGNAME, SHELL, USER, USERNAME and the SUDO_* vari-
    ables. Any variables in the caller's environment that
    match the env_keep and env_check lists are then added.
    The default contents of the env_keep and env_check
    lists are displayed when sudo is run by root with the
    -V option. If sudo was compiled with the SECURE_PATH
    option, its value will be used for the PATH environment
    variable. This flag is on by default.


    So may need to check that this is/is not compiled in.

    It is by default in Gentoo

    ( From the build Script )
    ....
    ROOTPATH=$(cleanpath /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin${ROOTPATH:+:${ROOTPATH}})
    ....
    econf --with-secure-path="${ROOTPATH}"

    ReplyDelete
  4. Looks like this bug has been around for quite a while! Here are some bug references you may find helpful (and may want to subscribe to / vote up, hint, hint...):



    Debian bug #85123 ("sudo: SECURE_PATH still can't be overridden") (from 2001!)


    It seems that Bug#20996 is still present in this version of sudo. The
    changelog says that it can be overridden at runtime but I haven't yet
    discovered how.


    They mention putting something like this in your sudoers file:

    Defaults secure_path="/bin:/usr/bin:/usr/local/bin"


    but when I do that in Ubuntu 8.10 at least, it gives me this error:

    visudo: unknown defaults entry `secure_path' referenced near line 10




    Ubuntu bug #50797 ("sudo built with --with-secure-path is problematic")


    Worse still, as far as I can tell, it
    is impossible to respecify secure_path
    in the sudoers file. So if, for
    example, you want to offer your users
    easy access to something under /opt,
    you must recompile sudo.



    Yes. There needs to be a way to
    override this "feature" without having
    to recompile. Nothing worse then
    security bigots telling you what's
    best for your environment and then not
    giving you a way to turn it off.



    This is really annoying. It might be
    wise to keep current behavior by
    default for security reasons, but
    there should be a way of overriding it
    other than recompiling from source
    code! Many people ARE in need of PATH
    inheritance. I wonder why no
    maintainers look into it, which seems
    easy to come up with an acceptable
    solution.



    I worked around it like this:

    mv /usr/bin/sudo /usr/bin/sudo.orig


    then create a file /usr/bin/sudo containing the following:

    #!/bin/bash
    /usr/bin/sudo.orig env PATH=$PATH "$@"


    then your regular sudo works just like the non secure-path sudo




    Ubuntu bug #192651 ("sudo path is always reset")


    Given that a duplicate of this bug was
    originally filed in July 2006, I'm not
    clear how long an ineffectual env_keep
    has been in operation. Whatever the
    merits of forcing users to employ
    tricks such as that listed above,
    surely the man pages for sudo and
    sudoers should reflect the fact that
    options to modify the PATH are
    effectively redundant.

    Modifying documentation to reflect
    actual execution is non destabilising
    and very helpful.




    Ubuntu bug #226595 ("impossible to retain/specify PATH")


    I need to be able to run sudo with
    additional non-std binary folders in
    the PATH. Having already added my
    requirements to /etc/environment I was
    surprised when I got errors about
    missing commands when running them
    under sudo.....

    I tried the following to fix this
    without sucess:


    Using the "sudo -E" option - did not work. My existing PATH was still reset by sudo
    Changing "Defaults env_reset" to "Defaults !env_reset" in /etc/sudoers -- also did not work (even when combined with sudo -E)
    Uncommenting env_reset (e.g. "#Defaults env_reset") in /etc/sudoers -- also did not work.
    Adding 'Defaults env_keep += "PATH"' to /etc/sudoers -- also did not work.


    Clearly - despite the man
    documentation - sudo is completely
    hardcoded regarding PATH and does not
    allow any flexibility regarding
    retaining the users PATH. Very
    annoying as I can't run non-default
    software under root permissions using
    sudo.

    ReplyDelete
  5. Works now using sudo from the karmic repositories. Details from my configuration:

    root@sphinx:~# cat /etc/sudoers | grep -v -e '^$' -e '^#'
    Defaults env_reset
    Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/grub-1.96/sbin:/opt/grub-1.96/bin"
    root ALL=(ALL) ALL
    %admin ALL=(ALL) ALL
    root@sphinx:~# cat /etc/apt/sources.list
    deb http://au.archive.ubuntu.com/ubuntu/ jaunty main restricted universe
    deb-src http://au.archive.ubuntu.com/ubuntu/ jaunty main restricted universe

    deb http://au.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted universe
    deb-src http://au.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted universe

    deb http://security.ubuntu.com/ubuntu jaunty-security main restricted universe
    deb-src http://security.ubuntu.com/ubuntu jaunty-security main restricted universe

    deb http://au.archive.ubuntu.com/ubuntu/ karmic main restricted universe
    deb-src http://au.archive.ubuntu.com/ubuntu/ karmic main restricted universe

    deb http://au.archive.ubuntu.com/ubuntu/ karmic-updates main restricted universe
    deb-src http://au.archive.ubuntu.com/ubuntu/ karmic-updates main restricted universe

    deb http://security.ubuntu.com/ubuntu karmic-security main restricted universe
    deb-src http://security.ubuntu.com/ubuntu karmic-security main restricted universe
    root@sphinx:~#

    root@sphinx:~# cat /etc/apt/preferences
    Package: sudo
    Pin: release a=karmic-security
    Pin-Priority: 990

    Package: sudo
    Pin: release a=karmic-updates
    Pin-Priority: 960

    Package: sudo
    Pin: release a=karmic
    Pin-Priority: 930

    Package: *
    Pin: release a=jaunty-security
    Pin-Priority: 900

    Package: *
    Pin: release a=jaunty-updates
    Pin-Priority: 700

    Package: *
    Pin: release a=jaunty
    Pin-Priority: 500

    Package: *
    Pin: release a=karmic-security
    Pin-Priority: 450

    Package: *
    Pin: release a=karmic-updates
    Pin-Priority: 250

    Package: *
    Pin: release a=karmic
    Pin-Priority: 50
    root@sphinx:~# apt-cache policy sudo
    sudo:
    Installed: 1.7.0-1ubuntu2
    Candidate: 1.7.0-1ubuntu2
    Package pin: 1.7.0-1ubuntu2
    Version table:
    *** 1.7.0-1ubuntu2 930
    50 http://au.archive.ubuntu.com karmic/main Packages
    100 /var/lib/dpkg/status
    1.6.9p17-1ubuntu3 930
    500 http://au.archive.ubuntu.com jaunty/main Packages
    root@sphinx:~# echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/grub-1.96/sbin:/opt/grub-1.96/bin
    root@sphinx:~# exit
    exit
    abolte@sphinx:~$ echo $PATH
    /home/abolte/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/grub-1.96/sbin:/opt/grub-1.96/bin:/opt/chromium-17593:/opt/grub-1.96/sbin:/opt/grub-1.96/bin:/opt/xpra-0.0.6/bin
    abolte@sphinx:~$


    It's wonderful to finally have this solved without using a hack.

    ReplyDelete
  6. # cat .bash_profile | grep PATH
    PATH=$HOME/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
    export PATH

    # cat /etc/sudoers | grep Defaults
    Defaults requiretty
    Defaults env_reset
    Defaults env_keep = "SOME_PARAM1 SOME_PARAM2 ... PATH"

    ReplyDelete
  7. Just comment out "Defaults env_reset" in /etc/sudoers

    ReplyDelete
  8. Secure_path is your friend, but if you want to exempt yourself from secure_path just do


    sudo visudo


    And append


    Defaults exempt_group=your_goup


    If you want to exempt a bunch of users create a group, add all the users to it, and use that as your exempt_group. man 5 sudoers for more.

    ReplyDelete
  9. I think it is in fact desirable to have sudo reset the PATH: otherwise an attacker having compromised your user account could put backdoored versions of all kinds of tools on your users' PATH, and they would be executed when using sudo.

    (of course having sudo reset the PATH is not a complete solution to these kinds of problems, but it helps)

    This is indeed what happens when you use

    Defaults env_reset


    in /etc/sudoers without using exempt_group or env_keep.

    This is also convenient because you can add directories that are only useful for root (such as /sbin and /usr/sbin) to the sudo path without adding them to your users' paths. To specify the path to be used by sudo:

    Defaults secure_path="/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin"

    ReplyDelete
  10. the recommended solution in the comments on the OpenSUSE distro suggests to change:

    Defaults env_reset

    to:

    Defaults !env_reset

    and then presumably to comment out the following line which isn't needed:

    Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASURE MENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL L ANGUAGE LINGUAS XDG_SESSION_COOKIE"

    ReplyDelete
  11. Just edit env_keep in /etc/sudoers

    it looks something like this:

    Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASURE MENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL L ANGUAGE LINGUAS XDG_SESSION_COOKIE"

    just append PATH at the end, so after the change it would look like this:

    Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASURE MENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL L ANGUAGE LINGUAS XDG_SESSION_COOKIE **PATH**"

    close all ur terminal and then open again.

    ReplyDelete
  12. This seemed to work for me

    sudo -i


    which takes on the non-sudo PATH

    ReplyDelete
  13. Does root have anything that sets PATH in .bashrc? This is assuming that since you're on Linux, sh is really bash.

    ReplyDelete
  14. Er, it's not really a test if you don't add something to your path:


    bill@bill-desktop:~$ ls -l /opt/pkg/bin
    total 12
    -rwxr-xr-x 1 root root 28 2009-01-22 18:58 foo
    bill@bill-desktop:~$ which foo
    /opt/pkg/bin/foo
    bill@bill-desktop:~$ sudo su
    root@bill-desktop:/home/bill# which foo
    root@bill-desktop:/home/bill#

    ReplyDelete