PHP 安全问题入门:10 个常见安全问题 + 实例讲解( 二 )


正确的做法是坚决不要相信用户的任何输入,并过滤掉输入中的所有特殊字符 。这样就能消灭绝大部分的 XSS 攻击:
<?php$searchQuery = htmlentities($searchQuery, ENT_QUOTES);或者你可以使用模板引擎 Twig,一般的模板引擎都会默认为输出加上 htmlentities 防范 。
如果你保持了用户的输入内容,在输出时也要特别注意,在以下的例子中,我们允许用户填写自己的博客链接:
<body><a href=https://www.isolves.com/it/cxkf/yy/php/2019-12-31/"">Visit Users homepage以上代码可能第一眼看不出来有问题,但是假设用户填入以下内容:
#" onclick="alert(1)会被渲染为:
<body><a href=https://www.isolves.com/it/cxkf/yy/php/2019-12-31/"#" onclick="alert(1)">Visit Users homepage永远永远不要相信用户输入的数据,或者,永远都假设用户的内容是有攻击性的,态度端正了,然后小心地处理好每一次的用户输入和输出 。
另一个控制 XSS 攻击的方法是提供一个 CSP Meta 标签,或者标头信息,更多详情请见: https://www.html5rocks.com/en...
另外种 Cookie 时,如果无需 JS 读取的话,请必须设置为 "HTTP ONLY" 。这个设置可以令 JavaScript 无法读取 PHP 端种的 Cookie 。
3. XSRF/CSRFCSRF 是跨站请求伪造的缩写,它是攻击者通过一些技术手段欺骗用户去访问曾经认证过的网站并运行一些操作 。
虽然此处展示的例子是 GET 请求,但只是相较于 POST 更容易理解,并非防护手段,两者都不是私密的 Cookies 或者多步表单 。
假如你有一个允许用户删除账户的页面,如下所示:
<?php//delete-account.php$confirm = $_GET['confirm'];if($confirm === 'yes') {//goodbye}攻击者可以在他的站点上构建一个触发这个 URL 的表单(同样适用于 POST 的表单),或者将 URL 加载为图片诱惑用户点击:
<imgsrc=https://www.isolves.com/it/cxkf/yy/php/2019-12-31/"https://example.com/delete-account.php?confirm=yes"/>用户一旦触发,就会执行删除账户的指令,眨眼你的账户就消失了 。
防御这样的攻击比防御 XSS 与 SQL 注入更复杂一些 。
最常用的防御方法是生成一个 CSRF 令牌加密安全字符串,一般称其为 Token,并将 Token 存储于 Cookie 或者 Session 中 。
每次你在网页构造表单时,将 Token 令牌放在表单中的隐藏字段,表单请求服务器以后会根据用户的 Cookie 或者 Session 里的 Token 令牌比对,校验成功才给予通过 。
由于攻击者无法知道 Token 令牌的内容(每个表单的 Token 令牌都是随机的),因此无法冒充用户 。
<?php /* 你嵌入表单的页面 */ ?><form action="/delete-account.php" method="post"><input type="hidden" name="csrf" value=https://www.isolves.com/it/cxkf/yy/php/2019-12-31/"">## 请注意,这是个非常简单的示例,你可以加入更多的代码 。如果你使用的是像 Symfony 这样的 PHP 框架,那么自带了 CSRF 令牌的功能 。
你还可以查看关于 OWASP 更详细的问题和更多防御机制的文章: https://github.com/OWASP/CheatS....
4. LFILFI (本地文件包含) 是一个用户未经验证从磁盘读取文件的漏洞 。
我经常遇到编程不规范的路由代码示例,它们不验证过滤用户的输入 。我们用以下文件为例,将它要渲染的模板文件用 GET 请求加载 。
<body><?php$page = $_GET['page'];if(!$page) {$page = 'main.php';}include($page);?></body>由于 Include 可以加载任何文件,不仅仅是PHP,攻击者可以将系统上的任何文件作为包含目标传递 。
index.php?page=../../etc/passwd这将导致 /etc/passwd 文件被读取并展示在浏览器上 。
要防御此类攻击,你必须仔细考虑允许用户输入的类型,并删除可能有害的字符,如输入字符中的“.” “/” “” 。
如果你真的想使用像这样的路由系统(我不建议以任何方式),你可以自动附加 PHP 扩展,删除任何非 [a-zA-Z0-9-_] 的字符,并指定从专用的模板文件夹中加载,以免被包含任何非模板文件 。
我在不同的开发文档中,多次看到造成此类漏洞的 PHP 代码 。从一开始就要有清晰的设计思路,允许所需要包含的文件类型,并删除掉多余的内容 。你还可以构造要读取文件的绝对路径,并验证文件是否存在来作为保护,而不是任何位置都给予读取 。


推荐阅读