Passing root password safely in a shell script
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
.
Related videos on Youtube
Saeid Yazdani
Updated on September 18, 2022Comments
-
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 over 8 yearsI am just usurious to see a proper/alternative way
-
Admin over 8 yearsWhy not use the
NOPASSWD
syntax detailed insudoers(5)
for password-free calls to that service command, or a suitable wrapper? -
Admin over 8 yearsNote 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, asecho
is a bash builtin command, but the general approach is also dangerous for this reason.
-
-
Saeid Yazdani over 8 yearsThanks...thats way way way better :P...I use unity, should I still pass to startx the
gnome-seesion
argument? -
Saeid Yazdani over 8 yearsI 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 over 8 years+1 for suid, tough I think some Linux versions will ignore suid for plaintext scripts for security reasons
-
tcoolspy over 8 yearsAny 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 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...