2

我正在开发一些 WordPress 插件,它的功能之一是能够将用户输入的 HTML 正则表达式模式存储到数据库,然后将其显示在设置页面上。

我的方法实际上是可行的,但我想知道该代码是否足够安全:

那是用户输入的模式:

<div(.+?)class='sharedaddy sd-sharing-enabled'(.*?)>(.+?)<\div><\div><\div>

这就是我在 DB 中存储 HTML 模式的方式:

$print_options['custom_exclude_pattern'] = htmlentities(stripslashes($_POST['custom_exclude_pattern']),ENT_QUOTES,"UTF-8"); 

这就是它实际存储在 WordPress DB 中的方式:

s:22:"custom_exclude_pattern";s:109:"&lt;div(.+?)class=&quot;sharedaddy sd-sharing-enabled&quot;(.*?)&gt;(.+?)&lt;\div&gt;&lt;\div&gt;&lt;\div&gt;";

这就是输出在设置页面上的显示方式:

<input type="text" name="custom_exclude_pattern" value="<?php echo str_replace('"',"'",html_entity_decode($print_options['custom_exclude_pattern'])); ?>" size="30" />

感谢帮助 :)

4

3 回答 3

1

我希望我明白了这一点,如果没有,请纠正我:您正在尝试根据存储在数据库中的相同模式为输入字段动态插入模式,对吗?好吧,我个人认为模式对可用性有很好的帮助,因为用户知道他的输入格式不正确,而无需每次都提交和刷新。模式的大问题是,HTML 代码可以在客户端进行修改。我相信唯一安全的解决方案是检查服务器端输入的正确性......客户端程序不可能比服务器端程序更安全!

于 2015-06-11T03:19:08.320 回答
1

好吧,如果你要让你的用户输入一个正则表达式,你可以做一些类似准备好的语句 + htmlentities($input, ENT_COMPAT, "UTF-I");来清理输入,然后做相反的事情,那就是html_entity_decode($dataFromDb, ENT_COMPAT, " UTF-8");. 必须是准备好的语句,所有其他解决恶意输入的方法都可以以许多不同的方式组合!

于 2015-06-11T10:59:36.280 回答
1

从评论中,听起来您关心两个独立的问题(可能不知道我稍后会提到的第三个问题)并为这两个问题寻找一个解决方案:SQL 注入跨站点脚本。你必须分别对待每一个。我恳请您阅读 Defuse Security 的这篇文章

如何防止 SQL 注入

这个问题之前在 StackOverflow上已经回答了关于 PHP 应用程序的一般问题。WordPress$wpdb支持预处理语句,因此您也不必弄清楚如何使用 PDO 或 MySQLi。(但是,他们的驱动程序中的任何漏洞都会影响您的插件。确保您$wpdb彻底阅读了文档。

将参数传递给准备好的语句之前,不应转义参数。您最终会得到经过处理的数据。

跨站脚本

在撰写本文时(2015 年 6 月),您需要考虑两种一般情况:

  1. 不应允许用户此输入提交任何 HTML、CSS 等。
  2. 允许用户向此输入提交一些 HTML、CSS 等,但我们不希望他们能够通过这样做来破解我们。

第一个问题很简单,可以解决:

echo htmlentities($dbresult['field'], ENT_QUOTES | ENT_HTML5, 'UTF-8');

第二个问题有点棘手。它涉及仅允许某些标记,而不会意外地允许其他可用于使 Javascript 在用户浏览器中运行的标记。当前在 XSS 防御中允许一些 HTML 的黄金标准是HTML Purifier

重要的!

无论您的要求是什么,您都应该始终对输出应用 XSS 防御,而不是在将内容插入数据库之前。最近,Wordpress 核心有一个存储的跨站点脚本漏洞,这是由于决定在存储前转义而不是在渲染前转义造成的。通过提供足够长的注释,攻击者可以在转义文本上触发 MySQL 截断错误,从而使他们能够绕过防御。

奖励:来自的 PHP 对象注入unserialize()

这就是它实际存储在 WordPress DB 中的方式:

s:22:"custom_exclude_pattern";s:109:"&lt;div(.+?)class=&quot;sharedaddy sd-sharing-enabled&quot;(.*?)&gt;(.+?)&lt;\div&gt;&lt;\div&gt;&lt;\div&gt;";

看起来您serialize()在存储此数据时正在使用,并且可能unserialize()在检索数据时正在使用。小心unserialize(); 如果您让用户对字符串有任何控制权,他们可以将 PHP 对象注入您的代码中,这也可能导致远程代码执行。

记录在案的远程代码执行意味着他们可以接管您的整个网站,并可能接管托管您博客的服务器。如果用户有可能直接更改此记录,我强烈建议使用json_encode()andjson_decode()代替。

于 2015-06-11T15:10:26.267 回答