37

As a privileged user I am trying to set the sudo password to another then the one used at login.

I have done some research but have not found an answer. Does sudo support that kind of configuration?

If you ever lose your password, you lose everything. Someone could log in and promote himself to root with the same password.

sudo has an option to ask for root password instead of invoked user password, (rootpw), but sharing root password is definitely not an option, that is why we set up sudo.

I did config 2FA in the past, it worked great, but also defeats the automation purpose. For example if you want to execute a privileged command across a dozen of servers with an expect script, adding 2FA doesn't allow you to do that.

The closest solution I have found is to only allow SSH private key and setup pass-phrase with a key which differs from the sudo (login) password. Still, it is not comfy, because in an emergency situation you can't login with a PC where it doesn't have that key.

Braiam
  • 35,991
Shâu Shắc
  • 948
  • 1
  • 10
  • 12
  • 2
    Why do you need this exactly? Maybe the problem is somewhere else. Wouldn't be better to have dual-factor authentication for logging into system with a privileged account and then have 'NOPASSWD', so that sudo does not ask for password? Then you should have of course a separate emergency local account with strong password to be able to login when network is down (no ssh access). – jirib Oct 11 '13 at 13:33

8 Answers8

36

If you want to ask for the root password, as opposed to the user's password, there are options that you can put in /etc/sudoers. rootpw in particular will make it ask for the root password. There is runaspw and targetpw as well; see the sudoers(5) manpage for details.

Other than that, sudo does its authentication (like everything else) through PAM. PAM supports per-application configuration. Sudo's config is in (at least on my Debian system) /etc/pam.d/sudo, and looks like this:

$ cat sudo 
#%PAM-1.0

@include common-auth
@include common-account
@include common-session-noninteractive

In other words, by default, it authenticates like everything else on the system. You can change that @include common-auth line, and have PAM (and thus sudo) use an alternate password source. The non-commented-out lines in common-auth look something like (by default, this will be different if you're using e.g., LDAP):

auth    [success=1 default=ignore]      pam_unix.so nullok_secure
auth    requisite                       pam_deny.so
auth    required                        pam_permit.so

You could use e.g., pam_userdb.so instead of pam_unix.so, and store your alternate passwords in a Berkeley DB database.

example

I created the directory /var/local/sudopass, owner/group root:shadow, mode 2750. Inside it, I went ahead and created a password database file using db5.1_load (which is the version of Berkeley DB in use on Debian Wheezy):

# umask 0027
# db5.1_load -h /var/local/sudopass -t hash -T passwd.db
anthony
WMaEFvCFEFplI
^D

That hash was generated with mkpasswd -m des, using the password "password". Very highly secure! (Unfortunately, pam_userdb seems to not support anything better than the ancient crypt(3) hashing).

Now, edit /etc/pam.d/sudo and remove the @include common-auth line, and instead put this in place:

auth    [success=1 default=ignore]      pam_userdb.so crypt=crypt db=/var/local/sudopass/passwd
auth    requisite                       pam_deny.so
auth    required                        pam_permit.so

Note that pam_userdb adds a .db extension to the passed database, so you must leave the .db off.

According to dannysauer in a comment, you may need to make the same edit to /etc/pam.d/sudo-i as well.

Now, to sudo, I must use password instead of my real login password:

anthony@sudotest:~$ sudo -K
anthony@sudotest:~$ sudo echo -e '\nit worked'
[sudo] password for anthony: passwordRETURN

it worked
derobert
  • 109,670
  • Make sure to also configure "sudo-i", which newer versions of sudo often use for "sudo -i" (if the vendor hasn't changed something). – dannysauer Oct 11 '13 at 21:20
  • Can you elaborate on the PAM config pls? – Shâu Shắc Oct 14 '13 at 08:58
  • @ShâuShắc I've added an example, including PAM config changes. – derobert Oct 14 '13 at 17:35
  • Thanks. But I dont find db51-utils anywhere in Redhat/centos or sources, is it only available in Debian variants? – Shâu Shắc Oct 15 '13 at 05:01
  • @ShâuShắc I believe RHEL, Fedora, and CentOS call it libdb-utils. The command name may be a little different, too (maybe it won't have a version, or will be a different version—but it'll match db.*_load) – derobert Oct 15 '13 at 05:22
  • My system is redhat. This is original file:

    $ cat /etc/pam.d/sudo #%PAM-1.0 auth include system-auth account include system-auth password include system-auth session optional pam_keyinit.so revoke session required pam_limits.so

    – Shâu Shắc Oct 15 '13 at 08:10
  • And after I made the edit:

    $ cat /etc/pam.d/sudo #%PAM-1.0

    auth include system-auth

    auth [success=1 default=ignore] pam_userdb.so crypt=crypt db=/usr/local/etc/sudopass/passwd auth requisite pam_deny.so auth required pam_permit.so

    account include system-auth password include system-auth

    session optional pam_keyinit.so revoke session required pam_limits.so

    – Shâu Shắc Oct 15 '13 at 08:12
  • I have tried the new password, but it keeps telling me the password is incorrect – Shâu Shắc Oct 15 '13 at 08:13
  • @ShâuShắc it looks like you didn't remove the include line. So it's trying to match both passwords. RedHat appears to use a slightly different PAM setup than Debian. – derobert Oct 15 '13 at 14:44
  • Hi derobert,if you check it closely, I commented the line: # auth include system-auth. Also sorry for the very confusing format, it looks like to me comment on stackexchange doesnt accept formatting – Shâu Shắc Oct 15 '13 at 15:15
  • @ShâuShắc there is a debug option, add that to the pam_userdb line, and check your authentication logs... Maybe that'll explain what is going wrong. – derobert Oct 15 '13 at 15:36
  • @ShâuShắc I created a CentOS 6.4 VM and tested this on it, it works for me... Did you change the username in the password file to your username (instead of "anthony")? – derobert Oct 15 '13 at 17:28
  • Of course I changed it to my username. Later, I actually configured it successfully, with the help of google. Its slightly different from yours, though. I will share it tomorrow because Im on mobile atm. Now I need to work out a way that other users running sudo with normal authen method, and this configuration is applicable to me only, because Im the only person in this organisation really care about tight security. If it can be applied per user or group, that'd be perfect solution – Shâu Shắc Oct 15 '13 at 18:19
  • Some distributions (Arch, the Red Hat distros) do not provide the mkpasswd utility mentioned here. Is there an alternative? – Vladimir Panteleev Feb 29 '16 at 08:34
  • @VladimirPanteleev seems like that'd make a good question for the site. Search first to make sure it hasn't already been asked. – derobert Feb 29 '16 at 08:40
  • 4
    The "the ancient crypt(3) hashing" on modern versions of glibc has support for sha-512, eg. mkpasswd -m sha-512. pam_userdb.so can handle these just fine. – Andrew Domaszek Jul 19 '17 at 17:37
  • This answer is extremely useful; thanks for sharing this. – alecov Jun 22 '18 at 18:21
  • I'm having a similar problem (on Ubuntu 18.04) with authentication failure. Is this still active enough to get help? – RhythmInk Oct 04 '18 at 19:43
  • @RhythmInk probably you should ask your own question, feel free to link to this one. That way you have the full question to provide details (as opposed to the limited length & formatting of comments) and also it'll be presented to a much wider audience. https://unix.stackexchange.com/questions/ask – derobert Oct 04 '18 at 19:49
6

For Redhat/Centos, the requirement can be achieved with following steps:

Create custom user and pass:

# db_load -t hash -T /usr/local/etc/passwd.db
user
pass
^d

Edit the sudo pam.d file so that it looks like:

$ cat /etc/pam.d/sudo

auth            required        pam_userdb.so db=/usr/local/etc/passwd
account         required        pam_userdb.so db=/usr/local/etc/passwd
password        include         system-auth

session         optional        pam_keyinit.so revoke
session         required        pam_limits.so

Im still looking for the way to config, so that only a certain user/group must be authen by this custom method, others still can be authen by the normal system-auth method. Can anyone give me some advises?

Shâu Shắc
  • 948
  • 1
  • 10
  • 12
  • You should be able to do this with the full action syntax in PAM. e.g., [user_unknown=ignore,success=ok,default=bad]... but you'll have to play with that (and read the PAM docs) to get it right – derobert Oct 18 '13 at 21:06
  • This could also be accomplished using pam_succeed_if to skip one module if the user is in one of a list of groups, or to skip two modules if not. – dannysauer Jun 17 '15 at 19:15
  • So, something generally like this: /// auth [success=ignore default=1] pam_succeed_if.so user in danny:frank /// auth sufficient danny_frank_module.so /// auth sufficient not_danny_frank.so – dannysauer Jun 17 '15 at 19:15
3

I don't think sudo supports such a setup. The purpose of the sudo password prompt is to ensure that the person issuing the sudo command is the same person that is logged in, and the easiest way to do that is to ask for the currently logged in user to re-authenticate themselves.

In other words, the purpose of the sudo password prompt is not to establish authority, it is to establish identity. Based on the established identity and the sudo configuration, a decision can be made whether the user in question has the necessary authority or access rights.

user
  • 28,901
  • 4
    Sudo doesn't (except in the case that you want to ask the root password, or a particular user, or the target user's password), but PAM does. And sudo uses PAM. – derobert Oct 11 '13 at 15:56
1

My solution isn't any different then the excellently proposed ones.

However, I do include ALL commands for all steps taking out any guesswork or further reading.

I'm not against reading, just there are time when a pure reference is required. I hope others would find this useful.

I've tested this on Ubnutu 22.04.

I've installed db-util and whois (for mkpasswd):

sudo apt --yes install db_util whois
# Run this from your user
# Plaintext password
# Flavor is either sudo or sudo-i, recommended to test only on one first
PASSWD='password'; FLAVOR="sudo-i"

Uncomment next line to erase existing db and start from scratch:

sudo bash -c "[[ ! -r /var/local/sudopass/passwd.db ]] || rm /var/local/sudopass/passwd.db;"

[[ -d /var/local/sudopass ]]
|| sudo install --owner root --group shadow --mod 2750 --directory
&& sudo sed -E 's|^@include[ \t]+common-auth$|# @include\tcommon-auth\n\nauth\t[success=1 default=ignore]\tpam_userdb.so crypt=crypt db=/var/local/sudopass/passwd\nauth\trequisite\t\t\tpam_deny.so\nauth\trequired\t\t\tpam_permit.so\n|' -i "/etc/pam.d/$FLAVOR"
&& printf "%s\n" "$USER" "$( mkpasswd -m sha-512 "$PASSWD" )"
| sudo bash -c " umask 0027; db_load -Tt hash -h /var/local/sudopass passwd.db " && printf "\n\n"
&& sudo -k ${FLAVOR#sudo} || sudo journalctl -xe

unset PASSWD

Here is what's going on:

  • PASSWD='password'; FLAVOR="sudo-i":
    Assignment of plaintext to PASSWD
    Choice of FLAVOR (sudo, sudo-i) - I recommend you start with sudo-i so that sudo continues to behave the same until you've made sure everything is working correctly.
  • [[ ! -r ....:
    If not DB readbale (for sudo), continue, otherwise, remove the file.
    It is written this way, so that it 'always succeeds'
  • [[ -d ...:
    In case the directory doesn't exists, create it with the proper permissions.
  • sudo sed ... -i ...: For the specific FLAVOR, replace the default entry with the pam_user.db one.
  • printf "%s\n" "$USER" "$( mkpasswd -m sha-512 "$PASSWD" )":
    The mkpasswd generates a password and hashes it with SHA-512. Then the current user's name and the hashed password are passed to:
    | sudo ... db_load ... - which then loads the values into the DB.
  • sudo -k ${FLAVOR#sudo}:
    Testing the sudo prompt. The notation around FLAVOR strips sudo from the begning, which means that the correct FLAVOR of the sudo command will be called for testing.
    -k invalidates any cached password, forcing to enter the password.
  • || sudo journalctl -xe:
    If something failed, display the latest system's logs.
  • unset PASSWD - This shouldn't remain in the open.
Lockszmith
  • 670
  • 5
  • 14
1

Your concern is that your account password can be disclosed. The solution is to not use the login password in a way that it can be disclosed. With ssh, the password is encrypted on the wire, so it's fine. People turn off password auth with ssh to prevent password guessing attacks, not to protect password confidentiality. If you're using the same account password for anything else, make sure that you're using a secure, encrypted channel to provide the password. If you're worried about a keylogger or whatever, stop using untrusted machines to log in.

If someone can get your ssh password, they can probably also get the alternate sudo password, so you're better off investing time into making your connections more secure than spending time just making things more complicated just for the illusion of more security.

dannysauer
  • 1,269
1

I don’t have immediate access to a system where I can test this and work out the details, but I have an idea:

  • (Assume your normal login account is shau.)
  • Create a second account: shau2.  (I’m not sure whether you want it to have the same UID as shau.)
  • Configure shau2 to have sudo privileges with NOPASSWD.
  • Set up an alias or a shell script to do su shau2 -c sudo "$@".  This should ask for shau2’s password.  If that is entered correctly, it will run sudo as shau2 (which should not ask for a password).
  • Remove shau’s sudo privileges.

Unfortunately, you would have to repeat this for every user who has sudo privileges.

0

Thank you @Shâu Shắc for the answer! That solution also works for LinuxMint 17.1 Cinnamon 32bit (I've only installed db-util package in order to run db_load).

But I am very confused with the resultant passwd.db file. I've did the same as in your answer (but used david and jones, they look more eye-catching):

# db_load -t hash -T /usr/local/etc/passwd.db
david
jones
^d

But entered credentials are stored inside hash file as plain text:

# grep 'jones.*david'  /usr/local/etc/passwd.db
Binary file /usr/local/etc/passwd.db matches

You can also see david and jones via mcedit:

enter image description here

Yes, it's possible to restrict permissions of /usr/local/etc/passwd.db. But anyway, username and password stored as plain text are bad.


Even with separate sudo password there are some potential security holes (by default distro setup). Thus, separate password is not applicable for su (so it is possible to start root session using su and login password). Also separate password is not respected by Policy Kit (it is possible to start Synaptic using synaptic-pkexec and login password. Then delete packages...). These issues can be eliminated by additional tuning of configuration files.

In general seems that secure separate sudo password can be achieved only with aid of custom PAM module (perhaps, such module will compare password and SHA-512 hash read from file) or SELinux functionality.

PS: sorry, it should be a comment. But it goes as answer because of text format. Thanks for understanding.

flaz14
  • 101
  • If I understood correctly, you must hash your password manually using mkpasswd before storing it in the database. – leogama Apr 15 '23 at 19:37
-1

You just have to install the application using the sudo user, by running the command apt-get install.

The apt-get install command will by default install the application globally.

For example:

sudo su - <sudo_username>
echo "your_sudo_password" | sudo -S apt-get install <package> -y