WordPress前台表单提交一致性检测,防止浏览器开发模式篡改表单

在开发wnd-frontend插件之初,我就采用了一个偷懒的模式:为表单字段的name值设置固定格式的前缀,自动判断这个字段的数据应该存储在什么地方,比如以_post_为前缀的,就是post数据,_term_为前缀的是分类数据,_usermeta_为用户字段等等。这样一来在后台数据上只需要设置一套统一的规则,就可以实现对各类数据的自动清洗入库。非常方便。这个模式应该是wnd-frontend插件的核心思想之一。

这个通过前缀自动归类表单数据的方法,看起来很方便,但随之而来的就是安全问题。文章的权限其实到在其次,毕竟可以通过WordPress的current_user_can来判断,但对于文章字段,尤其是用户字段来说就比较危险了。例如我们用money这个字段存储了用户的余额,如果按照上面的思路,用户在任何一个表单可以通过浏览器开发模式,植入一个_usermeta_字段就可以随意更改自己的账户余额了。很恐怖吧。

最开始我是通过在设置表单字段白名单的方式来实现安全过滤的,即需要用户自己设置一个组可以通过表单提交修改的meta_key,只有在这个白名单内的数据可以通过前端提交更改。这个方法基本上解决了表单安全的问题。但依然不够方便。而且这总白名单的方式,没法针对单个用户做更详细的定制。我也一直想远没有什么办法可以更好地解决这个问题。

我心里最好的解决方案就是,每个表单生成时,自动根据表单name值,生成当前表单允许的字段。这样就自然保障了数据的安全性。但我一开始的思路不对,可能深受自定义文章类型,和自定义taxonomy的影响,直接朝着注册一个全局变量的思路去了。把问题高复杂了。直到前两天,我突然才想起,为什么不通过wp nonce来实现?

截至2019.05.10我的方法是:

在一个表单中,提取所有字段的name值,并按固定格式排序,去重(radio、checkbox等存在多个同名不同值字段),组合成一个字符串,并对该字符串md5处理,然后根据这个md5字符串生成wp_nonce随表单数据一起发送给后台。在后台数据处理上,首先也是需要获取所有表单数据并按相同的方法做处理,得到对应的字符串,并做nonce校验。校验通过,则说明,表单字段name没有被修改过。

可能有的同学会有疑问,如果用户知道了这个算法,这个nonce能不能逆向推导出来?实际上是有可能的,用户需要去研究一下wp nonce的生成机制,然后在本地测试验证得出nonce。为了更安全,就需要我们在加密算法上做更多处理,例如额外设置一个秘钥,添加到name字符串中,这样只要秘钥的强度足够,安全性是绝对足够的。

需要提示的一点是,如果生成的wp_nonce本身也是表单内的一个字段值,自动随表单发送到后台,那么注意将这个nonce字段自身也要计算在内。

以上方法我已经实际测试通过。如果有更好的思路,欢迎留言交流。

写一条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注