3

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?

  • 2
    Well you could run sudo -k , before running any script . Man page : -k, --reset-timestamp: When used without a command, invalidates the user's cached credentials. In other words, the next time sudo is run a password will be required. Basically you ensure that you invalidate possibility of using cached credentials in advance – Sergiy Kolodyazhnyy Mar 17 '16 at 19:21
  • @Serg: I have come up with a suggestion though I don't know of the full practicalities of this, I have updated my question with it at the end. What do you think? – user364819 Mar 17 '16 at 19:58
  • I suppose you could alias sudo to a script which would check the last item in the history and act accordingly. – Mark Smith Mar 17 '16 at 20:01
  • @MarkSmith: I'm not sure that it could just be the usual history though because that can be written to by anything and making it owned by root won't really solve anything, just make things worse in certain ways... So it will probably have to be a different history which is owned by root but doesn't mean that I exactly have to write to it as root, but maybe there should be a root daemon running which just checks the commands I run and then adds them to the history. – user364819 Mar 17 '16 at 20:25
  • I'll try and write it shortly... – Mark Smith Mar 17 '16 at 20:31
5

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 :-)

  • Is there a not easy more automatic way of doing this? – user364819 Mar 17 '16 at 19:23
  • 1
    The script should not only check if sudo was in the last command but also make sure that the commands are the same because I could have just run the sudo apt-get update command, and then the script could be wanting to run sudo rm -rf /, and just because they both have sudo in them your script would allow them to run... – user364819 Mar 17 '16 at 22:43
  • But this is a good answer, almost exactly what I want! I'll accept it after you fix that! ;-) – user364819 Mar 17 '16 at 22:44
  • If YOU run the script with sudo, it can do stuff as root anyway, without having to do sudo itself. – Mark Smith Mar 17 '16 at 22:45
  • Ah yes, well I guess so... – user364819 Mar 17 '16 at 22:47
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
  • 1
    Note that it won't detect a script which calls another script which runs sudo. – Mark Smith Mar 18 '16 at 22:15
  • Perhaps you should either link to this answer, or make it clear that the line you speak of does not already exist in that file. You should also specify that you should edit it with sudo visudo rather than just a normal text editor. – user364819 Mar 26 '16 at 14:02
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.

  • Well that basically is the same as making sudo reset timestamp each time, Panda wants to just exclude scripts from being "cached" – Sergiy Kolodyazhnyy Mar 17 '16 at 19:26
  • @Serg I know..my first part includes answer to that.. – heemayl Mar 17 '16 at 19:27
  • Is there no way of making it so that just anything that I run with sudo is not allowed to run any sudo commands without my proper authentication? – user364819 Mar 17 '16 at 19:38
  • I have come up with a suggestion though I don't know of the full practicalities of this, I have updated my question with it at the end. What do you think? – user364819 Mar 17 '16 at 19:57
  • @heemayl i like the idea of a function though. It has precedence over command names , so function named sudo will run instead of actual sudo – Sergiy Kolodyazhnyy Mar 17 '16 at 20:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy