Web 应用程序开发安全最佳实践

身份验证

使用经过良好审核的身份验证服务和客户端 IC 库

安全问题

在您的 Web 应用程序中自己实施用户身份验证和容器调用容易出错且存在风险。 例如,如果容器调用是从头开始实现的,则可能存在围绕签名创建或验证的错误。

推荐

  • 考虑使用例如 Internet Identity 进行身份验证,使用agent-js 进行容器调用,以及 auth-client 用于与您的 dApp 中的互联网身份进行交互。

  • 当然,考虑在 IC 上使用替代认证框架进行认证也是一种选择。

设置适当的会话超时

安全问题

目前,互联网身份向授权发出到期时间。 这个过期时间可以设置auth-client。 委托到期后,用户必须重新进行身份验证。 设置一个好的值是安全性和可用性之间的权衡。

推荐

OWASP Recommendations。 应为安全敏感的应用程序设置 30 分钟的超时。

注意:空闲超时可能很快就会引入,请参见this

不要在生产环境中的 agent-js 中使用 fetchRootKey

安全问题

agent.fetchRootKey() 可以使用agent-js 从测试环境中的状态调用中​​获取根子网阈值公钥。此密钥用于验证通过容器更新调用接收的认证数据的阈值签名。在生产 Web 应用程序中使用此方法使攻击者可以选择提供自己的公钥,从而使更新响应的所有真实性保证无效。

推荐

切勿在生产版本中使用 agent.fetchRootKey(),仅在测试版本中使用。不调用此方法将导致主网的硬编码根子网公钥用于签名验证,这是生产中的预期行为。

非特定于 Internet 计算机

本节中的最佳实践非常笼统,并不特定于互联网计算机。此列表绝不是完整的,仅列出了过去导致问题的一些非常具体的问题。

在前端验证输入

安全问题

对来自不受信任来源(例如用户)的数据的输入验证缺失可能会导致格式错误的数据被持久化并返回给用户。这可能会导致 DoS、注入攻击、网络钓鱼等。

推荐

不要从不受信任的域加载 JavaScript(和其他资产)

安全问题

<canister-id>.ic0.app 以外的域加载不受信任的 JavaScript 意味着您完全信任该域。此外,从这些域加载的资产(包括`<canister-id>.raw.ic0.app`)将不使用资产认证。

如果他们提供恶意 JavaScript,他们可以接管网络应用程序/帐户,例如从 LocalStorage 读取由 agent-js 管理的私钥。

请注意,从不受信任的域中加载其他资产(例如 CSS)也存在安全风险,请参见例如这里

推荐

  • 应避免从其他来源加载 JavaScript 和其他资产。特别是对于安全关键应用程序,我们不能假设其他域是值得信赖的。

  • 确保交付给浏览器的所有内容都由容器使用资产认证提供和认证。这尤其适用于任何 JavaScript,也适用于字体、CSS 等。

  • 使用Content Security Policy 来防止脚本和其他来源的其他内容被加载。另请参阅定义安全标头,包括内容安全策略 (CSP)

定义安全标头,包括内容安全策略 (CSP)

安全问题

安全标头可用于涵盖许多安全问题,例如禁止clickjackingharden TLS,确保无法在浏览器中执行来自不受信任域的JavaScript或其他内容等不配置这些适当的标头可能会导致具体的安全问题和缺少深度防御。

推荐

Crypto:使用 Web Crypto API 保护密钥材料免受 XSS

安全问题

在浏览器存储中存储密钥材料(例如sessionStoragelocalStorage) 被认为是不安全的,因为这些密钥可以被 JavaScript 代码访问。这可能通过 XSS 攻击或从其他域加载不受信任的脚本时发生(另请参阅 link:web-app-development-security-best-practices.adoc#dont-load-untrusted-content [不要从不受信任的域加载 JavaScript ]。

推荐

使用WebCrypto API 通过在 generateKey 中使用 extractable=false 来隐藏 JavaScript 中的密钥材料,请参阅this。可以在人员聚会项目中找到一个示例,请参见这里 .这使得无法从 JavaScript 访问私钥。

使用安全的网络框架

安全问题

现代 Web 框架使诸如 XSS 之类的攻击变得非常困难,因为它们可以安全地逃避/清理网页上呈现的任何潜在用户提供的数据。不使用这样的框架是有风险的,因为很难避免像 XSS 这样的攻击。

推荐

  • 使用具有安全模板机制的 Web 框架,例如Svelte 以避免 XSS。这用于例如在 [NNS dApp] 项目中。

  • 不要使用框架的不安全功能,例如@html in Svelte

确保注销有效

安全问题

如果用户的注销操作无效,这可能会导致帐户接管,例如如果使用共享或公共设备。

推荐

  • 清除所有会话数据(特别是sessionStoragelocalStorage),清除IndexedDB等注销。

  • 如果在一个选项卡中触发注销,请确保其他显示相同来源的浏览器选项卡也被注销。这不会在使用 agent-js 时自动发生,因为 agent-js 在初始化后会将私钥保存在内存中。

使用提示警告用户任何安全关键操作,让用户明确确认

安全问题

如果不是这种情况,用户可能会不小心执行一些敏感操作。

推荐

  • 向用户显示带有安全警告的提示,描述操作的确切后果,并让他们明确确认。

  • 对于安全性要求高的应用程序,考虑使用事务批准,即使用例如一个 WebAuthn 设备,让用户确认某些关键操作或交易。这是推荐的,例如涉及代币或循环(燃料费)转账时。例如,使用硬件钱包NNS dApp 实现了这一点。