三年前,我见证了一家我曾咨询的初创公司在72小时内失去了一切。并不是因为复杂的国家级攻击或某个引发头条新闻的零日漏洞。他们失去了整个客户数据库、声誉,最终失去了业务,只因为一名初级开发者在匆忙的星期五部署中引入的一个SQL注入漏洞。攻击发生在星期一早晨。到星期三下午,他们已经在起草破产文件。
💡 关键要点
- 捕获每一个人的认证陷阱
- 跨站脚本攻击:永不消亡的漏洞
- SQL注入:仍然有效的古老漏洞
- HTTPS已不再是可选项
我是Sarah Chen,过去12年我一直担任安全架构师,服务于从小型初创公司到财富500强企业的各种公司。我看到同样可以避免的错误一次又一次地摧毁了企业。令人沮丧的是,这些灾难中的大多数都可以通过基本的安全知识避免,而这些知识的学习时间甚至少于您掌握的普通JavaScript框架。
当你学习编程时,没有人告诉你:安全并不是一个在掌握其他一切之后才能处理的高级主题。它是基础。就像在不理解红灯意味着停车的情况下学习驾驶。你可能在一段时间内没有出事,但最终,你将导致一次灾难性的事故。
根据2023年Verizon数据泄露调查报告,74%的泄露事件涉及人为因素,包括错误、滥用或社会工程。但这里有个问题:当他们特别分析Web应用程序攻击时,发现86%利用了超过十年前就已被记录和可预防的漏洞。我们不是在输给复杂的攻击者,而是在输给自己对基础知识的无知。
捕获每一个人的认证陷阱
让我告诉你关于认证的事,因为这是我看到开发者犯下的第一重大错误。他们将其视为一个复选框特性,而不是整个安全模型的基础。我曾审查过一段代码,开发者通过检查用户的电子邮件是否存在于Cookie中来实现认证。不是签名的Cookie,也不是加密的令牌。只是一个普通文本的电子邮件地址,任何人都可以在浏览器的开发者工具中修改。
当我指出这一点时,开发者说,“但它有效!”这正是问题所在。安全漏洞不会通过错误消息自行宣布。它们在被利用之前工作得很好。
正确的认证实际上需要什么。首先,您需要理解认证(证明你是谁)和授权(证明你被允许做什么)之间的区别。我见过生产系统中,这些概念混淆到修复一个安全问题会产生三个新问题。
密码存储是不可协商的。您必须使用像bcrypt、scrypt或Argon2这样的合适密码哈希算法。不是SHA-256。不是MD5。绝对不是明文。我在2026年仍然遇到数据库中密码以明文存储的情况,每一次,开发者都会告诉我他们“没想到会有人真正试图破解。”这就像把前门锁不上,因为你认为不会有人真的会偷你。
这里的数据非常明确。根据2023年身份盗窃资源中心报告,美国发生了3205起数据泄露,影响超过3.53亿受害者。当研究人员分析泄露的数据时,他们发现,在披露密码存储方法的情况下,43%使用的哈希方法不充分或根本没有哈希。
会话管理是事情变得有趣的地方。您需要生成密码学上安全的随机会话令牌。大多数语言内置的随机数生成器并不是密码学上安全的。在Node.js中,您希望使用crypto.randomBytes(),而不是Math.random()。在Python中,您希望使用secrets.token_hex(),而不是random.random()。我见过会话令牌是通过将时间戳和用户ID连接在一起来生成的。攻击者可以在几秒钟内预测这些。
您的会话令牌应该至少具有128位的熵。它们只能通过HTTPS传输。它们应设置HttpOnly标志,以便JavaScript无法访问。它们应设置Secure标志,以便永远不通过未加密的连接发送。它们应设置SameSite属性以防止CSRF攻击。而且它们应该过期。我建议在敏感应用中设置30分钟的不活动时间,可能在较低风险的情况下设置24小时。
跨站脚本攻击:永不消亡的漏洞
XSS攻击就像蟑螂。它们存在了很久,大家都知道它们,但它们仍然不断出现于生产代码中。自2003年创立以来,OWASP前10名已将XSS漏洞纳入其中,到2026年仍在。这是21年中同样可以预防的漏洞。
“安全并不是一个在掌握其他一切之后才能处理的高级主题。它是基础。就像在不理解红灯意味着停车的情况下学习驾驶。”
我记得审核一个医疗应用程序,该程序显示医生输入的患者笔记。开发者构建了一个允许基本格式化的富文本编辑器。听起来合理,对吧?除了他们将该HTML输入直接呈现在页面上而没有任何消毒。我通过输入一个包含script标签的患者笔记来演示漏洞。该脚本可以窃取会话令牌、修改病历或外泄患者数据。开发者们感到震惊。他们从未考虑过医生可能会恶意,或者医生受损的计算机可能会注入恶意代码。
这里有一个基本原则:永远不要信任用户输入。永远不。无论是来自医生、管理员,还是你的CEO。来自您应用程序外部的每一条数据在被证明无害之前都是潜在的恶意。
您需要了解三种类型的XSS。存储型XSS是指恶意代码保存在您的数据库中,并且每次有人查看该数据时都会执行。反射型XSS是指URL参数中的恶意代码立即被反射到响应中。基于DOM的XSS是指客户端JavaScript接收用户输入并在没有适当消毒的情况下将其插入页面。
解决方案并不复杂,但需要自律。您需要根据上下文转义输出。如果您将数据插入HTML内容中,则需要HTML实体编码。如果您将数据插入JavaScript字符串中,则需要JavaScript转义。如果您将数据插入URL中,则需要URL编码。如果您将数据插入CSS中,则需要CSS转义。
现代框架对此有所帮助。React、Vue 和 Angular 默认都会转义输出。但它们不是魔法。如果您在React中使用dangerouslySetInnerHTML或在Vue中使用v-html,则绕过了这些保护。我见过开发者使用这些功能,因为他们“需要”呈现HTML,而并不理解他们正在打开一个XSS漏洞。
内容安全政策是您的第二道防线。CSP是一个HTTP头,告诉浏览器哪些内容来源是合法的。您可以完全阻止内联脚本,限制哪个域可以加载JavaScript,并防止整类XSS攻击。根据Google的研究,实施严格的CSP可以防止大约95%的XSS攻击。然而,在我经历的审计中,少于30%的应用程序有任何CSP,并且其中大多数是如此宽松,以至于几乎无用。
SQL注入:仍然有效的古老漏洞
SQL注入应该已经绝迹。自1990年代以来,这一点已经得到充分理解。Bobby Tables已经成为了一个流行语超过十年。然而,根据Akamai的2023年互联网状态报告,SQL注入尝试占所有Web应用程序攻击的65%。为什么?因为它仍然有效。
| 漏洞类型 | 风险等级 | 预防难度 | 常见原因 |
|---|---|---|---|
| SQL注入 | 严重 | 简单 | 查询中的未消毒用户输入 |
| 弱认证 | 严重 | 简单 | 糟糕的密码策略,没有多因素认证 |
| XSS(跨站脚本攻击) | 高 | 中等 | HTML中的未转义用户内容 |
| 访问控制破坏 | 高 | 中等 | 缺少授权检查 |
| 安全配置错误 | 中 | 简单 | 默认设置,暴露的端点 |
我曾经为一家经营了八年的电子商务公司提供咨询。他们处理了数百万笔交易。拥有15人的开发团队。但是他们的搜索功能容易受到SQL注入攻击。代码看起来像这样:他们从URL参数中获取搜索词,并直接连接到SQL查询中。没有参数化。没有输入验证。什么都没有。
当我展示出漏洞时,