1

我正在设计 Flex 中的应用程序,该应用程序连接到一些 Web 服务以执行一些金融交易。Web 服务使用 https 协议进行保护,并要求在每个请求登录时创建用户令牌。这用于对用户进行身份验证和授权。到现在为止还挺好。

诀窍在于,并非我们所有的 Web 服务都是粗粒度的。举个例子,我们可以有两种 Web 服务方法:EnoughFounds 和 Transfer。因此,只有在 EnoughFounds 方法回复“true”后,我才会执行 Transfer。此逻辑在 Flex 应用程序代码中进行编程。

我所呈现的场景如下:如果有人下载应用程序并对其进行反编译怎么办。比修改代码,因此不执行步骤 EnougFunds。或者也许编写一个全新的客户端,甚至可能在其他技术中执行 Transfer 而无需通过 EnoughFunds 步骤。执行 Transfer 时,用户将在服务器上获得授权和身份验证;但由于他使用的是他的真实凭据,他将能够执行转移。他跳过的检查属于业务逻辑,而不是安全域。我需要以某种方式确保执行应用程序的代码是我编写和用户下载的未经修改的 Flex 代码。我怎样才能做到这一点?我知道我可以重写服务,以便在服务器上执行序列,

在我看来,必须有一些安全机制可以解决这个特定问题。

请注意,我不是在寻找有关最佳实践的建议。我的要求是不要更改服务器端的任何内容。如何在不更改服务的情况下保护协议级别的序列?

4

6 回答 6

17

这是一个大错误。必须在服务中检查任何重要到重要的业务规则。必须是这样的,无论客户端做什么,服务都不会让任何不好的事情发生。

特别是,进行 EnoughFunds 操作是有意义的,因为如果 EnoughFunds 返回 false,您可以告诉用户他没有足够的资金。但是,转账操作必须检查是否有足够的资金,而不是依赖客户进行如此重要的检查。

于 2009-02-24T17:34:51.283 回答
9

让我补充一点——我让孩子们反编译我的游戏并更改/编辑通过操纵 http 通信的工具来回发送的消息——这仅适用于没有外部价值的游戏。我的用户实际上加载了 fiddler 和 firefox 标头工具来操纵服务调用,只是为了在每天都会自行重置的游戏板上获得高分。

如果我把钱或“真正的”价值投入其中,我不禁想到会发生什么。

不要相信客户端发送给您的任何数据...使用“足够的资金”调用来更新您的用户界面,但是在执行“传输”阶段时,您需要纯粹在服务器端重新评估该调用 - 不要相信那只是因为客户要求转移,您应该接受它。

于 2009-02-24T17:41:22.920 回答
6

如果不更改服务器端,您将无法解决此问题,因为正如所有其他答案所指出的那样,这就是问题所在。此外,不会有不涉及更改服务器端的合适协议。

将其与银行柜台的人进行比较是非常合适的。该人已向银行员工提供了一些凭据,以验证她是谁以及她实际上拥有某个帐户 X。这就是登录。

现在这个人想要从账户 X 到 Y 的转账。无论她对可用资金说什么都无关紧要。如果她出示银行行长签署的文件说她有足够的资金,银行仍然需要在转账之前进行检查,因为钱必须在那里。

这意味着,即使您在协议中获得了一个安全的序列逻辑,以确保在“Transfer”之前调用了“EnoughFunds”,并且仅在不久前调用了一次,并且使用了正确的参数,它仍然是客户端告诉银行“没关系,我有足够的资金”。这永远不会削减它。

你能得到的最接近的情况相当于银行客户俯身在柜台上,指着员工的屏幕说“看,这里,在你的系统中,它说交易可以完成,因为有足够的资金”,即客户端可以可验证地重现服务器刚刚发出的对 EnoughFunds 的调用的时间、输入和输出,这没问题,但毫无意义。

所以解决方案是让 Transfer 在内部调用 EnoughFunds , period。如果客户需要知道,您可以返回描述性异常/错误以防资金不足。

就像这样。
(来源:userfriendly.org

于 2009-03-05T08:54:36.390 回答
5

老实说,我认为您需要认真重新评估您的发展计划。正如其他人在这里正确地指出的那样,您不能依赖客户的完整性。

简而言之,在您可以控制的环境(即服务器——即使那样,它还是有争议的)之外,没有“安全、受信任的代码”之类的东西。你不知道你实际上正在与之交谈的软件,所以无论你如何“调整”应用层协议,你仍然不能保证一个坏演员不会简单地用逆向工程的实现来欺骗你你的“调整”协议。

您的“信任域”仅扩展到 Web 服务 api,仅此而已。如果您的服务无法验证其操作的完整性,那么它就是设计不佳的服务。

于 2009-03-06T18:36:36.823 回答
1

我认为你应该考虑以下几点:

  • 防篡改 URL
  • 即将过期的网页
  • 将您的 EnoughFunds 和 Transfer 逻辑组合到一个调用中。正如 John Saunders 所说,无论如何,您必须在转移之前检查 EnoughFunds,因此检查一次更有意义。
于 2009-03-03T14:32:12.677 回答
0

首先,我同意其他答案——客户绝对是你的敌人,永远不应该被信任。还要扩展您放置的一些评论——即使“足够的资金”返回某种加密令牌,有什么保证它仍然没有被黑客以 10 的数量调用,并且随后的转移以 10000000 的数量被激活。

方法必须是将原子业务逻辑放在一起,例如“足够的资金和转移”。

我建议也为每个服务器调用添加一个序列,以便永远不会重新执行旧的服务器调用,因为它们现在不按顺序进行。服务器应将“下一个序列令牌”作为某种“加密”数字返回。这可以很简单,只需生成随机数并作为响应的一部分返回,同时也将其置于服务器会话中并在该客户端的任何后续调用中重新确认它。

同样,这个技巧不是一种安全措施,而是简单地试图帮助避免过于简单的“摆弄”情况。

这可以与混淆您的 API 结合使用。如果您以 Web 服务的名称来称呼它们(例如:EnoughFunds 服务将被这样称呼),逆向工程变得容易得多。相反,做一些像枚举服务这样简单的事情,然后通过中央控制器 - activateTask=12?param1=200 。不过,这仍然很容易进行逆向工程......如果您可以投资于完全加密每个请求,看起来会更好:SFASDFsdq1231sd4DFGTRsdf2rDF

当然,任何这样好的请求加密,都应该部分基于 session-id(又名:登录身份验证令牌,通常)

于 2009-03-01T19:16:50.077 回答