安全性不是一个你勾选之后就忘记的框。这是一种心态、一个持续的过程,也是每个开发人员所承担的责任。一个安全漏洞就可能造成数百万美元的损失,破坏用户多年来建立的信任,甚至摧毁公司。但安全不一定是令人生畏或令人瘫痪的。凭借正确的知识和既定实践,您可以构建强大的应用程序来保护您的用户。
现代威胁格局
近年来,网络安全世界发生了巨大变化。攻击者不再是黑暗地下室中的孤独黑客 - 他们是预算数百万的复杂犯罪组织、拥有无限资源的民族国家,以及 24/7 扫描互联网寻找漏洞的自动化机器人。
成功攻击的成本呈爆炸式增长。我们谈论的不仅仅是被盗数据。 GDPR 和 [LGPD2] 规定了巨额监管罚款,最高可达公司全球年收入的 4%。通知受影响用户、法证调查、系统修复以及受害者信用监控都会产生费用。声誉受损的代价是不可估量的——用户失去信任,再也不会回来。
但防守方面的情况也发生了变化。我们拥有更好的工具、更安全的默认框架以及消除整类漏洞的托管服务。云提供商在基础设施安全方面投资了数十亿美元。开源社区可以快速发现并修复漏洞。如果您利用这些工具并遵循最佳实践,您就有真正的机会领先于攻击者。
真正重要的漏洞
OWASP 发布定期更新的 10 个最严重 Web 漏洞列表。这个列表不是学术性的——它是基于真实的、成功的攻击,这些攻击让公司损失了金钱和数据。让我们探讨最重要的问题以及如何保护自己。
访问控制故障
这是排名第一的漏洞,原因很简单:它极其常见且具有破坏性。基本思想是用户可以访问他们不应该访问的资源。 Bob 可以看到 Alice 的命令。普通用户可以访问管理端点。客户可以通过向 URL 添加参数来修改产品价格。
这里的根本错误是依赖用户输入来做出安全决策。 “我要在 UI 中隐藏此管理按钮”并不安全 - 任何知道 URL 的人都可以访问它。 “我将在 URL 中放入连续的 ID”是对资源进行迭代的邀请。
防御从每个端点的权限检查开始。不仅在 UI 中,而且在后端,在每个敏感操作中。每个请求必须回答三个问题:谁提出这个请求?他们经过身份验证吗?他们是否被明确允许对该特定资源执行此操作?
使用**不可猜测的标识符
vel** 作为 UUID,而不是顺序 ID。实施最小权限策略 - 用户应仅拥有其角色所需的最低权限。并积极测试 - 尝试以另一个用户、未经身份验证的用户身份使用修改后的 ID 来访问资源。
密码缺陷
敏感数据由于没有得到充分保护而不断泄漏。这包括以明文或弱哈希存储的密码、未加密的信用卡数据、可预测的会话令牌、不受保护的数据库备份。
基本原则是对静态和传输中的敏感数据进行加密。 HTTPS (TLS) 对于公共互联网上的任何网站来说都不是可选的 - 现代浏览器甚至将 HTTP 网站标记为“不安全”。幸运的是,Let's Encrypt 提供免费的 TLS 证书。
对于静态数据,请使用强加密。用于对称数据的 AES-256。永远不要实现自己的[密码学4] - 使用完善且经过审计的库。特别是对于密码,请使用 专为密码设计的哈希算法,例如 bcrypt、scrypt 或 Argon2。这些都是故意缓慢的,使得即使使用现代硬件进行暴力攻击也是不切实际的。
密钥管理通常是薄弱环节。加密密钥不能硬编码到存储库中的代码或配置文件中。使用 AWS Secrets Manager、Google Secret Manager 或 [HashiCorp Vault5 等机密管理服务。定期轮换钥匙。制定撤销受损密钥的程序。
注射
SQL 注入仍然很普遍,因为它很容易被意外引入,并且在被利用时会造成破坏。但注入类别更广泛——它包括命令注入、LDAP注入、NoSQL注入、模板注入。
常见的模式是在没有适当清理的情况下信任用户输入,从而允许攻击者注入恶意命令。攻击者可以提取整个数据库、删除表、修改数据,甚至获得服务器的控制权。
主要防御是准备好的语句和参数化查询。您无需连接字符串来构建 SQL 查询,而是使用填充值的占位符。 [数据库7将这些值视为数据,而不是命令,使得注入变得不可能。
现代 ORM 如 Prisma、TypeORM 或 Sequelize 默认执行此操作,因此在大多数情况下使用这些框架已经可以保护您。但必要时您仍然需要小心原始查询。
严格的输入验证是另一道防线。如果您期望一个数字,请检查它是否确实是一个数字。如果您期望日期,请验证格式。如果您希望从预定义列表中进行选择,请检查该值是否在该列表中。切勿假设客户数据是安全的或格式良好的。
跨站脚本(XSS)
XSS 允许攻击者注入在受害者浏览器中运行的恶意 JavaScript。这可以窃取会话 cookie、修改页面内容、重定向到网络钓鱼站点或安装键盘记录程序。
主要分为三种类型:存储型 XSS(恶意脚本保存在[数据库8°中,并在每次页面加载时执行)、反射型 XSS(脚本来自 URL 参数并反射回响应中)和基于 DOM 的 XSS(漏洞位于客户端 JavaScript 中)。
防御从逃逸输出开始。当您将用户数据放入 HTML、JavaScript、CSS 或 URL 中时,必须针对该上下文适当地转义特殊字符。大多数情况下,像 React 这样的现代框架会自动执行此操作,但您仍然可以使用 0 或类似的方式引入 XSS。
内容安全策略 (CSP) 是强大的附加防线。它是一个 HTTP 标头,指定允许使用哪些脚本字体、样式、图像等。即使攻击者设法注入代码,CSP 也可以阻止其执行。从限制性政策开始,然后根据需要开放。
用于会话令牌的 仅 HTTP cookie 可防止 JavaScript 访问这些 cookie,从而减轻 XSS 的影响。如果攻击者无法窃取会话 cookie,则攻击的效果就会降低。
敏感数据的暴露
日志、错误消息、API 响应——这些都是敏感数据可能意外泄露的地方。生产中详细的堆栈跟踪可以揭示代码结构和依赖关系。 SQL 错误消息可能会暴露 [数据库9 的架构。如果您不小心,日志可能包含密码或令牌。
原则是假设您发送给客户端的所有内容都可以被攻击者看到。这意味着永远不要依赖“通过默默无闻实现安全”——隐藏信息,希望没有人会发现它。使用真正的[身份验证10和授权。
生产与开发中的不同错误消息是一个很好的实践。在开发过程中,您需要详细的堆栈跟踪以进行调试。在生产中,用户(和攻击者)应该看到诸如“发生意外错误”之类的通用消息。
仔细过滤日志至关重要。将记录器配置为不记录敏感字段,例如密码、令牌、信用卡号。使用屏蔽 - 例如,仅记录卡的最后 4 位数字。
强大的身份验证和授权
这些是您系统的守护者。身份验证验证身份(您是谁),授权验证权限(您可以做什么)。这里的错误是灾难性的。
密码和凭据
要求强密码是一个好的开始,但正确定义“强”很重要。诸如“每个字符必须有一种类型”之类的任意规则不如简单地要求 12-16 个字符的最小长度有效。长而好记的密码比用户写在便利贴上的复杂短密码更好。
永远不要以明文形式存储密码。使用适当的哈希算法。成本系数至少为 10 的 Bcrypt 是一个很好的标准。散列应该足够慢以使得暴力破解变得不切实际,但又不能慢到降低用户体验。
登录端点的速率限制可防止暴力攻击。尝试几次失败后,需要验证码或暂时阻止。使用指数退避 - 每次失败的尝试都会增加冷却时间。
多重身份验证 (MFA) 添加了关键的安全层。即使密码泄露,攻击者在没有第二个因素的情况下也无法访问该帐户。通过 Google Authenticator 或 Authy 等应用程序进行的 TOTP(时间码)非常好。 SMS 总比没有好,但容易受到 SIM 卡交换的影响。带有硬件密钥 (YubiKey) 的 WebAuthn 是黄金标准。
会话管理
会话令牌本质上是应用程序的密钥。如果攻击者窃取了有效令牌,他们就可以冒充用户。
会话令牌必须是真正随机的且不可预测。使用加密安全生成器,而不是1。令牌必须具有足够的熵 - 建议至少 128 位。
会话过期平衡便利性和安全性。如果令牌泄露,很长的会话就会存在风险。太短会让用户感到沮丧。考虑使用刷新令牌 - 短期访问令牌(15-30 分钟),可使用长期刷新令牌进行更新,但需要定期重新进行身份验证。
当用户注销或更改密码时,旧会话失效至关重要。在受害者意识到受到威胁后,攻击者不应该能够使用窃取的令牌。
OAuth 和 OpenID 连接
在大多数情况下,不要自己实施身份验证。使用 Auth0、AWS Cognito、Firebase Auth 或社交登录(Google、GitHub、Microsoft)等成熟的提供商。这些专业服务有整个团队致力于身份验证安全。
如果您绝对必须实施,请使用既定标准。 [OAuth122.0 用于授权,OpenID Connect 用于身份验证。不要发明自己的系统——这个领域充满了很容易被忽视的微妙陷阱。
PKCE(代码交换证明密钥) 即使在非公共应用程序中也应该使用,以防止授权代码拦截攻击。这是一个很小的开销,可以消除一类漏洞。
纵深防御
不要依赖单层保护。假设每一层都可能失败并实现多个独立层。
Web 应用程序防火墙 (WAF) 在恶意流量到达您的应用程序之前对其进行过滤。 Cloudflare、AWS WAF 或 Azure WAF 等服务可阻止已知的攻击特征
。它不能替代安全代码,但它是一个有价值的附加层。
速率限制和节流 防止 API 滥用。限制用户每分钟/小时可以发出的请求数量。这可以减轻 DDoS、暴力破解和攻击性抓取。
监控和警报检测可疑行为。一个IP多次登录失败?通常休眠的帐户出现异常活动?普通用户尝试访问管理端点?这些模式应该触发警报和调查。
事件响应计划确保您知道当(而不是如果)攻击发生时该怎么做。谁被通知?如何隔离系统?如何与用户沟通?如何从备份中恢复?拥有剧本可以大大缩短响应时间。
结论
网络安全是一个广阔且不断发展的领域。新的漏洞被发现,新的攻击模式出现,新的防御工具被创建。您永远不会知道一切,但您可以建立可靠的原则和流程,使您领先于大多数威胁。
从基础开始:[强大的身份验证、适当的访问控制、输入验证、转义输出、敏感数据加密。使用完善的框架和库,而不是重新发明轮子。使依赖项保持最新。定期测试。持续监控。
安全性不是您完成的一个项目,而是一种持续的实践,您可以将其融入到开发的各个方面。请以应有的严肃态度对待它,因为您的用户信任您处理他们的数据。
您如何处理项目的安全性?您处理过安全事件吗?分享您的经验!
另请阅读
- [Web 应用程序的安全14
- [Web 应用程序的安全性 - 公司架构15
- [网络应用程序的安全性:为初学者解释的架构16
- [网络应用程序的安全性:任何人都不能忽视的基础知识17
- [API安全18
- [API 安全:不让门敞开的基本步骤19
