即使在 /etc/sudoers 中使用 NOPASSWD,PAM 也需要 exec/shell_exec 的密码
PAM requires password for exec/shell_exec even with NOPASSWD in /etc/sudoers
我想做什么:
允许网络服务器用户 (http) 运行 显式 iptables 命令或(最好)在将输入传递给 iptables 之前检查语法的脚本,而不需要密码。
问题:
尽管我对手头的问题进行了所有搜索,但对 visudo、sudoers.d 或 php 配置的任何更改似乎都对我尝试做的事情产生了影响。
我服务器的相关情况:
[weasel@darwyn ~]$ uname -a
Linux darwyn 5.3.7-arch1-1-ARCH #1 SMP PREEMPT Fri Oct 18 00:17:03 UTC 2019 x86_64 GNU/Linux
nginx version: nginx/1.16.1
PHP 7.3.10 (cli) (built: Sep 26 2019 13:40:03) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.10, Copyright (c) 1998-2018 Zend Technologies
Username: http
UID: 33
Gecos field:
Home directory: /srv/http
Shell: /usr/bin/nologin
No login: yes
Primary group: http
GID: 33
Hushed: no
Running processes: 3
Last logs:
09:29 sudo[648]: pam_unix(sudo:auth): auth could not identify password for [http]
09:29 sudo[649]: pam_unix(sudo:account): account http has expired (account expired)
09:29 sudo[650]: pam_unix(sudo:account): account http has expired (account expired)
我已采取的解决问题的步骤:
- 我在PHP-FPM中启用了调试。
/var/log/php-fpm.log 告诉我呼叫正在启动但需要密码:
"sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
- 我对visudo做了修改
从类似的问题中,我了解到 sudoers 文件优先考虑与用户相关的最后一个配置。所以我第一次去的地方
root ALL=(ALL) ALL
weasel ALL=(ALL) ALL
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
我将条目下移到
root ALL=(ALL) ALL
weasel ALL=(ALL) ALL
## Uncomment to allow members of group wheel to execute any command
# %wheel ALL=(ALL) ALL
## Same thing without a password
# %wheel ALL=(ALL) NOPASSWD: ALL
## Uncomment to allow members of group sudo to execute any command
# %sudo ALL=(ALL) ALL
## Uncomment to allow any user to run sudo if they know the password
## of the user they are running the command as (root by default).
# Defaults targetpw # Ask for the password of the target user
# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
##
## Relocated user http permissions for testing
##
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
## Read drop-in files from /etc/sudoers.d
## (the '#' here does not indicate a comment)
#includedir /etc/sudoers.d
- 我已经修改了 /etc/sudoers.d/90-MyOverrides.
我删除了 visudo 中的 http 条目并将其移动到 /etc/sudoers.d/90-MyOverrides.
- 我尝试了 sudoers 规则的变体。
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
http ALL=NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
http ALL=(http:http) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip *, /usr/bin/iptables *
http ALL=NOPASSWD: /usr/local/bin/blacklist_ip *, /usr/bin/iptables *
http ALL=(http:http) NOPASSWD: /usr/local/bin/blacklist_ip *, /usr/bin/iptables *
http ALL=(ALL) NOPASSWD: /usr/bin/iptables -L
http ALL=NOPASSWD: /usr/bin/iptables -L
http ALL=(http:http) NOPASSWD: /usr/bin/iptables -L
为了确保这会产生某种效果,我在自己的用户身上进行了测试
weasel ALL=(ALL) NOPASSWD: /usr/bin/iptables
我能够以用户 weasel 的身份在没有密码的情况下执行 iptables 命令,但是 php-fpm 日志仍然需要用户 http 的密码。
我还尝试使用 'sudo -S' 命令,希望密码的空值可以工作,但它也会出错。
"[sudo] password for http: "
"sudo: no password was provided"
- 我仔细检查了 php 配置中 exec/shell_exec 函数的访问权限。
我检查了 /etc/php/php.ini 和 /etc/php/php-fpm.conf 以确保 exec/shell_exec 命令未被禁用并且安全模式未激活。 /var/log/php-fpm.log 中生成的调试信息已经证明了这一点,但我想更彻底。
- 我暂时把脚本chown给用户http.
这有点多余,但只是为了排除它重要的可能性。
- 我尝试了 exec/shell_exec 调用的变体。
exec("sudo blacklist_ip 185.189.12.135");
shell_exec("sudo blacklist_ip 185.189.12.135");
return:
"sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
exec("blacklist_ip 185.189.12.135");
shell_exec("blacklist_ip 185.189.12.135");
exec("/usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
shell_exec("/usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
return:
"Fatal: can't open lock file /run/xtables.lock: Permission denied"
exec("sudo /usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
shell_exec("sudo /usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
return:
"sudo: Account expired or PAM config lacks an "account" section for sudo, contact your system administrator"
- 我注意到 PAM 配置错误。
经过一些搜索发现,根据 https://www.sudo.ws/troubleshooting.html:
Q) Sudo says 'Account expired or PAM config lacks an "account" section for sudo, contact your system administrator' and exits but I know my account has not expired.
A) Your PAM config lacks an "account" specification. On Linux this usually means you are missing a line like:
account required pam_unix.so
in /etc/pam.d/sudo.
在与此主题相关的任何其他问答中,没有人将此作为原因提及。尽管如此,为了彻底 I looked up information regarding PAM and sudo:
#%PAM-1.0
auth include system-auth
account required pam_unix.so
#account include system-auth
session include system-auth
没有区别。
我没主意了。我需要有关适当 PAM 模块的更多信息,使 PAM 可以通过 http 用户,或者我需要一些重定向以进行进一步评估。
编辑
为了简洁起见,已更新以简化信息。
编辑
添加了 /etc/php/php-fpm.d/www.conf
的内容
[www]
user = http
group = http
listen = /run/php-fpm/php-fpm.sock
listen.owner = http
listen.group = http
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
access.log = /var/log/php/$pool.access.log
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
catch_workers_output = yes
php_flag[display_errors] = on
php_admin_value[error_log] = /var/log/php/fpm-php.www.log
php_admin_flag[log_errors] = on
根据评论中的 ,事实证明,在某些时候,http 帐户的到期日期被设置为过去的某个时间,因此它在功能上永远无法用于 sudo 命令。也许这是一个决定,以防止系统在未来通过在网络服务器中使用 PHP 注入 exec/shell_exec 命令的可能性。
解决方法:
chage -E -1 http
这将用户的到期时间设置为 'never' 并使其再次可用。 sudo 设置现在按预期工作。
很抱歉没有给出你的问题的答案,但与这个问题相关,在这里值得一提。我在使用
时遇到了类似的问题
GitHub actions to run sudo command in your-file-name.yaml file
所有脚本运行成功,但是运行到最后
sudo supvervisor restart all
由于 sudo 命令需要密码和 returns 错误 sudo: no tty present and no askpass program specified
,它失败了
下面是解决这个问题的步骤:
如果您的 your-user-name
没有退出,您可以使用以下命令将其添加到 sudoer 组:
sudo adduser your-user-name sudo
现在您可以告诉系统将其添加为不需要密码的用户
sudo sh -c "echo 'your-user-name ALL=NOPASSWD: ALL' >> /etc/sudoers"
我想做什么:
允许网络服务器用户 (http) 运行 显式 iptables 命令或(最好)在将输入传递给 iptables 之前检查语法的脚本,而不需要密码。
问题:
尽管我对手头的问题进行了所有搜索,但对 visudo、sudoers.d 或 php 配置的任何更改似乎都对我尝试做的事情产生了影响。
我服务器的相关情况:
[weasel@darwyn ~]$ uname -a
Linux darwyn 5.3.7-arch1-1-ARCH #1 SMP PREEMPT Fri Oct 18 00:17:03 UTC 2019 x86_64 GNU/Linux
nginx version: nginx/1.16.1
PHP 7.3.10 (cli) (built: Sep 26 2019 13:40:03) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.10, Copyright (c) 1998-2018 Zend Technologies
Username: http
UID: 33
Gecos field:
Home directory: /srv/http
Shell: /usr/bin/nologin
No login: yes
Primary group: http
GID: 33
Hushed: no
Running processes: 3
Last logs:
09:29 sudo[648]: pam_unix(sudo:auth): auth could not identify password for [http]
09:29 sudo[649]: pam_unix(sudo:account): account http has expired (account expired)
09:29 sudo[650]: pam_unix(sudo:account): account http has expired (account expired)
我已采取的解决问题的步骤:
- 我在PHP-FPM中启用了调试。
/var/log/php-fpm.log 告诉我呼叫正在启动但需要密码:
"sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
- 我对visudo做了修改
从类似的问题中,我了解到 sudoers 文件优先考虑与用户相关的最后一个配置。所以我第一次去的地方
root ALL=(ALL) ALL
weasel ALL=(ALL) ALL
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
我将条目下移到
root ALL=(ALL) ALL
weasel ALL=(ALL) ALL
## Uncomment to allow members of group wheel to execute any command
# %wheel ALL=(ALL) ALL
## Same thing without a password
# %wheel ALL=(ALL) NOPASSWD: ALL
## Uncomment to allow members of group sudo to execute any command
# %sudo ALL=(ALL) ALL
## Uncomment to allow any user to run sudo if they know the password
## of the user they are running the command as (root by default).
# Defaults targetpw # Ask for the password of the target user
# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
##
## Relocated user http permissions for testing
##
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
## Read drop-in files from /etc/sudoers.d
## (the '#' here does not indicate a comment)
#includedir /etc/sudoers.d
- 我已经修改了 /etc/sudoers.d/90-MyOverrides.
我删除了 visudo 中的 http 条目并将其移动到 /etc/sudoers.d/90-MyOverrides.
- 我尝试了 sudoers 规则的变体。
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
http ALL=NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
http ALL=(http:http) NOPASSWD: /usr/local/bin/blacklist_ip, /usr/bin/iptables
http ALL=(ALL) NOPASSWD: /usr/local/bin/blacklist_ip *, /usr/bin/iptables *
http ALL=NOPASSWD: /usr/local/bin/blacklist_ip *, /usr/bin/iptables *
http ALL=(http:http) NOPASSWD: /usr/local/bin/blacklist_ip *, /usr/bin/iptables *
http ALL=(ALL) NOPASSWD: /usr/bin/iptables -L
http ALL=NOPASSWD: /usr/bin/iptables -L
http ALL=(http:http) NOPASSWD: /usr/bin/iptables -L
为了确保这会产生某种效果,我在自己的用户身上进行了测试
weasel ALL=(ALL) NOPASSWD: /usr/bin/iptables
我能够以用户 weasel 的身份在没有密码的情况下执行 iptables 命令,但是 php-fpm 日志仍然需要用户 http 的密码。 我还尝试使用 'sudo -S' 命令,希望密码的空值可以工作,但它也会出错。
"[sudo] password for http: "
"sudo: no password was provided"
- 我仔细检查了 php 配置中 exec/shell_exec 函数的访问权限。
我检查了 /etc/php/php.ini 和 /etc/php/php-fpm.conf 以确保 exec/shell_exec 命令未被禁用并且安全模式未激活。 /var/log/php-fpm.log 中生成的调试信息已经证明了这一点,但我想更彻底。
- 我暂时把脚本chown给用户http.
这有点多余,但只是为了排除它重要的可能性。
- 我尝试了 exec/shell_exec 调用的变体。
exec("sudo blacklist_ip 185.189.12.135");
shell_exec("sudo blacklist_ip 185.189.12.135");
return:
"sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
exec("blacklist_ip 185.189.12.135");
shell_exec("blacklist_ip 185.189.12.135");
exec("/usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
shell_exec("/usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
return:
"Fatal: can't open lock file /run/xtables.lock: Permission denied"
exec("sudo /usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
shell_exec("sudo /usr/bin/iptables -A INPUT -s 185.189.12.135 -j DROP");
return:
"sudo: Account expired or PAM config lacks an "account" section for sudo, contact your system administrator"
- 我注意到 PAM 配置错误。
经过一些搜索发现,根据 https://www.sudo.ws/troubleshooting.html:
Q) Sudo says 'Account expired or PAM config lacks an "account" section for sudo, contact your system administrator' and exits but I know my account has not expired.
A) Your PAM config lacks an "account" specification. On Linux this usually means you are missing a line like:
account required pam_unix.so
in /etc/pam.d/sudo.
在与此主题相关的任何其他问答中,没有人将此作为原因提及。尽管如此,为了彻底 I looked up information regarding PAM and sudo:
#%PAM-1.0
auth include system-auth
account required pam_unix.so
#account include system-auth
session include system-auth
没有区别。
我没主意了。我需要有关适当 PAM 模块的更多信息,使 PAM 可以通过 http 用户,或者我需要一些重定向以进行进一步评估。
编辑 为了简洁起见,已更新以简化信息。
编辑 添加了 /etc/php/php-fpm.d/www.conf
的内容[www]
user = http
group = http
listen = /run/php-fpm/php-fpm.sock
listen.owner = http
listen.group = http
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
access.log = /var/log/php/$pool.access.log
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
catch_workers_output = yes
php_flag[display_errors] = on
php_admin_value[error_log] = /var/log/php/fpm-php.www.log
php_admin_flag[log_errors] = on
根据评论中的
解决方法:
chage -E -1 http
这将用户的到期时间设置为 'never' 并使其再次可用。 sudo 设置现在按预期工作。
很抱歉没有给出你的问题的答案,但与这个问题相关,在这里值得一提。我在使用
时遇到了类似的问题GitHub actions to run sudo command in your-file-name.yaml file
所有脚本运行成功,但是运行到最后
sudo supvervisor restart all
由于 sudo 命令需要密码和 returns 错误 sudo: no tty present and no askpass program specified
下面是解决这个问题的步骤:
如果您的 your-user-name
没有退出,您可以使用以下命令将其添加到 sudoer 组:
sudo adduser your-user-name sudo
现在您可以告诉系统将其添加为不需要密码的用户
sudo sh -c "echo 'your-user-name ALL=NOPASSWD: ALL' >> /etc/sudoers"