5

If I run a sudo command it will ask me for a password, however in that Terminal session for the next few minutes it will allow me to run sudo commands without asking me for a password as it will cache that I am allowed.

This is good for convenience, and I find it rather convenient so I don't want to fix this by meaning it asks for a password every time instead of caching.

But what I have recently found has been something rather worrying, if I create a little script like this for instance:

#!/bin/bash

sudo rm -rf /

And I execute it as the normal user in Terminal before I have executed any sudo commands then all is well and works as expected, it prompts me for the sudo password. However if I am to run a sudo command before executing this script without sudo it will cache that sudo commands should not ask for a password for a few minutes in this session and then even though I did not give the script sudo privileges it will not prompt me for a password and the script will be allowed to execute whatever sudo commands it wants.

Now I'm not the sort to execute many scripts without knowing what's in them but sometimes I have to install stuff from a script which I got from a trusted location, but I don't know for sure if there isn't anything bad in the script so I would like the piece of mind that it's not going to just hijack the sudo ability that has been granted to my Terminal session.

So my questions is, is it possible to make it so that I can run sudo commands and it will cache it for me, but then if I run a script not with sudo for the script not to be able to just hijack that ability? I understand that me executing the script is basically the same as me just executing the commands in the script in the order they are in there, but is there not a way of doing something clever so that it runs in a slightly different way or so that sudo is restricted for scripts that I run?

Really anything though that I didn't run with sudo shouldn't be able to run things with sudo. Including commands. If they are only hijacking the cached ability that is...

I am running Ubuntu GNOME 15.10 with GNOME 3.18.

I have a suggestion for how this could be done but I don't know the practicalities of this: could I make it so that when I execute a command and it starts running it it logs that to a file (like is done with all Terminal commands though maybe a bit too late for this - with the history command) and then when sudo is run it checks if I executed that command in Terminal (through the use of the log that logs when I do) and if not then it is assumed that it's not by me so it prompts me for a password?

4 Answers4

6

You can run

sudo -k

before you run your script. It will clear the cached credentials and the next sudo will ask again for your password.

Here's a way to do what you want (I think).

  1. Move your sudo elsewhere:

    mv /usr/bin/sudo /usr/bin/sudo_real
    
  2. Put the following into usr/bin/sudo:

    #!/bin/bash -i
    # Allows 'sudo' to be run with cached credentials from the command line,
    # but clears the cache if run from within a script.
    # Get the last command executed manually from the history
    LAST_COMMAND=`history | tail -n 1 | cut -c 8-`
    
    if [[ "${LAST_COMMAND}" == "sudo "* ]]; then
        # The last command was 'sudo' - i.e. the user ran sudo 
        sudo_real "$@"
    else
        # The last command was NOT sudo - so this sudo was called from within a script.
        # Force the cached credentials to be cleared. 
        sudo_real -k "$@"
    fi
    
  3. Make the new /usr/bin/sudo executable:

    chmod a+x /usr/bin/sudo
    
  4. Alias sudo to update the bash history when you run it from a shell by putting this in your ~/.bashrc:

    alias sudo="history -a;sudo"
    

Now, when YOU run sudo ... it will put the sudo ... into the bash history and the script will find it and run sudo_real. But when another script runs sudo, it won't be in the history, and it'll call sudo_real -k.

I think this is incredibly hairy, and I'd just live with the risk or use a new shell for scripts I didn't trust, personally :-)

muru
  • 207,228
Mark Smith
  • 1,313
  • 1
  • 11
  • 24
4

My stance on this issue is this : if you are unsure whether or not you may or may not run an app with root privillege while your credentials still haven't timed out, then just disable the timeout at all, make it 0. Specifically you need this setting in your /etc/sudoers file:

Defaults    timestamp_timeout=0

Man page defines it like so:

 timestamp_timeout
                   Number of minutes that can elapse before sudo will ask
                   for a passwd again.  The timeout may include a frac‐
                   tional component if minute granularity is insufficient,
                   for example 2.5.  The default is 15.  Set this to 0 to
                   always prompt for a password.  If set to a value less
                   than 0 the user's time stamp will never expire.  This
                   can be used to allow users to create or delete their
                   own time stamps via “sudo -v” and “sudo -k” respec‐
                   tively.

However, if you intend to be prudent, you can define the following function in .bashrc

sudo_check()
{
  real_path="$( realpath $1 )"
  file "$real_path" | grep -q -i script
  if [ $? -eq 0 ]; then
     grep -q 'sudo' "$real_path"  && \
     { echo '>>> ALERT: Its a script that requests sudo';
       echo '    resetting sudo timestamp';
       echo 'please rerun with sudo appended ';
     }
     sudo -k
  else
     sudo "$@"
  fi

}

This function will check whether or not a script contains call to sudo and alert you of that. Bellow is example of me running that function on a script ( which is my login screen background changer by the way )

$ sudo_check sergrep/chgreeterbg.sh                            
>>> ALERT: Its a script that requests sudo
    resetting sudo timestamp
muru
  • 207,228
2

If you have at least version 1.8.21 of sudo, you will want to set timestamp_type to ppid instead of the default tty.
By default, sudo will 'cache credentials' per terminal. This setting will make sudo only reuse them if the invoking process is the same. Any scripts you run will have a PID different from your shell, and will not be able to use your authorization.

Specifically, the following line needs to be in your sudoers file:
Defaults timestamp_type=ppid

More details can be found in the manual.

citriqa
  • 21
2

How can you differentiate between a script and an executable binary command?

Of course you can think of defining a function named sudo that will have the sanity checks before running the actual binary but

  • As the script can have any name, what if a script has a name like ls? So checking for extensions like .sh won't help
  • Also reading shebang as the first line of the script won't help too because a script can run without having a shebang

I think, if you are too paranoid about it, you can think of disabling password caching altogether by creating an alias like:

alias sudo='sudo -k'

and put it in your ~/.bashrc.

heemayl
  • 93,925