Sudo issue

Ubuntu Support Template

Ubuntu Version:
26.04 LTS

Desktop Environment (if applicable):
none

Problem Description:
I have been running my own Apache PHP application on Ubuntu Server 20.04 LTS and am now trying to get it up and running on a new server running Ubuntu Server 26.04 LTS. I am currently struggling with an issue involving sudo.

I have already switched from sudo-rs to sudo.ws to ensure consistent conditions. Unfortunately, it does not work with either option.

The PHP application calls iptables:

exec('sudo /usr/sbin/iptables -4 -L INPUT -n -v --line-numbers', $out);

To make this possible, I have defined the following in /etc/sudoers.d/nopasswd:

Defaults logfile="/var/log/sudo.log"

User_Alias      U_IPTABLES = www-data
Cmnd_Alias      C_IPTABLES = /usr/sbin/iptables, /usr/sbin/ip6tables
U_IPTABLES      ALL=(root) NOPASSWD: C_IPTABLES

It works perfectly on the old server; the web server can call iptables and I can also see an entry in the log file /var/log/sudo.log:

May 12 10:54:03 : www-data : TTY=unknown ; PWD=/srv/www/admin ; USER=root ;
COMMAND=/usr/sbin/iptables -4 -L INPUT -n -v --line-numbers

However, on the new server, this fails even though the configuration is identical:

There is no entry in /var/log/sudo.log

In /var/log/apache2/error.log, I find:

sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required

Unfortunately, I’m at a loss now. It looks to me as though sudo, when called by www-data, isn’t taking the sudoers configuration into account. However, I can’t pinpoint the exact cause at the moment. My tests all yield the same result:

new server:

root@speedtest:/# sudo -l -U www-data
Matching Defaults entries for www-data on speedtest:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, logfile=/var/log/sudo.log

User www-data may run the following commands on speedtest:
    (root) NOPASSWD: /usr/sbin/iptables, /usr/sbin/ip6tables
root@speedtest:/#

old server:

root@speedtest:/# sudo -l -U www-data
Matching Defaults entries for www-data on speedtest:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, logfile=/var/log/sudo.log

User www-data may run the following commands on speedtest:
    (root) NOPASSWD: /usr/sbin/iptables, /usr/sbin/ip6tables
root@speedtest:/#

Unfortunately, it still doesn’t work.

When I switch to root via `sudo -i` from my personal user account, this is correctly logged, so the configuration is generally applied as well.

May 12 11:35:15 : jbr : TTY=pts/0 ; PWD=/root ; USER=root ; COMMAND=/bin/bash

What else can I do? How can I narrow down the problem? I’m slowly running out of ideas, unfortunately.

I’ve enabled

Debug sudo /var/log/sudo_debug all@debug
Debug sudoers.so /var/log/sudoers_debug all@debug

in /etc/sudo.conf now.

So the configuration files are indeed being read, but unfortunately I can’t tell anything more from the logs. They look very different between the two servers.

Unfortunately I’m not allowed to upload them here.

This could be related to the switch to sudo-rs.

You can, sort of, by using “code” blocks (</>) and pasting their content. As it happens, I’ve written a small shell script that may help with that; just run cmd2bb cat /path/to/file and then paste what it puts in the clipboard directly into the editor.

1 Like

Can you try, shell_exec("sh sudo /usr/sbin/iptables -4 ...");

added sh

New error message in /var/log/apache2/error.log:

sh: 0: cannot open sudo: No such file

Thx, too big…

Old server log:

https://nas.jens-bretschneider.de:50005/sharing/DBecLoT1o

New Server log:

https://nas.jens-bretschneider.de:50005/sharing/FizzPhPUL

Yes, I think so too. Unfortunately, it doesn’t work with either sudo-rs or sudo.ws now :frowning:

On second look, is Apache running in some kind of sandbox/chroot? That could explain, why it ignores sudoers; because the file “does not exist” in that environment.

systemctl cat apache\*

Old Server:

# /lib/systemd/system/apache2.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=https://httpd.apache.org/docs/2.4/

[Service]
Type=forking
Environment=APACHE_STARTED_BY_SYSTEMD=true
ExecStart=/usr/sbin/apachectl start
ExecStop=/usr/sbin/apachectl stop
ExecReload=/usr/sbin/apachectl graceful
PrivateTmp=true
Restart=on-abort

[Install]
WantedBy=multi-user.target
root@speedtest:~#

New Server:

# /usr/lib/systemd/system/apache2.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=https://httpd.apache.org/docs/2.4/

[Service]
Type=notify
Environment=APACHE_STARTED_BY_SYSTEMD=true
ExecStart=/usr/sbin/apachectl start
ExecStop=/usr/sbin/apachectl graceful-stop
ExecReload=/usr/sbin/apachectl graceful
# Send SIGWINCH for graceful stop
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true
Restart=on-abnormal
OOMPolicy=continue
RemoveIPC=yes

DevicePolicy=closed
KeyringMode=private
LockPersonality=yes
MemoryDenyWriteExecute=yes
PrivateDevices=yes
ProtectClock=yes
ProtectControlGroups=yes
ProtectHome=read-only
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectSystem=full
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
ProtectProc=invisible
ProcSubset=pid

ReadWritePaths=/var/log/apache2
ReadWritePaths=/var/cache/apache2/mod_cache_disk

InaccessiblePaths=/boot
InaccessiblePaths=/root
InaccessiblePaths=-/etc/sudoers
InaccessiblePaths=-/etc/sudoers.d
InaccessiblePaths=-/etc/ssh
InaccessiblePaths=-/etc/apt
InaccessiblePaths=-/etc/.git
InaccessiblePaths=-/etc/.svn

[Install]
WantedBy=multi-user.target
root@speedtest:~#

Good catch! Will have a look at the “InaccessiblePaths”-Lines.

1 Like

Thanks a lot!

Commenting out

#InaccessiblePaths=-/etc/sudoers
#InaccessiblePaths=-/etc/sudoers.d

did the trick! :+1::+1:

1 Like

You shouldn’t edit /usr/lib/systemd/system/apache2.service, though, because that file is owned by the apache2 package and will be happily overwritten by the package manager on the next (security) upgrade. The proper way of doing things like that is:

sudo systemctl edit apache2.service.
### Editing /etc/systemd/system/apache2.service.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file

[Service]
# clear the list
InaccessiblePaths=

# only re-activate what you need
InaccessiblePaths=/boot
InaccessiblePaths=/root

# comment these out or just delete them
# InaccessiblePaths=-/etc/sudoers
# InaccessiblePaths=-/etc/sudoers.d

InaccessiblePaths=-/etc/ssh
InaccessiblePaths=-/etc/apt
InaccessiblePaths=-/etc/.git
InaccessiblePaths=-/etc/.svn

### Edits below this comment will be discarded

See man 5 systemd.unit for details on the override mechanism.

You should also think long and hard about what these directives mean for security; your www-data user, or an attacker capturing it, rather, is now free to edit your firewall rules at will.

2 Likes

Thanks. Yes, I’m aware of that risk.

OK, thanks again, I’ll change that. :+1:

Great, and then please consider selecting my reply as the solution, because yours may lead others with similar issues down the wrong path.

I’ve used

systemctl edit apache2.service --full 

to edit the file and commented out the

#InaccessiblePaths=-/etc/sudoers
#InaccessiblePaths=-/etc/sudoers.d

lines in there.

Thanks!

Why? That needlessly overrides the Ubuntu packaged version completely. Any additional future security additions will be lost to you that way.

It’s not wrong, per se, but too heavy a hammer IMO, because you’ve effectively made yourself the maintainer of that service unit. Systemd overrides are really great for only overriding what’s absolutely necessary.

sudo systemctl edit ... also shows the original unit file in the comments below ### Edits below this comment will be discarded so you don’t have to type all the InaccessiblePaths= lines or whatever you want to override; just copy and uncomment what you want to keep, if that’s why you did the --full edit – and that’s only necessary because InaccessiblePaths= is a cumulative directive which needs to be reset in this case. I just didn’t bother to copy all that stuff for brevity. Systemd tooling is absolutely great for this kind of stuff.

This topic was automatically closed 18 hours after the last reply. New replies are no longer allowed.