如何保护我的 API 端点

信息安全 Web应用程序
2021-09-08 12:40:37

我有一个用 nodejs 编写的 API,我有一个用 angularjs 编写的前端应用程序。我希望我的 API 只能通过我的前端应用程序调用,而不是从任何其他来源调用。

例如,我有一个名为 myhost.com/posts/id 的端点,当该方法被删除时,它会删除帖子。我不希望攻击者访问此端点并删除我的帖子。我该如何预防?

3个回答

不幸的是,我相信这是不可能的。让我解释一下为什么。

您希望您的前端应用程序能够向 API 标识自己。换句话说,您需要身份验证。

但是身份验证需要存在某种独特的、秘密的数据,前端应用程序可以使用这些数据将自己与其他应用程序区分开来。这可以是共享密钥(密码、“API 密钥”)、私有非对称加密密钥或其他内容。但无论它是什么,它都必须保密,因为如果另一个应用程序可以复制它,它就可以作为您的前端应用程序传递。

所以问题是,你要把这个秘密存储在哪里?

如果它存储在应用程序代码本身内部,或者可以直接访问它,那么无论您使用多少层加密间接来隐藏它,它都容易受到逆向工程或前端应用程序的攻击。这是导致迄今为止设计的几乎所有 DRM 方案失败的根本安全缺陷。

如果它存储在客户端机器的某个防篡改位置(例如 TPM 芯片、受信任的操作系统密钥管理工具),那么问题就变成了,它最初是如何到达那里的?你将如何从 Javascript 代码中访问它,它具有有限的低级操作系统访问能力?

如果它是远程存储的,那么您只是将应用程序身份验证问题转移到其他地方:您的前端应用程序将如何在远程服务器上进行身份验证?或者换句话说,是什么阻止了另一个应用程序以完全相同的方式访问该远程服务器?

我的结论是没有真正安全的方式来验证一个 JS 软件。您必须以一种不受恶意客户端输入影响的方式设计您的 API,如果您确实想要一种方法来禁止受感染的客户端,请为客户端提供可撤销的“API 密钥”,您可以轻松地在服务器端禁止,大多数 Web 服务(和较新的 DRM)的方式。

一个好的开始方法是防止从任何东西连接到 API 应用程序,除了有效的客户端地址,在你的情况下,你的 angularjs 服务器。

通过在每个 angularjs 实例和您的 API 之间实现可撤销的共享 API 密钥可以获得额外的安全性,因此您可以撤销受感染实例的权限。

此外,最好确认前端应用程序和 API 服务器之间的流量已加密,即使它仅在您的内部网络上也是如此。

如果您的前端可以使用 API,那么任何人都可以使用该 API。在这种情况下,你的前端/浏览器只是一个抽象层来调用你的 API,没有什么能阻止人们摆脱那个抽象层并自己调用 API。

你不能可靠地问“这个 API 调用是否来自我的前端”,因为任何人都可以在 API 调用中说它来自你的前端。

有人可能认为他们可以让 Web 服务器在您第一次打开页面时为您提供某种密钥,将密钥存储在浏览器中,然后在每次 API 调用时发送该密钥。但是,是什么阻止了某人从您的 Web 服务器获取该密钥,然后恶意使用 API 呢?如果浏览器可以请求密钥,那么任何人都可以请求密钥。

为了限制访问,您需要某种形式的授权。所以你的 API 必须说“这个想要删除帖子的人是否允许这样做?”。在这种情况下,API 调用来自何处并不重要,也应该无关紧要,只要调用此 API 的人具有这样做的正确授权即可。

一种方法是实现某种登录功能并在成功登录时让服务器检索唯一密钥。服务器应该以一种或另一种方式知道该密钥是由服务器提供给该用户的。您可以通过记住此密钥属于服务器上的该用户或使用 JSON Web 令牌之类的东西来做到这一点。理想情况下,您将使用某种库或框架来执行此身份验证。对于每个 API 调用,您都可以发送此密钥,服务器将知道您被允许执行此操作,无论您是单击右侧的前端按钮还是使用其他程序进行调用。