在Linux上以特权用户身份通过PHP/Perl脚本运行命令

在Linux上以特权用户身份通过PHP/Perl脚本运行命令,php,linux,perl,cgi,apache,Php,Linux,Perl,Cgi,Apache,背景:我正在为一家公司编写一个脚本,允许用户通过web界面创建FTP帐户。在后台,脚本必须运行一系列命令: 将用户添加到系统(useradd) 打开和编辑各种文件 通过sendmail向用户发送邮件 还有其他一些事情 我基本上是在寻找最安全的方法。我听说过setuid方法,sudo方法,当然还有作为特权用户运行httpd。当然,在执行任何命令之前,都会对输入的数据进行健全性检查(即用户名中仅包含字母数字字符) 流行的脚本(例如webmin)使用的方法是什么,因为它必须相当安全?我会设置一个队

背景:我正在为一家公司编写一个脚本,允许用户通过web界面创建FTP帐户。在后台,脚本必须运行一系列命令:

  • 将用户添加到系统(useradd)
  • 打开和编辑各种文件
  • 通过sendmail向用户发送邮件
还有其他一些事情

我基本上是在寻找最安全的方法。我听说过setuid方法,sudo方法,当然还有作为特权用户运行httpd。当然,在执行任何命令之前,都会对输入的数据进行健全性检查(即用户名中仅包含字母数字字符)


流行的脚本(例如webmin)使用的方法是什么,因为它必须相当安全?

我会设置一个队列,绑定到web的脚本可以写入该队列

然后我将从该队列中读取一些特权进程,并采取适当的操作。您可以通过cron作业驱动一个命令行脚本,或者用PHP编写一个小守护进程来检查队列,并比cron允许的更频繁地执行工作


这样,唯一可以运行特权的代码就是您的小工作脚本,您无需为web绑定脚本提供任何路径即可获得必要但危险的特权。

创建一个接受命令行选项、验证它并执行useradd的脚本。使用NOLOGIN指令将httpd的用户添加到sudoers文件中,仅用于该进程


这样,您就不必担心编写一个始终以root权限运行的守护程序,您的脚本也将立即返回。如果您只使用setuid根脚本,同一系统上的其他用户可以执行您的脚本(除非您检查了他们的真实用户ID)。

我首先要说,以根用户身份运行httpd是一个非常糟糕的主意

最安全的方法是在Web服务器UI和效应器之间进行完全的权限分离-一种明显的方法是以根用户身份运行服务器,只接受UI向其发送请求的本地连接(一种简单的方法是通过inetd/xinetd实现——这意味着您不必为建立守护进程的所有复杂性而烦恼)

用户界面和效应器之间还需要某种信任机制(共享秘密就足够了),以便系统上的其他程序无法调用效应器。使用依赖基于质询的身份验证或非对称加密的信任系统意味着您不再需要担心局部连接约束

最后,您需要一个定义良好的协议,UI和效应器通过该协议进行通信

这比使用sudo复杂得多,但更安全(例如,sudo只允许用户以不同的uid执行特定文件-您希望该文件包含正确的程序)

Setuid与sudo有许多相同的缺点,但增加了复杂性(在大多数情况下),即如果它启动另一个程序,那么它将像原始uid一样启动


C.

唯一的问题是:1)我需要立即创建帐户,我不能等待cron。。。这导致了2)我不想每分钟都运行cron,这不会给服务器带来很大的压力吗?这就是为什么另一种选择是编写一个守护进程(后台进程),监视队列并立即执行操作。只要你没有使用共享主机(如果你正在添加用户,听起来你好像没有),这可能是可行的。如果可以接受等待一分钟,那么每分钟一个cron就可以了。它不会给服务器带来任何可观的负载——大多数情况下,它只会看到队列为空并退出。我可能只需要编写一个小守护程序,每隔一秒钟左右检查一次队列。出于您的目的,一个单进程、非线程守护进程就足够了。唯一的缺点是您现在需要确保您的守护进程始终在运行——但这很容易解决。编写守护进程更有效的方法是将队列设置为命名管道,并在管道的文件描述符上选择守护进程
。这样,它只会在有数据要从队列中读取时运行,而在出现新数据时几乎会立即运行。