Skip to main content
Commonmark migration
Source Link

##Don't do this.##

Don't do this.

##But if you absolutely must, here's how.##

But if you absolutely must, here's how.

##Don't do this.##

##But if you absolutely must, here's how.##

Don't do this.

But if you absolutely must, here's how.

Source Link
telcoM
  • 114.3k
  • 5
  • 163
  • 311

##Don't do this.##

You're giving the sudo-user the ability to run any commands as any user. That includes the ability to modify /etc/sudoers using any tool that does not require executing sub-processes. You may be thinking that excludes visudo, but strictly speaking, you don't need visudo to edit /etc/sudoers.

Like, for example:

sudo-user$ sudo sed --in-place -e '/^sudo-user/s/NOEXEC://' /etc/sudoers 

...and the user has just removed the NOEXEC: restriction.

A restriction that the user can remove at will is not a true restriction.


Also, NOEXEC: may cause problems. It does not just prevent shell escapes: it prevents the program executed with sudo from directly starting any other programs. This can have a lot of consequences.

For example, if your sudo-user stops and later restarts the cron daemon (e.g. to stop scheduled jobs for the duration of some maintenance), the restarted cron daemon will be unable to actually execute any scheduled jobs because of the NOEXEC: restriction.

NOEXEC: exists so that the sysadmin can apply it to carefully selected programs that are found to be able to perform their task without exec()ing any sub-processes. Applying it blindly to everything is going to cause problems.


##But if you absolutely must, here's how.##

From the sudoers(5) man page:

User specification User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \ (':' Host_List '=' Cmnd_Spec_List)* Cmnd_Spec_List ::= Cmnd_Spec | Cmnd_Spec ',' Cmnd_Spec_List Cmnd_Spec ::= Runas_Spec? SELinux_Spec? Tag_Spec* Cmnd Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')' SELinux_Spec ::= ('ROLE=role' | 'TYPE=type') Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' | 'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' | 'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'PASSWD:' | 'NOPASSWD:' | 'SETENV:' | 'NOSETENV:') 

This is a detailed description on how to construct a user specification line for the sudoers file. It may be a little tedious to read, but it does hold the information you need.

Let's work it out using your example line:

sudo-user ALL=(ALL) NOEXEC: NOPASSWD: ALL 

The entire line is known as the user specification, or User_Spec.

It breaks down as follows:

  • User_List has just one user in your example: sudo-user
  • Host_List has just one entry, ALL
  • Cmnd_Spec_List in your example is (ALL) NOEXEC: NOPASSWD: ALL
  • there are no further : Host_List = Cmnd_Spec_List units on this line (the asterisk after parentheses suggests there might be zero or more additional units like this.)

Your Cmnd_Spec_List has no commas, so it has just one Cmnd_Spec.

Cmnd_Spec breaks down into:

  • optional Runas_Spec: in your case, (ALL)
  • optional SELinux_Spec, which does not exist in your example
  • zero or more Tag_Specs, which is the part you want to know about
  • Cmnd, the command, which is ALL in your case.

And a single Tag_Spec is just one of the listed keywords with a colon at the end, with no comma, space or other delimiter explicitly listed. The Cmnd_Spec ::= line tells us exactly where to put spaces on that line. Since there is no instruction to put spaces or any other delimiters between tags, don't do that.

So, just put the tags one after the other, like this:

sudo-user ALL=(ALL) NOEXEC:NOPASSWD: ALL