在PHP / CodeIgniter 4中清理HTML表单用户输入的最佳实践

c2e8gylq  于 2023-02-17  发布在  PHP
关注(0)|答案(4)|浏览(162)

我有一个使用CodeIgniter 4框架用PHP编程的简单应用程序,作为一个Web应用程序,它有一些HTML表单供用户输入。
我在做两件事:
1.在我的视图中,来自数据库的所有变量(来自用户输入)都使用CodeIgniter 4的esc()函数进行了清理。
1.在我的控制器中,当阅读HTTP POST数据时,我使用PHP过滤器:
$data = trim($this->request->getPost('field', FILTER_SANITIZE_SPECIAL_CHARS));
我不确定在从POST阅读数据和打印/显示到HTML时进行消毒是否是一种好的做法,或者是否应该 * 只消毒一次 *。
另外,FILTER_SANITIZE_SPECIAL_CHARS不能正常工作。我希望HTML表单文本输入能防止用户使用HTML进行攻击,但我希望保留一些数据库在以前的应用程序中使用的“换行符”。
FILTER_SANITIZE_SPECIAL_CHARS不会删除HTML标记,它只会将它们存储在数据库中,而不是作为HTML存储,但它也会更改我的 “换行符”。是否有一个过滤器不会删除HTML标记(只存储带有适当条件的标记),但会考虑\n“换行符”

xxls0lw8

xxls0lw81#

需要清理用户输入数据,如以下问题所述:
How can I sanitize user input with PHP?
用户输入可以被过滤是一个常见的误解。PHP甚至有一个(现在已经弃用的)“特性”,叫做magic-quotes,它建立在这个想法之上。这是无稽之谈。忘记过滤(或者清理,或者其他人们叫它的东西)吧。
此外,对于 * 大多数使用情形 *,您需要使用FILTER_SANITIZE_SPECIAL_CHARShtmlspecialchars(...)htmlentities(...)esc(...)

  • Comment from OP (user1314836)
    我肯定我不需要净化用户输入的数据,因为我不是直接写SQL,而是使用CodeIgniter 4的函数来创建SQL安全的查询。另一方面,我肯定需要在显示时esc()相同的信息,以避免在只需要文本的地方显示html。
  • 在大多数用例中不需要esc()方法的原因是:*

应用程序中的大多数用户表单输入 * 不 * 期望用户提交/发布您计划稍后显示/运行的HTML、CSS或JavaScript。
如果预期的用户输入仅为纯文本(usernameagebirth date等)、图像或文件,请改用form validation以禁止意外数据。
即:可用规则和创建自定义规则
通过使用Query Builder进行数据库查询并使用验证规则(alphaalpha_numeric_punctnumericexact_lengthmin_length[8]valid_dateregex_match[/regex/]uploaded等)拒绝意外的用户输入数据,您可以避免大多数潜在的安全漏洞,即:SQL injectionsXSS attacks中的一个。

x6yk4ghg

x6yk4ghg2#

据我了解,

FILTER_SANITIZE_SPECIAL_CHARS用于在处理或存储用户输入之前对其进行净化。

esc用于转义字符串中的HTML等,这样它们就不会干扰正常的html、css等。它用于查看数据。

因此,您需要两者,一个用于输入,另一个用于输出。

以下是codeigniter.com。注意,它使用了层压板Escaper库。
esc($数据[,$上下文= 'html'[,$编码]])
参数
$数据(字符串|array)-要转义的信息。
$context(string)-转义上下文。默认值为“html”。
$encoding(string)-字符串的字符编码。
返回转义数据。
返回类型混合
将数据包含在网页中,以帮助防止XSS攻击。这使用Laminas Escaper库来处理数据的实际过滤。
如果$data是一个字符串,那么它就简单地转义并返回它;如果$data是一个数组,那么它就循环遍历它,转义键/值对中的每个“值”。
有效上下文值:html,js,css,网址,属性,原始
docs.laminas.dev开始
什么是laminas-Escaper不是
laminas-escaper只用于转义输出数据,因此不应该被误用来过滤输入数据。对于这样的任务,请使用laminas-filter,应该使用HTMLPurifier或PHP的Filter功能。
它们所做的一些功能是相似的。比如它们都可以/将要把<转换成&lt。然而,你存储的数据可能不仅仅来自用户输入,它可能包含<。这样存储它是非常安全的,但是它需要被转义以用于输出,否则浏览器可能会混淆,认为它是html。

xmjla07d

xmjla07d3#

steven7mwesigwa的回答得到了我的投票,但这里是你应该如何思考它。
规则摘要

  • 应该始终在内存中保存要处理的实际数据。
  • 应始终将输出上的数据转换为输出可以处理的格式。

输入:
您应该去除所有不可信的输入(用户表单、您没有写入的数据库、您不控制的XML提要等)

  • 任何你不能处理的数据(例如,如果你不能处理多字节字符串,因为你没有使用正确的函数,或者你的数据库不支持它,或者你不能处理UTF8/16等,去掉那些你不能处理的额外字符)。
  • 任何永远不会构成进程或输出的一部分的数据(例如,如果只能有一个整型/布尔,则转换为整型/布尔;如果你只在HTML页面上显示数据,那么你也可以减少空格;如果需要日期,请去掉任何不能格式化为日期内容[或拒绝 *])。

这意味着不需要许多"传统"清理功能(例如,魔术引号、strip_tags等):但是你需要知道你可以处理代码。如果你知道在那个字段中有那些数据是没有意义的,你应该只使用strip_tags或者escape等等。
注:对于用户输入,我倾向于在用户输入时保留数据并拒绝表单,以允许他们重试。例如,如果我需要一个数字,但我得到了"hello",则我将使用"hello"重新加载表单,并告诉用户重试。steven7mwesigwa具有CI中验证函数的链接,可实现此操作。
输出:
为输出选择正确的转换:别把他们搞混了。

  • 用于输出到HTML或XML的html特殊字符(或家族);尽管这通常由您使用的任何模板引擎来处理。
  • 数据库输入转义;尽管这应该留给你使用的DB引擎(例如参数化查询、查询构建器等)。
  • 用于输出URL的urlencode
  • 根据需要保存图像、json、API响应等

为什么?
如果您在输入时执行输出转换,则可以轻松地对输入进行双重转换,或者在输出前忘记是否需要确保安全,或者丢失用户想要输入的数据。错误会发生,但遵循干净的规则可以防止错误。
这也意味着没有必要拒绝特殊字符(例如,拒绝引号的表单会带来糟糕的用户体验,任何限制密码字段中可以使用哪些字符的人只会削弱安全性)
在您的特定情况下:

  • 在输入时删除FILTER_SANITIZE_SPECIAL_CHARS,保留用户提供的数据
  • 使用现有模板引擎输出:这将显示用户输入的〈〉标记,但不会中断输出。

基本上,您将清理每个输出(您似乎希望避免),但这比意外错过输出清理更安全,比丢失输入的内容更好的用户体验。

n3ipq98p

n3ipq98p4#

我认为在这种情况下使用esc就足够了。FILTER_SANITIZE_SPECIAL_CHARS是一个PHP过滤器,它可以对“"〈〉&进行编码,并且可以根据标志对其他特殊字符进行剥离或编码。为此,您需要设置标志。它是getPost()方法中的第三个参数。下面是一个示例

$this->request->getPost('field', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_ENCODE_HIGH)

这个标志可以根据你的要求改变。你可以使用任何带有标志的PHP过滤器。请参考php documentation了解更多信息。

相关问题