当前位置:  开发笔记 > 编程语言 > 正文

实例分析10个PHP常见安全问题

在本篇文章里小编给各位分享了关于10个PHP常见安全问题以及相关实例代码,需要的朋友们学习参考下。

相对于其他几种语言来说, PHP 在 web 建站方面有更大的优势,即使是新手,也能很容易搭建一个网站出来。但这种优势也容易带来一些负面影响,因为很多的 PHP 教程没有涉及到安全方面的知识。

本文分为几部分,每部分会涵盖不同的安全威胁和应对策略。但是,这并不是说你做到这几点以后,就一定能避免你的网站出现任何问题。如果你想提高你的网站安全性的话,你应该继续通过阅读书籍或者文章,来研究如何提高你的网站安全性

出于演示需要,代码可能不是很完美。日常开发过程中,很多代码都包含在了框架跟各种库里面。作为一个后台开发,你不仅要熟练基本的 CURD,更要知道如何保护你的数据。

1. SQL 注入

我赌一包辣条,你肯定会看到这里。 SQL 注入是对您网站最大的威胁之一,如果您的数据库受到别人的 SQL 注入的攻击的话,别人可以转出你的数据库,也许还会产生更严重的后果。

网站要从数据库中获取动态数据,就必须执行 SQL 语句,举例如下:

<?php

$username = $_GET['username'];

$query = "SELECT * FROM users WHERE username = '$username'";

攻击者控制通过 GET 和 POST 发送的查询(或者例如 UA 的一些其他查询)。一般情况下,你希望查询户名为「 peter 」的用户产生的 SQL 语句如下:

SELECT * FROM users WHERE username = 'peter'

但是,攻击者发送了特定的用户名参数,例如:' OR '1'='1

这就会导致 SQL 语句变成这样:

SELECT * FROM users WHERE username = 'peter' OR '1' = '1'

这样,他就能在不需要密码的情况下导出你的整个用户表的数据了。

那么,我们如何防止这类事故的发生呢?主流的解决方法有两种。转义用户输入的数据或者使用封装好的语句。转义的方法是封装好一个函数,用来对用户提交的数据进行过滤,去掉有害的标签。但是,我不太推荐使用这个方法,因为比较容易忘记在每个地方都做此处理。

下面,我来介绍如何使用 PDO 执行封装好的语句( mysqi 也一样):

$username = $_GET['username'];

$query = $pdo->prepare('SELECT * FROM users WHERE username = :username');

$query->execute(['username' => $username]);

$data = $query->fetch();

动态数据的每个部分都以:做前缀。然后将所有参数作为数组传递给执行函数,看起来就像 PDO 为你转义了有害数据一样。

几乎所有的数据库驱动程序都支持封装好的语句,没有理由不使用它们!养成使用他们的习惯,以后就不会忘记了。

2. XSS

XSS 又叫 CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往 Web 页面里插入恶意 html 代码,当用户浏览该页之时,嵌入其中 Web 里面的 html 代码会被执行,从而达到恶意攻击用户的特殊目的。

下面以一个搜索页面为例子:



<?php

$searchQuery = $_GET['q'];

/* some search magic here */

?>

You searched for: <?php echo $searchQuery; ?>

We found: Absolutely nothing because this is a demo

因为我们把用户的内容直接打印出来,不经过任何过滤,非法用户可以拼接 URL:

search.php?q=%3Cscript%3Ealert(1)%3B%3C%2Fscript%3E

PHP 渲染出来的内容如下,可以看到 Javascript 代码会被直接执行:



You searched for:

We found: Absolutely nothing because this is a demo

问:JS 代码被执行有什么大不了的?

Javascript 可以:

偷走你用户浏览器里的 Cookie;

通过浏览器的记住密码功能获取到你的站点登录账号和密码;

盗取用户的机密信息;

你的用户在站点上能做到的事情,有了 JS 权限执行权限就都能做,也就是说 A 用户可以模拟成为任何用户;

在你的网页中嵌入恶意代码;

...

问:如何防范此问题呢?

好消息是比较先进的浏览器现在已经具备了一些基础的 XSS 防范功能,不过请不要依赖与此。

正确的做法是坚决不要相信用户的任何输入,并过滤掉输入中的所有特殊字符。这样就能消灭绝大部分的 XSS 攻击:

<?php

$searchQuery = htmlentities($searchQuery, ENT_QUOTES);

或者你可以使用模板引擎 Twig ,一般的模板引擎都会默认为输出加上 htmlentities 防范。

如果你保持了用户的输入内容,在输出时也要特别注意,在以下的例子中,我们允许用户填写自己的博客链接:

以上代码可能第一眼看不出来有问题,但是假设用户填入以下内容:

#" onclick="alert(1)

会被渲染为:

永远永远不要相信用户输入的数据,或者,永远都假设用户的内容是有攻击性的,态度端正了,然后小心地处理好每一次的用户输入和输出。

另外设置 Cookie 时,如果无需 JS 读取的话,请必须设置为 "HTTP ONLY"。这个设置可以令 JavaScript 无法读取 PHP 端种的 Cookie。

3. XSRF/CSRF

CSRF 是跨站请求伪造的缩写,它是攻击者通过一些技术手段欺骗用户去访问曾经认证过的网站并运行一些操作。

虽然此处展示的例子是 GET 请求,但只是相较于 POST 更容易理解,并非防护手段,两者都不是私密的 Cookies 或者多步表单。

假如你有一个允许用户删除账户的页面,如下所示:

<?php

//delete-account.php

$confirm = $_GET['confirm'];

if($confirm === 'yes') {

 //goodbye

}

攻击者可以在他的站点上构建一个触发这个 URL 的表单(同样适用于 POST 的表单),或者将 URL 加载为图片诱惑用户点击:

你是不希望用户看到这个的吧?

一般根据你使用的框架或者 CMS ,配置方法会有不同的变化。通常框架具有允许你将站点更改为某种生产环境的设置。这样会将所有用户可见的错误消息重定向到日志文件中,并向用户显示非描述性的 500 错误,同时允许你根据错误代码检查。

但是你应该根据你的 PHP 环境设置: error_reporting 与 display_errors.

10. 登录限制

像登录这样的敏感表单应该有一个严格的速率限制,以防止暴力攻击。保存每个用户在过去几分钟内失败的登录尝试次数,如果该速率超过你定义的阈值,则拒绝进一步登录尝试,直到冷却期结束。还可通过电子邮件通知用户登录失败,以便他们知道自己的账户被成为目标。

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有