运行Fedora 9/10,Apache 2,PHP 5 ...
我可以使用exec()?
从PHP脚本以root身份运行shell脚本我只是给Apache root priveleges,然后在他们面前添加“sudo”命令吗?
具体来说,我正在尝试启动和停止后台脚本。
目前我有一个只运行应用程序的shell脚本,start.sh:
#!/bin/bash
/path/to/my/app/appname
一个杀死应用程序的脚本,stop.sh:
#!/bin/bash
killall appname
我会这么做:
<?php
exec("sudo start.sh");
?>
提前致谢。
答案 0 :(得分:13)
你不能只是sudo那样,你需要先在/ etc / sudoers文件中设置无密码sudo。例如,可以使用visudo命令完成此操作。确保在sudoers文件中设置权限,以便将apache用户限制为您希望运行的单个命令(即shell脚本)。
即使这样,它也会带来安全风险,因为任何人都可以创建PHP脚本并依次运行shell脚本。因此,请确保shell脚本本身不会被Apache用户更改。
第二部分 killall 更有问题。您不应该只允许Apache以root权限运行killall。你应该将killall包装在另一个shell脚本中,并在sudoers中授予访问权限。
最后:不要使用root帐户运行Apache,也不要使用setuid。两者都打开了一堆蠕虫,因为你是一个新手(考虑到你提出的问题),你很可能会错过一些会产生潜在问题的小细节。
答案 1 :(得分:4)
不要以root
的身份运行Apache。 Apache的设计非常适合以root
开头,然后尽快放弃其权限
不要在您的脚本中使用sudo
- 最终导致sudo
配置错误太容易,以至于服务器上运行的任何脚本都可以运行任何程序喜欢root
特权
看看让自己的程序运行“setuid”,这样它就会获得root权限,但是当它不再需要它们时就会删除它们(就像Apache那样)
确保任何不能运行它的人都无法运行“setuid”可执行文件。
答案 2 :(得分:3)
我在这个领域不专业,但看起来你需要SUID标志。
请在此处阅读examples或Google
答案 3 :(得分:2)
你需要一层抽象来至少提供一点安全性!...
我这样做的方法是在Python中编写一个带root权限的简单UDP服务器*: 注意在给定端口上传入的UDP数据包 将它们与白名单进行比较 如果他们匹配执行操作
然后你有一点PHP用预定义的消息向Python服务器发送消息......
<?php
$handle = fsockopen("udp://localhost",12345);
fwrite($handle,"Start Script");
fclose($handle);
?>
python服务器监视端口12345上的数据包,但只是忽略任何不是“启动脚本”或“停止脚本”的数据包,因为它以root身份运行,它可以愉快地启动您的bash脚本。你绝对必须使用白名单,直接从UDP套接字向命令行发送任何输入真是不安全!
请注意,UDP可以被欺骗,因此如果您的防火墙允许欺骗入站流量(它真的不应该!),有人可能会将伪造的数据包发送到您的Python服务器并停止/启动您的服务。这不太可能是一个问题,但如果您无法修复防火墙并且想要防范它,您可以使用无法欺骗的TCP / IP重写上述内容。
Roger Heathcote。
*这是一个非常简单的服务器(约20行),但如果你不知道如何发送消息,我会发送给你或发布在这里。
答案 4 :(得分:2)
你不想给Apache root。
您的问题还有另一种解决方案。问题是Apache无法终止进程,因为它由root拥有。您可以做的是将所有者更改为“www-data”,这是Apache所识别的。
如果该流程是服务并在启动时启动,则可以添加
sudo -u www-data <start-up script>
这样www-data将成为该进程的所有者,因此运行关闭脚本将起作用。
答案 5 :(得分:1)
根据要求,这是python服务器......
#!/usr/bin/python
import os
import socket
print " Loading Bindings..."
settings = {}
line = 0
for each in open('/path/to/actions.txt', 'r'):
line = line + 1
each = each.rstrip()
if each <> "":
if each[0] <> '#':
a = each.partition(':')
if a[2]:
settings[a[0]] = a[2]
else:
print " Err @ line",line,":",each
print " Starting Server...",
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", port))
print "OK."
print " Listening on port:", port
while True:
datagram = s.recv(1024)
if not datagram:
break
print "Rx Cmd:", datagram
if settings.has_key(datagram):
print "Launch:", settings[datagram]
os.system(settings[datagram]+" &")
s.close()
配置文件“actions.txt”使用格式“action-name:adjacent-shell-command”,即。
# Hash denotes a comment
webroot:nautilus /var/www
ftp:filezilla
edit_homepage:gedit /var/www/homepage/htdocs/index.php
此代码不检查传入的UDP数据包的原始IP,因为我在localhost上运行它,我被其他任何人防火墙,并且无论如何检查都不会提供欺骗保护。
我没有时间重写它以使用TCP / IP,但Python是一种值得了解的语言,所以如果你真的想要这个功能,我会留给你一个google的'Python'和'SOCK_STREAM'。这可能不值得你的麻烦,它更容易配置你的防火墙,以便没有欺骗的localhost数据包可以通过并修改代码,以确保它只侦听来自环回的数据包。
答案 6 :(得分:1)
您可以考虑使用具有keepair身份验证的localhost的ssh连接到具有root权限的帐户。在这样的设置中,您不需要为您的网络服务器进行root访问。