插件在哪种情况下负责数据验证/清理?


17

我想确保插件/主题中的所有数据在进入数据库之前以及输出到浏览器之前都得到安全处理。我的问题是,在某些情况下,API会为您处理清理操作(例如,保存帖子元字段时),而在某些情况下,插件/主题作者将全权负责清理操作(例如,保存自定义设置时)。

对于此问题的范围,我不关心在域级别验证数据-例如,检查表单上的Age字段是否在0到120之间,或电子邮件地址是否有效。我只关心安全性-例如,转义SQL查询以避免在保存到数据库时进行SQL注入,或者清除输出到HTML模板的数据以避免XSS。

为了进行输出清理,我知道在将变量回显到HTML模板中时,您总是需要使用esc_html()和之类的函数esc_attr()。但是,使用模板标签时呢?他们都已经清理输出了吗?如果是这样,则针对哪个上下文(常规HTML,标记属性等)?某些函数具有针对不同上下文的变体(例如the_title_attribute(),但大多数没有)。

为了进行输入清理,我知道$wpdb->prepare()在进行手动查询时需要使用,但是在使用Settings API创建插件设置页面或为自定义帖子类型保存帖子元字段时该怎么办?

现在,每当我使用一个函数来查找它是否可以清除时,我就一直在深入研究Core并阅读教程,但这很容易出错并且很耗时。我希望找到所有可能情况以及API是否处理的全面列表。例如,

API验证/清除

  • 使用 update_postmeta()
  • 保存用户元 update_user_meta()
  • 输出帖子标题-使用上下文相关的变体 the_title()
  • 等等

您必须手动验证/消毒

  • 使用Settings API保存插件选项。将回调作为的第3个参数传递register_setting()
  • 直接数据库查询:将查询包装在中$wpdb->prepare()
  • 以HTML输出变量。使用esc_attr()esc_html()
  • 等等

我也很想了解为什么在某些情况下API提供了它,而在其他情况下却没有。我假设它与数据的未知性质有关,但希望听到一个详尽的解释。


我喜欢这个问题。我和你有同样的想法。我认为,如果有这样的清单,当我们必须手动验证/消毒时,那会很棒。+1。
Anh Tran 2012年

1
@Rilwis,请参阅我的回答。您必须始终进行验证。卫生处理比较麻烦,因为“安全”取决于环境。一般情况下,如果使用与WordPress,已知数据WordPress的API( the_title()the_permalink()等),你是罚款,但与自定义数据你是不是(例如get_post_meta())。如有疑问,请对自己的身体进行消毒 -不会受伤。
史蒂芬·哈里斯

@StephenHarris:我读了你的评论。我也知道 但是我和伊恩·邓恩(Ian Dunn)有相同的看法。我认为他问的主要原因是“做得足够,不要多做,不要少做”。
Anh Tran 2012年

1
实际上,我不介意在谨慎和进行过多的验证/卫生方面犯错,但是我认为在某些情况下,两次转义是个问题。
伊恩·邓恩2012年

Answers:


15

这里有两个概念:

  • 验证-确保数据是 有效,即整数是整数,日期是日期(采用正确的格式等)。这应该在保存数据之前完成。
  • 消毒 -确保日期安全在当前上下文中的使用(例如,转义SQL查询或在输出中转义HTML)。

验证几乎普遍地完全取决于您。您知道您要向用户询问什么数据,也知道您期望什么数据-WordPress不需要。验证将在例如save_post钩子保存到数据库之前钩子update_post_meta,也可以通过在Settings API中指定一个回调函数(在WordPress保存数据之前调用)来完成验证。

消毒有点混杂。当处理WordPress本身知道的数据(例如帖子的磁贴)时,您可以确定WordPress已经使数据安全。但是,“安全”取决于具体情况。在页面上安全使用的内容不一定是安全的元素属性。因此,WordPress的将有不同的上下文不同的功能(例如the_title()the_title_rss()the_title_attribute() - ),所以你需要使用正确的

在大多数情况下,您的插件可能会处理post meta或自定义表中的事件数据。WordPress不知道该数据是什么或用于什么目的,因此它当然也不知道如何使其安全。这取决于你。这在使用特别重要esc_url()esc_attr()esc_textarea()等,以防止能够嵌入代码恶意输入。由于WordPress知道next_posts()应该在页面上打印一个url,因此它适用esc_url()-但是对于post meta,例如,它不知道它存储了url-或您要使用的URL(如果打印esc_url(),则如果重定向)esc_url_raw()如果处于对立状态-谨慎行事,自己逃避 -并尽可能晚进行。

最后-保存数据如何?那您需要确保它安全吗?如前所述,你做的必要,以确保数据有效。但是,如果使用WordPress API( wp_insert_post()update_post_meta()等等),那么你就不需要消毒数据-保存数据时,因为唯一的消毒,你需要做的就是逃跑的SQL语句-和WordPress的做到这一点。如果您正在运行直接SQL语句(例如从自定义表中读取/写入数据),则应使用$wpdb该类来帮助您清理查询。

我写了一篇有关数据清理和验证的博客文章,您可能会发现它对您有所帮助-在其中,我谈到了您对此的期望。


嗨,斯蒂芬,谢谢您的解释。确实可以帮助我更好地理解它,但是我真正想要的是一种综合清单,就像我举的例子一样。看来您的方法似乎是对WP是否处理它进行有根据的猜测,或者在谨慎方面犯错误并始终进行消毒。如果我拥有权威而全面的清单,而不是依靠我对清单的理解,我会对此更有信心。我还担心两次转义会导致问题。
伊恩·邓恩2012年

我还刚刚更新了问题,以澄清一些问题。
伊恩·邓恩2012年

0

不确定是否如此彻底,但是对于任何插件或主题,都应该对用户输入进行清理。数据库操作应使用$ wpdb->方法来完成。所有$ _GET和$ _POST数据都应进行清理。

与WordPress相比,这是PHP编程的最佳实践。

因此,总而言之,如果有WordPress函数,请使用它,否则,请清理您的变量并自行输入。

如果我不太清楚,请问一个更具体的问题。


3
我了解始终需要对其进行消毒,但是问题是在每种特定情况下谁进行消毒。有时WordPress会自动执行,有时则需要手动执行。我已经更新了问题,以使其更加清晰。
伊恩·邓恩

即使使用update_user_meta(),您仍然需要对其进行验证,因为更新的值可能来自公开的形式或来自用户的输入。如果它的值来自脚本(例如内部决策)或if / else循环,那么您就不应该清理它。
西普里安2012年

1
你传递的价值update_user_meta()被穿过stripslashes_deep(),并sanitize_meta()update_metadata(),然后$wpdb->prepare()$wpdb->update()。因此,我认为您无需对其进行消毒。我想念什么吗?
伊恩·邓恩2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.