So I have a file data.txt that stores user name and some piece of data, one line per user. I'd like to have a Bash script that is runable by the users and allows them to call

grep -w "^$USER" data.txt

to retrieve their piece of information but not being able to read the whole data.txt. Is there any simple setuid-trick to do it?

Doesn't have to be Bash, any C or Perl solution is fine.

  • Sorry, I don't get it. Care to provide a short example? – Pavel Nov 19 '15 at 16:29
  • Sorry, still doesn't make sense to me. The point is, the script will grep under their username on a file that I don't want to be readable for them as a whole (they can open the script and see where data.txt resides) – Pavel Nov 19 '15 at 16:49

This is a solution with Bash scripts.

I assume you cannot use setuid for scripts, as explained in this U&L answer. The advice therein is to use

a wrapper that sanitizes the environment (such as sudo with the env_reset option).

In this example I use /etc/our_secrets.txt instead of data.txt. At first restrict access to the file:

sudo chown root: /etc/our_secrets.txt
sudo chmod 600 /etc/our_secrets.txt

Then create a script /usr/local/sbin/sget_my_secret. This is the script:

exec /bin/grep -w "^$SUDO_USER" /etc/our_secrets.txt

And its permissions:

sudo chown root: /usr/local/sbin/sget_my_secret
sudo chmod 744 /usr/local/sbin/sget_my_secret

Now you should run sudo visudo and modify your sudoers file to allow users to invoke sudo /usr/local/sbin/sget_my_secret. The most basic way is to add

ALL ALL=(ALL) NOPASSWD: /usr/local/sbin/sget_my_secret

to the file. Now any user can run sudo sget_my_secret. For convenience you need another script, /usr/local/bin/get_my_secret:

exec /usr/bin/sudo /usr/local/sbin/sget_my_secret

Its permissions:

sudo chown root: /usr/local/bin/get_my_secret
sudo chmod 755 /usr/local/bin/get_my_secret

At this moment any user can run get_my_secret to obtain their piece of information (if any). This is what happens:

  1. get_my_secret runs with normal permissions.
  2. It tries to run sudo /usr/local/sbin/sget_my_secret.
  3. sudoers file says it can do this.
  4. sget_my_secret is run with elevated permissions.
  5. Elevated grep processes the file.

Security notes:

  • In my Debian the mentioned env_reset option is enabled by default.
  • You may want to replace this ALL ALL=(ALL) ... line with more restrictive one.
  • In the scripts I use full paths wherever I can.
  • Anyone able to run sget_my_secret with spoofed $SUDO_USER is able to retrieve somebody else's secret. I think if you can do this, you can also read our_secrets.txt directly.
  • You may think you could allow users to run sudo grep; but this would allow them to grep for anything in any file! The point of having sget_my_secret is to add just this one specialized executable in the sudoers file.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.