Passing root password safely in a shell script

26,564

Solution 1

Passing a password to sudo in a script is utterly pointless. Instead, add a sudo rule adding the particular command you want to run with the NOPASSWD tag. Take care that the command-specific NOPASSWD rule must come after any general rule.

saeid ALL = (ALL:ALL) ALL
saeid ALL = (root) NOPASSWD: service lightdm start

But this is probably not useful anyway. lightdm start starts a login prompt, but you only need that if you want to let other users log in graphically. You don't need it if all you want is to start a GUI session. Instead, call startx to start a GUI session from your text mode session. This does not require any extra privilege.

You may need to explicitly specify your window manager or desktop environment, as startx might not pick up the same default session type that lightdm uses.

startx -- gnome-session

Solution 2

There are some options, and one of them is to add the specific command using visudo with the NOPASSWD flag:

%wheel ALL=(ALL) NOPASSWD: /path/to/myscript

cat /path/to/myscript
#!/bin/bash
service lightdm start

Solution 3

EDIT
Just noticed in your comments you mentioning Unity, so it appears you're running Ubuntu. My original answer was geared toward SysVinit systems, but commands like telinit still exist for compatibility and will work on distros using Systemd or Upstart.

SysV way

    telinit 5

On modern Systemd systems, telinit is redirected to systemctl.

Systemd way

    systemctl isolate runlevel5.target

or

    systemctl isolate graphical.target

Original answer:
On older non-Systemd distros (RHEL/CentOS 6 and older, for example) the easiest way to switch from console mode to GUI is with the telinit command. On the RHEL/Centos distros, for example, multi-user text-based mode is run level 3 and the multi-user GUI mode is run level 5. Switching from console to GUI mode would be done like this: By default, telinit requires root privileges. To run this as a normal user without a password, you'll need a sudoers entry or set the setuid flag set on the telinit executable. The sudo method is the preferred approach as it can be restricted to just your account.

Solution 4

The classical UNIX way is making the script setuid:

$ sudo chown root gogui.sh  #not necessary if root is already the owner of the file
$ sudo chmod u+s gogui.sh

This will set a special permission bit on the file:

$ ls -l gogui.sh
  -rwsr-xr-x 1 root root [omitted] gogui.sh

(Notice the letter s instead of x in the fourth position.)

If you do this, all the times you run the script, it will be run with the privileges of the file's owner, instead of the ones of the user that runs it.

You can now simplify your script gogui.sh to contain only

/usr/sbin/service lightdm start

Notice that I have added an explicit path for the executable (that I have located by typing which service): this is necessary in setuid files, because otherwise the first program called service found in your PATH will be executed. Forgetting the explicit path would be a huge security problem, since it means that any user can tweak the PATH variable and run a program of their choice with root privileges.

If you wish, you can also restrict other users from running the files with chgrp some_group gogui.sh; chmod o-x gogui.sh, which will make the file executable only for members of some_group.

Share:
26,564

Related videos on Youtube

Saeid Yazdani
Author by

Saeid Yazdani

Updated on September 18, 2022

Comments

  • Saeid Yazdani
    Saeid Yazdani over 1 year

    I always boot up my GNU/Linux laptop in console mode. But sometimes I need to bring up the GUI mode. it always requires entering the root password. So I wrote the following script "gogui.sh" and put it in /usr/bin:

    #!/bin/bash
    echo "mypassword" | sudo service lightdm start
    

    It is a really stupid idea, as if someone read the file, can easily see my password.

    Is the an alternative to this?

    • Admin
      Admin over 8 years
      I am just usurious to see a proper/alternative way
    • Admin
      Admin over 8 years
      Why not use the NOPASSWD syntax detailed in sudoers(5) for password-free calls to that service command, or a suitable wrapper?
    • Admin
      Admin over 8 years
      Note that in constructions like these, an unprivileged user doing a process list (with e.g. ps ax) at just the right time might also see your password. It won't happen in this particular case, as echo is a bash builtin command, but the general approach is also dangerous for this reason.
  • Saeid Yazdani
    Saeid Yazdani over 8 years
    Thanks...thats way way way better :P...I use unity, should I still pass to startx the gnome-seesion argument?
  • Saeid Yazdani
    Saeid Yazdani over 8 years
    I just checked with startx, while it does bring up my desktop, but many things are missing like the unity launcher and also I got no sound, if I do the lightdm service everything works fine
  • Tobias Kienzler
    Tobias Kienzler over 8 years
    +1 for suid, tough I think some Linux versions will ignore suid for plaintext scripts for security reasons
  • tcoolspy
    tcoolspy over 8 years
    Any time you pass a variable as an argument to a shell command the shell does the expansion from variable name to value. The command that gets executed has the value as the argument and anything with access to the process list can read those arguments. Try for example var=131 ; sleep $var & ; ps waux | grep 131. You are passing it to the final command through stdin which is okay but that's only after invoking a builtin shell command with the sensitive data as a regular argument in plain sight.
  • Tobias Kienzler
    Tobias Kienzler over 8 years
    @Caleb So the $password part is the culprit? One could of course write a small Python script, but I wonder if bash can't handle this on its own...