1

I want to run command as root inside a bash script.

This command needs to be able to read from STDIN.

I have a root password as a local variable inside bash script and don't want to enter it manually.

Whan I've tried:

  1. I know approach with running initial script as root (and actually using it, but looking for better ways to live) but it has it's limitations when complex logic, different users and environment variables involved.

  2. I know about sudo-NOPASSWD approach, but it's not something I want to use for security reasons.

  3. I know su -c approach, but it makes me enter root password every time:

su - -c "adduser new_user"
  1. I know heredoc approach but it blocks STDIN for me:
read -sp "Please, enter root password: " ROOT_PASSWD
echo
su - <<EOI
$ROOT_PASSWD
echo "<This password input is handled automatically based on previously asked password>"

Do NOT asks user password and data as supposed to:

adduser new_user EOI

vdshb
  • 113

2 Answers2

0

Saving root password in any file is tantamount to shooting yourself in the foot. Too high risk.

Best approach is to have a script for the dedicated task and assign that with the setuid-bit permission (ex. chmod 4755) to run as root and with group permissions to a group dedicated for the task. That script would not assign write privileges to anyone but root, who would be the script owner.

Then create a dedicated user ID to perform that task in a dedicated space (examples are cron, sync, daemon, lp, mail, sys, etc). Then have that user run the task when required. That approach makes it a configured facility with known privilege to perform a restricted task. That is the cleanest approach.

The whole point of sudo is to force an interractive verification that the user attempting to gain superuser privileges is authentic and legitimate because they are trying to "circumvent" pre-defined processes. It isn't meant to be easy.

It seems setuid has been disabled without attempts to use it flagging its inactive status. That is not Kosher !!!

Small script to demonstrate setuid function is NOT active:

#!/bin/sh

BASE=basename &quot;$0&quot; &quot;.sh&quot; TEST="${BASE}.testor"

touch "${TEST}"

Snapshot of that script in action:

snapshot of SetUID action

  • The sticky bit (t) has nothing whatsoever to do with setuid privileges. Furthermore scripts ignore setuid bits and have done for years – Chris Davies Sep 14 '22 at 06:57
  • Sorry. I meant the setuid flag. chmod 4755 will set a script to set effective ID=root if script is owned by root and permitted to run by group/other. – Eric Marceau Sep 14 '22 at 17:28
  • Scripts ignore setuid bits. It doesn't matter how you set it, it's still ignored – Chris Davies Sep 14 '22 at 19:05
  • @roaima, about the setuid bit being ignored: you are incorrect. I just tested it with a simple script and proved without question that setuid is functional to give access, as root, to a non-root user. You must be working with a defective Linux. Mine is UbuntuMATE 20.04 LTS, and it works just fine. It is unfortunate that I cannot attach images to this comment. – Eric Marceau Sep 14 '22 at 20:16
  • It doesn't work for me, and there's no evidence in your screenshot that it worked for you – Chris Davies Sep 14 '22 at 20:27
  • Linux ignores the setuid bit for scripts, see e.g. Allow setuid on shell scripts. I can't exactly tell what your screenshot is trying to show there, other than that the setuid shell script runs. It doesn't produce any output that would tell what UID it runs under, nor does the screenshot include anything executed afterwards to see what it did. I'd suggest trying something like printf '#!/bin/sh\nid\n' > suidtest.sh && chmod u+s,a+xr suidtest.sh and then running that. – ilkkachu Sep 14 '22 at 20:35
  • @roaima, I stand corrected. Screenshots updated. – Eric Marceau Sep 14 '22 at 20:35
  • Though also note that if you manage to run Bash setuid without the -p option, it'll switch back – ilkkachu Sep 14 '22 at 20:36
  • anyway, you can use sudo to allow running a script under the changed UID. And make a wrapper script with sudo somescript.sh "$@" if you want to hide the fact that you're using sudo from the user. (Or create a five-line C wrapper program to run set*uid() and execve()) – ilkkachu Sep 14 '22 at 20:38
  • Why was chmod's setuid bit disabled? It was an elegant solution, fit for root users who know what they are doing? – Eric Marceau Sep 14 '22 at 20:46
  • 1
    Having unprivileged processes able to start privileged processes as direct children is just asking for trouble, what with the numerous different things that are inherited from a parent process to a child. Worse, there's very likely more of those things now than there were 30 years ago, so anyone who "knows what they're doing" would need to keep a close eye. (Also, general experience has shown that a lot of people don't know what they're doing anyway, so it helps to keep the tools with sharp edges on both ends out of the kitchen.) – ilkkachu Sep 14 '22 at 20:54
  • 1
    @EricMarceau There are race conditions that make suid shell scripts insecure. In the time period between the time the command is given and when the script is executed. One explanation is here and many more are available. – doneal24 Sep 14 '22 at 21:10
0

you can do this,

echo $PASSWORD | su -c "tac <<_EOF
1
2
3
_EOF"

but as other people have responded, this isn't secure or recommended. The reason you method didn't work, is that su swalled the entire script, when you wanted stdin to be passed to the command su executes. Also, most adduser commands allow you to specify the password via the command line and not stdin, so I'm not sure you even need to do this, just use -c option for su should be enough.

toppk
  • 657