-1

This is based on another question of mine I am trying to prevent executions of certain commands using a script. I got the script to work perfectly in interactive shells but for non interactive shells it doesn't prevent its execution. I did see this and I am doing the same thing.

/home/user/stop.sh (sourced in .bashrc)

#!/usr/bin/env bash
shopt -s extdebug; stop_cmd () {
    [ -n "$COMP_LINE" ] && return  # not needed for completion
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # not needed for prompt
    local this_command=$BASH_COMMAND;
    echo $this_command" Not Allowed";
    return 1
};
trap 'stop_cmd' DEBUG

/home/user/temp.sh

#!/usr/bin/env bash
ls

I used the BASH_ENV variable suggested by @Inian to get my script into script files that use non-interactive shells.

In a new shell

#:export BASH_ENV=/home/user/stop.sh
#:ls
ls Not Allowed --> This is because of the source in .bashrc
#:             --> Prompt appears. ls did not run
#:./temp.sh
./temp.sh: /usr/share/bashdb/bashdb-main.inc: No such file or directory
./temp.sh: warning: cannot start debugger; debugging mode disabled
ls Not Allowed  --> Because of the $BASH_ENV
Directory contents displayed  --> ls ended up running
#:             --> Prompt appears after executing temp.sh

But this behavior is not displayed if I source stop.sh within temp.sh directly and it works like a charm.

1 Answers1

1

I am afraid it is not possible to restrict command execution with the DEBUG trap within non-interactive shell.

Alternatively you can try different approaches:

Restriction with rbash, BASH_ENV and command_not_found_handle

  • Setup a test user
  • Symlink the allowed commands within test-users homedir

example:

allow=(bash cat sed)
user="ruser"
homedir="/home/$user"
mkdir "$homedir/bin"
for c in ${allow[@]}; do
  ln -s /bin/$c $homedir/bin
done
  • Set the PATH variable in /home/$user/.bashenvrc and ensure that it only lists bindirs you want to allow, for example /home/$user/bin;...;...
  • Set BASH_ENV=/home/$user/.bashenvrc from /home/$user/.bashrc
  • Use a restricted shell via bash -r so the user cannot execute command names containing slashes, for example /bin/sh.

But keep the rbash security weaknesses in mind.

You want more fine grained restriction possibilities? You could extend this method with the command_not_found_handle () function, so every command which is not found in PATH can be handled in detail.

function command_not_found_handle () {
  while read -r pattern; do
    [[ "$1" =~ $pattern ]] \
    && command="/bin/restrict/$1" \
    && [ -h $command -a -x $command ] \
    && shift \
    && { $command "$@"; return $?; }
  done </bin/restrict/whitelist
  echo "Command '$1' not found."
}

Restriction with rbash, blacklist and wrappers

  • Setup a blacklist as root

example:

cat <<EOF >/home/cmd_blacklist
  ~/bin/ls -al
  ~/bin/rm -rf
EOF
chmod g-wx+r,o-wx+r /home/cmd_blacklist
  • Add BASH_ENV=~/.bashenvrc to ~/.bashrc
  • Edit ~/.bashenvrc

example:

PATH="$HOME/bin"
errmsg='arguments not allowed: $cmd $pattern'
while read -r cmd pattern; do
  [ ! -e "$cmd" ] && continue # skip nonexistent
  [ "$cmd" == "$(basename $cmd)" ] && continue  # prevent recursion
  eval "function $(basename $cmd) () { [[ \"$(printf $'%s ' \$@)\" =~ $pattern ]] && echo \"$errmsg\" || $cmd \"\$@\"; }"
done </home/cmd_blacklist

Now every line of blacklist of the form [cmd] [pattern] should be read, from which wrapper functions are generated. You could also export the wrapper functions to subshell

Further reading and straightforward method with sudo

For many cases editing the sudoers configuration to restrict command execution is the best choice.

domson
  • 341
  • Well I thought of that already.. moreover If I was to take this approach I would just add users to groups who can run this script right... but my requirement is more fine grained.. for eg: if some one runs ls I will permit it. But if some one runs ls -al I don’t want to.. for this I need to study the entire command carefully and compare against a text file that have certain rules... and hence the need for this.. I hope some one can answer this – Sam Thomas Feb 08 '18 at 06:33
  • But in my above comment ls will be in PATH i just dont want ls -al to be run (running ls by itself is fine).. Using the edited approach will I not be force to have an empty PATH so that every command goes through this handle? Also I do not want to give them a notion that command is not present in PATH. A person could easily install ls into that PATH. – Sam Thomas Feb 08 '18 at 08:06