PHP 应用程序的安全问题比平均水平要多。您使用哪些配置技术来确保应用程序尽可能安全?
我正在寻找类似这样的想法:
- 使用强化的 PHP/Suhosin
- 使用mod_security
- 在 php.ini 中禁用 register_globals 和 allow_url_fopen
我通常使用 Linux,但也欢迎提出 Windows 解决方案。
答案1
使用 open_basedir 指令将 PHP 脚本限制在其主目录和最终的额外应用程序目录中。这本身就非常有效。
使用强化的 php,因为它不花费任何成本而且可以提供帮助。
使用苏普让 PHP 脚本以文件所有者的身份执行(每个网站一个用户),并避免使用权限不良的文件,如 777...suPHP 还允许您在每个网站上拥有 php.ini,这样一个网站的愚蠢要求就不会破坏一切。
Mod_security 是一个很大的优点,但需要很好地使用和配置。
答案2
根据我的经验,基于 PHP 的网站上的大多数漏洞是由于糟糕的(网站)设计造成的,而不是 PHP 本身的缺陷。
一些快速提示:
- 普遍过滤输入,转义输出。澄清:过滤并不意味着转义,它意味着“如果我发现用户输入中存在可疑之处,则导致提交失败并告诉用户重新格式化。”
- 不要使用 escapeshellcmd(),只需不允许在 shell 中执行任何用户输入。这很危险,而且可能实际上没有必要。
- 不在生产站点上调用像 phpinfo() 这样的函数(或者如果您这样做,请参见下文*)。
- 在设计 Web 应用程序时,总是考虑“这是一个可能的攻击媒介吗?”比如 SQL 注入。如果答案是“是”,请立即将其堵住 - 不要说“好的,我将在以后的开发中将其作为一项功能添加。”安全从来都不是一个功能。
- 绝不将原始错误输出给用户;这意味着设置 php.ini 的 display_errors = Off、log_errors = On。捕获运行时错误并输出一些漂亮的内容。以 Twitter 的鲸鱼为例:它不会向用户提供调试级别的信息,只会说“哎呀,有东西坏了,请刷新”。
*你也可以看看我写的一篇短文,名为“保护 phpinfo()”,一定要阅读评论http://egovsergo.com/2009/04/03/protecting-your-phpinfo/我很快就想到,如果我因某种原因忘记在生产站点上删除 phpinfo(),我必须(以某种方式)保护它。
更一般地,一些开发人员为敏感功能编写包装器,检查是否设置了“生产站点”标志,并在生产中禁用该敏感功能。
答案3
为了强化 PHP,还应该修改其他参数:
safe_mode = Off
register_globals = Off
expose_php = Off
allow_url_fopen = Off
allow_url_include = Off
log_errors = On
error_log = /var/log/phperror.log
display_errors = Off
enable_dl = Off
disable_functions="popen,exec,system,passthru,proc_open,shell_exec,show_source,phpinfo"
将所有 PHP 错误存储在文件中/var/log/phperror.log:
touch /var/log/phperror.log
chmod 666 /var/log/phperror.log
答案4
open_basedir
考虑按“每个站点” 进行设置。open_basedir
是一个 php.ini 设置,它将阻止您的脚本访问定义的白名单之外的文件。 如果您的服务器托管多个站点,它将阻止一个站点从另一个站点读取数据库设置。 它还将阻止 php 脚本访问/修改核心系统文件。 Open basedir 很容易设置,只需将行“ php_admin_value open_basedir /my/list/of/folders:/as/a/colon/seperated/list
”添加到每个 Apache vhost 即可。
还可以考虑关闭所有不应包含 PHP 脚本的站点/文件夹(例如上传的图像文件夹)的 PHP 脚本引擎。同样,这很简单,只需将“php_admin_value engine off”添加到任何不需要 php 的 Apache VirtualHosts 即可。要禁用目录中的 PHP,请将相同的内容放入 Directory 标记中。
运行文件权限尽可能严格,避免 Apache 用户对 PHP 脚本具有写访问权限,这可以防止正在运行的脚本修改自身或同一站点/服务器上的其他脚本。尽可能避免使用 777 权限,找出运行应用程序所需的最低权限并使用这些权限。
如果您托管多个网站,每个网站都有自己的数据库,请为每个网站使用单独的 MySQL/Postgres 用户,并为每个用户设置权限,使他们只能访问相关数据库。这同样可以防止恶意脚本篡改其他应用程序的数据库。
Suosin、HardenedPHP、mod_security 等也都很有用,但是应该将它们作为严格锁定的配置的补充,而不是替代。