相对于其他几种语言来说, PHP 在 web 建站方面有更大的优势,即使是新手,也能很容易搭建一个网站出来。但这种优势也容易带来一些负面影响,因为很多的 PHP 教程没有涉及到安全方面的知识。
本文分为几部分,每部分会涵盖不同的安全威胁和应对策略。但是,这并不是说你做到这几点以后,就一定能避免你的网站出现任何问题。如果你想提高你的网站安全性的话,你应该继续通过阅读书籍或者文章,来研究如何提高你的网站安全性
出于演示需要,代码可能不是很完美。日常开发过程中,很多代码都包含在了框架跟各种库里面。作为一个后台开发,你不仅要熟练基本的 CURD,更要知道如何保护你的数据。
1. SQL 注入
我赌一包辣条,你肯定会看到这里。 SQL 注入是对您网站最大的威胁之一,如果您的数据库受到别人的 SQL 注入的攻击的话,别人可以转出你的数据库,也许还会产生更严重的后果。
网站要从数据库中获取动态数据,就必须执行 SQL 语句,举例如下:
<"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 代码会被执行,从而达到恶意攻击用户的特殊目的。
下面以一个搜索页面为例子:
<body> <"htmlcode">search.php"htmlcode"><body> <h1>You searched for: <script>alert(1);</script></h1> <p>We found: Absolutely nothing because this is a demo</p> </body>问:JS 代码被执行有什么大不了的?
Javascript 可以:
偷走你用户浏览器里的 Cookie;
通过浏览器的记住密码功能获取到你的站点登录账号和密码;
盗取用户的机密信息;
你的用户在站点上能做到的事情,有了 JS 权限执行权限就都能做,也就是说 A 用户可以模拟成为任何用户;
在你的网页中嵌入恶意代码;
...
问:如何防范此问题呢?
好消息是比较先进的浏览器现在已经具备了一些基础的 XSS 防范功能,不过请不要依赖与此。
正确的做法是坚决不要相信用户的任何输入,并过滤掉输入中的所有特殊字符。这样就能消灭绝大部分的 XSS 攻击:
<"htmlcode"><body> <a href="<" rel="external nofollow" >Visit Users homepage</a> </body>以上代码可能第一眼看不出来有问题,但是假设用户填入以下内容:
#" onclick="alert(1)会被渲染为:
<body> <a href="#" rel="external nofollow" onclick="alert(1)">Visit Users homepage</a> </body>永远永远不要相信用户输入的数据,或者,永远都假设用户的内容是有攻击性的,态度端正了,然后小心地处理好每一次的用户输入和输出。
另外设置 Cookie 时,如果无需 JS 读取的话,请必须设置为 "HTTP ONLY"。这个设置可以令 JavaScript 无法读取 PHP 端种的 Cookie。
3. XSRF/CSRF
CSRF 是跨站请求伪造的缩写,它是攻击者通过一些技术手段欺骗用户去访问曾经认证过的网站并运行一些操作。
虽然此处展示的例子是 GET 请求,但只是相较于 POST 更容易理解,并非防护手段,两者都不是私密的 Cookies 或者多步表单。
假如你有一个允许用户删除账户的页面,如下所示:
<"htmlcode"><img src="/UploadFiles/2021-04-02/delete-account.php">用户一旦触发,就会执行删除账户的指令,眨眼你的账户就消失了。
防御这样的攻击比防御 XSS 与 SQL 注入更复杂一些。
最常用的防御方法是生成一个 CSRF 令牌加密安全字符串,一般称其为 Token,并将 Token 存储于 Cookie 或者 Session 中。
每次你在网页构造表单时,将 Token 令牌放在表单中的隐藏字段,表单请求服务器以后会根据用户的 Cookie 或者 Session 里的 Token 令牌比对,校验成功才给予通过。
由于攻击者无法知道 Token 令牌的内容(每个表单的 Token 令牌都是随机的),因此无法冒充用户。
<"/delete-account.php" method="post"> <input type="hidden" name="csrf" value="<"> <input type="hidden" name="confirm" value="yes" /> <input type="submit" value="Delete my account" /> </form> ## <"htmlcode"><body> <"htmlcode"><"htmlcode"><"htmlcode"><"ping -c 5 $targetIp");输出将包括对目标主机 Ping 5 次。除非采用 sh 命令执行 Shell 脚本,否则攻击者可以执行想要的任何操作。
ping.php"htmlcode"><"ping -c 5 $targetIp");现在你的命令应该是相当安全的,就个人而言,我仍然避免使用 PHP 调用外部命令,但这完全取决于你自己的喜好。
另外,我建议进一步验证用户输入是否符合你期望的形式。
8. XXE
XXE (XML 外部实体) 是一种应用程序使用配置不正确的 XML 解析器解析外部 XML 时,导致的本地文件包含攻击,甚至可以远程代码执行。
XML 有一个鲜为人知的特性,它允许文档作者将远程和本地文件作为实体包含在其 XML 文件中。
<"1.0" encoding="ISO-8859-1""file:///etc/passwd" >]> <foo>&passwd;</foo>就像这样, /etc/passwd 文件内容被转储到 XML 文件中。
如果你使用 libxml 可以调用 libxml_disable_entity_loader 来保护自己免受此类攻击。使用前请仔细检查 XML 库的默认配置,以确保配置成功。
9. 在生产环境中不正确的错误报告暴露敏感数据
如果你不小心,可能会在生产环境中因为不正确的错误报告泄露了敏感信息,例如:文件夹结构、数据库结构、连接信息与用户信息。
你是不希望用户看到这个的吧?
一般根据你使用的框架或者 CMS ,配置方法会有不同的变化。通常框架具有允许你将站点更改为某种生产环境的设置。这样会将所有用户可见的错误消息重定向到日志文件中,并向用户显示非描述性的 500 错误,同时允许你根据错误代码检查。
但是你应该根据你的 PHP 环境设置: error_reporting 与 display_errors.
10. 登录限制
像登录这样的敏感表单应该有一个严格的速率限制,以防止暴力攻击。保存每个用户在过去几分钟内失败的登录尝试次数,如果该速率超过你定义的阈值,则拒绝进一步登录尝试,直到冷却期结束。还可通过电子邮件通知用户登录失败,以便他们知道自己的账户被成为目标。
标签:PHP,安全问题
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com狼山资源网 Copyright www.pvsay.com暂无“实例分析10个PHP常见安全问题”评论...