假设我有一个用JavaScript编写的单页web应用程序和一个服务器端API,两者都是我可以改变的。该应用程序根据用户输入计算一些值,并将这些值发布到API中。这些值基于用户输入,但不包含用户输入。例如,它可能要求用户根据单选按钮选择A或B,然后将他们的选择发送到服务器。没有会话,并且用户是匿名的。
规则1永远不信任用户输入。恶意用户可以修改有效负载,并将"A“更改为"C”(不是其中一种选择)。我不希望这种事发生。
对于简单的情况,有一个明显的解决方案:验证输入服务器端。如果不是"A“或"B",就拒绝它。然而,在一个复杂的应用程序中,可能的排列次数可能会使验证变得非常困难。
应用程序可以在发送之前对计算出的有效载荷进行数字签名,但是由于客户端可以使用JavaScript,用户可以同时获得密钥和算法。在这里混淆是不够的。
有没有人想出办法来防止这种篡改?服务器提供的基于时间的密钥?Web3?或者是否有正式的证据证明这是不可能的(除了针对一组输入约束的服务器端验证之外)?
发布于 2022-03-06 03:37:33
TL,DR:客户端不可能这样做。
客户端验证只是客户端的一种方便,对于真正验证任何东西都没有用。您不希望客户端键入错误的电子邮件,在某个地方放置无效的char,并且必须等待提交的表单、服务器解析它,并在5秒后发回一个错误,您希望该错误立即显示。您在客户端上进行验证,但是完全忽略客户端验证,然后在服务器上再次验证。
如果验证是由客户端完成的,则客户端可以手工提交请求,从而绕过所有验证。即使您使用散列、签名、混淆或其他任何方法,结果也是HTTP请求,客户端可以拦截并篡改它。
如果您的用例是您所要求的,那么服务器验证一点也不困难。有一个包含所有问题和所有有效答案的表格,并使用该表检查每个客户端的答案。对于第一个无效的答案,您将停止处理并返回一个空页。
可能的排列数可能会使验证变得非常困难。
您必须在服务器端(从琐碎到非常困难)和客户端(根本不可能)之间进行选择。我相信选择是容易的。
发布于 2022-03-06 18:53:35
您必须在服务器端验证它。你说可能的排列数量太大了--但客户端不知何故做到了,不是吗?如果服务器端没有足够的信息来有效地验证输入,那么让客户端发送更多信息。最坏的情况是,只需发送所有原始用户输入并重新计算服务器端的所有内容,而完全忽略客户端的工作。
发布于 2022-03-06 02:56:03
处理此问题的唯一方法是对连接进行身份验证并控制浏览器中发生的事情。当然,验证连接是可能的,但控制浏览器是另一回事。您必须同时信任操作系统和浏览器,并避免泄漏任何身份验证密钥。
总之:不,这是不可能的,至少对一般用户来说是不可能的。如果计算机由受信任的实体控制,可能在某种程度上是可能的。但是,通常您应该在服务器上维护一个安全状态,其中包括验证输入,以防触发这样的无效状态。
https://security.stackexchange.com/questions/260116
复制相似问题