在客户端使用验证码的哈希值进行验证是否安全?

5

我经常使用验证码来保护表单。迄今为止,由于明显的原因,我只在服务器端检查用户输入的验证码解决方案。

对于所有其他表单字段,我在客户端进行javascript验证,因为这样更快且更用户友好;(当然,我会在服务器端进行第二次检查),但是对于验证码字段,我只检查它是否已填写。

我的问题: 通过使用哈希密钥(例如MD5),在客户端JavaScript验证中使用是否安全?使用哈希密钥进行验证不会向机器人透露验证码本身,应该相当安全,对吗?

但也许我的想法完全错误... 感谢您的见解!


1
仅在客户端上吗? - zerkms
不仅仅是客户端,第二个检查将在服务器上进行。 - Arno
2个回答

5
足够安全,但这可能会帮助OCR机器人检查它们是否正确破解验证码而不必冒险尝试在服务器上进行操作并且有可能失去当前的验证码(因为如果提供了错误答案,则服务器将使代码无效,并且不会让您使用相同的验证码再次尝试)。
假设一个OCR机器人无法确定您的验证码的最后一个字母是小写L还是数字"1"?在没有客户端验证的传统验证码中,机器人只需尝试自己的运气,如果猜错了,服务器会记录失败并重新发送完全不同的验证码,因此OCR不得不重新开始。
现在想象一下上述情况,但具有客户端验证,这里机器人有一种方法来验证它们是否有正确的答案,而不通知服务器,因此,在这种情况下,如果机器人不确定,它会针对哈希算法尝试所有可能性,仅提交正确的答案。基本上,这给了机器人犯错误的能力,而不必告诉服务器并且无需重新开始。
最后,我没有确切的数字,但即使每次都有不同的盐(如4个大小写不敏感的字母数字字符),根据可能性的数量,也可能在合理的时间内暴力破解每个可能性,甚至不需要进行OCR。为了减轻这种情况,应使用哈希的许多迭代,以便尝试所有可能的答案变得计算上困难。

嗨,安德烈,你说得很好,我之前没有看到这一点!如果你真的希望有人分析你的表单和代码,我认为这个方面确实会破坏验证码的安全性。但有时验证码更像是对垃圾邮件发送者的“提示”,它告诉他们:“不要尝试——我已经准备好了”;-) - Arno
@Arno:“但有时验证码更多地被视为对垃圾邮件发送者的“提示”。” --- 那么可以放置一个虚假的静态图像,没有任何逻辑。简单易行。 - zerkms
如果你只是担心路人垃圾邮件机器人,那么一个简单的解决方案就是让你真正的表单字段名称具有随机/无意义的值,然后创建一些隐藏字段,例如“电子邮件”,“姓名”,“消息”,基本上任何看起来像联系表单的东西。在服务器上,检查这些蜜罐字段是否为空(因为它们对人类不可见),如果不为空,则是垃圾邮件机器人。当然,这种方法在针对性攻击的情况下也会失效,但你的解决方案也是如此。 - user2629998

1

听起来可行,但是你一定要考虑一个长而随机的盐来防止基于预计算的简单攻击。

更正式地说,你需要发送图像、一个长而随机的盐和哈希值。然后,在客户端,你将计算输入文本与盐连接后的哈希值,并将结果与哈希值进行比较。

由于有了长而随机的盐,攻击者的预计算集合必须非常庞大才能反映出所有可能的盐值。

此外,忘记使用MD5,因为它被认为是不安全的。使用更强的哈希函数。

还要注意,这只是可能会提高用户体验的东西(在验证码输入错误时无需POST页面),但绝不能仅在客户端执行。实际验证必须在服务器上完成。


1
记住验证码通常只有6个字符长(甚至更短)-你可以直接暴力解决它。因此s/doable/security flaw/ - zerkms
嗨Wiktor,非常感谢您的提示和建议!zerkms的评论使我相信不要在应该真正受保护的表单上使用此客户端验证。 - Arno
@zerkms:可以要求使用大量轮次计算哈希值,以便单个计算需要大量时间。这样暴力破解就可能更加困难。 - Wiktor Zychla
@WiktorZychla 正如另一个答案中提到的 - 如果您有OCR,则可能需要对1或2个字符进行暴力破解,这对于任意轮数来说都是即时的。我个人认为,故意放置安全漏洞然后尝试加强它是一种冒险的做法。 - zerkms
1
@zerkms:同意,我是那个在我的回答下点赞你的评论以及你的回答的人。 - Wiktor Zychla
@zerkms:我敢打赌上面回答的是你,但事实并非如此。不过这只是小问题 ;) - Wiktor Zychla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接