Table of Contents
How to check if a normal user has sudo access? Is it possible to know if a user has sudo access using a script? The script prompts for user password if I attempt to use or verify sudo privilege, can it be done without password prompt?
The other day I was writing a script which demanded a normal user to use sudo access to perform certain operation. But then I realised a normal user does not has privilege to read sudoers
file as it is only readable by root user by default
# ls -l /etc/sudoers
-r--r----- 1 root root 4367 Jul 11 11:14 /etc/sudoers
So this means we cannot use grep by a normal user as it would give "Permission denied
"
[deepak@client root]$ grep deepak /etc/sudoers
grep: /etc/sudoers: Permission denied
[root@client ~]# id deepak uid=1001(deepak) gid=1001(deepak) groups=1001(deepak),10(wheel)
So to treat him as a normal user we must remove this user from wheel group.
Check sudo access as normal user
There are couple of methods you can use to check sudo access inside a script or even without a script. In this tutorial I will share the ones which I know, you can add any more to this list using the comment section. We will analyse the pros and cons of individual method so you can select the most suitable one based on your requirement.
Method 1: Using sudo -l or --list
As per the man page, sudo can be used with -l
or --list
to get the list of allowed and forbidden commands for any particular user.
The syntax would be:
sudo -l [-AknS] [-a type] [-g group] [-h host] [-p prompt] [-U user] [-u user] [command]
If we use sudo --list
without any arguments, then it will print the list of allowed and forbidden commands for the user who is executing the sudo command
# sudo --list
<Output trimmed>
User root may run the following commands on client:
(ALL) ALL
Similarly to verify for normal user, for example I have a user deepak
# sudo -l -U deepak <Output trimmed> User deepak may run the following commands on client: (ALL) NOPASSWD: /bin/chmod, !/usr/bin/passwd
So user deepak
is allowed to use chmod
and is forbidden to use passwd
with sudo
Or you can run this as a normal user:
[deepak@client ~]$ sudo -l <Output trimmed> User deepak may run the following commands on client: (ALL) NOPASSWD: /bin/chmod, !/usr/bin/passwd
To get more detailed output of the commands allowed/dis-allowed by user, you can add -l
multiple times
[amit@client ~]$ sudo -ll Sudoers entry: RunAsUsers: ALL Options: !authenticate Commands: /bin/chown
You can also search for the exact command to make sure the provided command is allowed or not for the user
[deepak@client ~]$ sudo --list chmod /bin/chmod
So we know the user has sudo
access to use chmod
command, similarly let's try to check for a different command:
[deepak@client ~]$ sudo --list passwd
[deepak@client ~]$ echo $?
1
Here the exit status is non-zero so we know that user deepak
has no sudo
access to use passwd
command
If the user deepak
does not has sudo privilege, you will end up with a password prompt. Once you prove the password you would get something like below:
[deepak@client ~]$ sudo -l
[sudo] password for deepak:
Sorry, user deepak may not run sudo on client.
The downside of using sudo --list
is that the very first time when you execute this, it will prompt for password.
[deepak@client ~]$ sudo -l -U deepak
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for deepak:
Although you can use a workaround hack (if possible), execute sudo --list -U <user>
as root
user for the first session which will not prompt for password as the first execution is using super user and next time onward now you can use --list
with sudo even as normal user to check sudo access without any password prompt
Pros
- Get the complete list of individual commands allowed/forbidden
- Get detailed output of commands allowed/forbidden in
sudoers
list - Easy to use and does not depend on any other commands for execution
Cons
- Not a ideal solution for scripting as we can expect a password prompt if user has no sudo access
Method 2: Using sudo -v or --validate
sudo -v
or sudo --validate
will update the user's cached credentials, authenticating the user if necessary. This is another simple approach to check sudo access but this may not give you too much detail as seen with sudo --list
If the user has sudo access then this command will return zero exit status
[amit@client ~]$ sudo --validate
[amit@client ~]$ echo $?
0
So we know user amit
has sudo access but he has no idea which all command are allowed/forbidden for him.
If the user has no sudo access i.e. there is no entry for a user in /etc/sudoers
then this command will return "Sorry, user XXX may not run sudo on client.
"
[deepak@client ~]$ sudo --validate
Sorry, user deepak may not run sudo on client.
Pros
- Ease of use
- Can be useful if the requirement is only to check presence of user in
/etc/sudoers
- Can be used with scripting based on requirement
Cons
- You get no information about the list of commands allowed/forbidden for the individual user
Method 3: Use sudo with timeout
If you just attempt to use sudo for any command as normal user, the downside is the password prompt (assuming user has no sudo access). If the user has sudo access for the provided command with NOPASSWD
argument then there is no problem at all. But in scripts we have to handle both positive and negative scenarios.
So we must also handle a possible scenario that the script may get stuck waiting for user password prompt with sudo. So how do we handle this? timeout to the reuse
In bash we have timeout utility which is used to kill stuck processes and moreover timeout also can be used to kill itself if for some reason timeout also gets stuck.
So assuming the user deepak
was expecting, he has sudo privilege for using chmod
command and he tries to use chmod
from within the script
[deepak@client ~]$ sudo chmod --help [sudo] password for deepak:
The script halts waiting for user input. So we add timeout
with this command, to monitor the time of execution I have also added "time
"
[deepak@client ~]$ time timeout 2 sudo chmod --help [sudo] password for deepak: real 0m2.011s user 0m0.015s sys 0m0.009s [deepak@client ~]$ echo $? 124
So as expected after waiting for 2 seconds, the sudo
prompt was killed. If the command times out, and --preserve-status
is not set, then exit with status 124. You can use --preserve-status
to exit with your command's exit status
Example Script
So we can use this within our script and send the output to /dev/null
or to any of your log file to avoid any unwanted messages on the console. I had to use -k
with timeout
as I observed that timeout was stuck infinitely within the shell script.
#!/bin/bash timeout -k 2 2 bash -c "sudo chmod --help" >&/dev/null 2>&1 if [ $? -eq 0 ];then echo "yay, user `id -Gn` has sudo access" else echo "sorry, user `id -Gn` has no sudo access" fi
If we execute this script, the output
[deepak@client ~]$ /tmp/script.sh
/tmp/script.sh: line 3: 2299 Killed timeout -k 2 2 bash -c "sudo chmod --help" &> /dev/null 2>&1
sorry, user deepak has no sudo access
It does the work but clearly the output is not good, so let's fix this by sending output to /dev/null
#!/bin/bash `timeout -k 2 2 bash -c "sudo /bin/chmod --help" >&/dev/null 2>&1` >/dev/null 2>&1 if [ $? -eq 0 ];then echo "yay, user `id -Gn` has sudo access" else echo "sorry, user `id -Gn` has no sudo access" fi
Now we execute this script:
[deepak@client ~]$ /tmp/script.sh
sorry, user deepak has no sudo access
So now we can check the sudo access with cleaner output on the console. You can also assign a variable based on the execution and then use the variable in your script.
#!/bin/bash has_sudo_access="" `timeout -k 2 2 bash -c "sudo /bin/chmod --help" >&/dev/null 2>&1` >/dev/null 2>&1 if [ $? -eq 0 ];then has_sudo_access="YES" else has_sudo_access="NO" fi echo "Does user `id -Gn` has sudo access?: $has_sudo_access"
Now assuming I have added sudo access for user deepak
for /bin/chmod
, let's execute this script:
[deepak@client ~]$ /tmp/script.sh
Does user deepak has sudo access?: YES
Pros
- Can be used in a script to check sudo access for normal user in Linux
- Can return user defined exit status or variables based on the condition match
Cons
- The solution is not very robust, as if a switch user is done without using hyphen (
-
), it is possible this command may fail because properPATH
variables are not found - If exact path is not used for the commands, for example here
/bin/chmod
, if I just usechmod
then this will not give correct exit status. So the command must match with what is there insudoers
list - Dependency with
timeout
utility, sotimeout
also must be installed on the server.
Method 4: Using sudo with -S or --stdin
You can use sudo
with --stdin
or -S
to write the prompt to the standard error and read the password from the standard input instead of using the terminal device. The password must be followed by a newline character.
Example Script
For example, in this sample script I am providing password for my user "deepak
" to check the sudo access
#!/bin/bash has_sudo_access="" printf "mypassword\n" | sudo -S /bin/chmod --help >/dev/null 2>&1 if [ $? -eq 0 ];then has_sudo_access="YES" else has_sudo_access="NO" fi echo "Does user `id -Gn` has sudo access?: $has_sudo_access"
If the user has sudo
access to execute /bin/chmod
, the output would be:
Does user deepak has sudo access?: YES
Or else you will get:
Does user deepak has sudo access?: NO
Pros
- Easy solution to check
sudo
access for individual commands - Can be easily used in scripts
Cons
- Not good for security as you have to provide your user's password in plain text format within the script. Although you can use third part tools to encrypt your script or convert it into binary format so no one can read your script content.
Conclusion
In this tutorial we learned about different possible solutions to check sudo
access using normal user in Linux. You may choose the most appropriate solution based on your requirement. Please note you may have to use "sudo -K
" or "sudo --remove-timestamp"
to remove the user's cached credentials entirely from the user session. As once the user's sudo
is modified, it is possible the user will still have the access based on earlier permission unless you refresh the cache.
Lastly I hope the steps from this tutorial to check Linux sudo access as normal user was helpful. So, let me know your suggestions and feedback using the comment section.
For interactive use: the command will show everything what use need:
For non-interactive (and scripting):