4 easy methods to check sudo access for user in Linux

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

 

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 proper PATH variables are not found
  • If exact path is not used for the commands, for example here /bin/chmod, if I just use chmod then this will not give correct exit status. So the command must match with what is there in sudoers list
  • Dependency with timeout utility, so timeout 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.

NOTE:

This method should be used only if security is not your primary concern as your password will be publicly visible. You may choose to convert your script to binary format so no once can read the content of your script.

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.

Leave a Comment

Please use shortcodes <pre class=comments>your code</pre> for syntax highlighting when adding code.