功能正确 ≠ 安全:AI 生成代码中的安全边界问题

Published 2026-08-26 15:31 3519 words 18 min read

This post is not yet available in English. Showing the original.
安全见解:为什么需要代码审查,为什么 AI 代码不可信

本人极力反对网络攻击行为,本教程仅供学习使用,你不能也不应对未经授权的网站实施这些操作。

本人不对因阅读本文章导致的直接和间接损失负责。

你应当更加注重对破坏行为的防御,恶意破坏可能会被追究法律责任!

为了确保遵循不鼓励不诱导网络攻击的原则,本篇文章案例已进行脱敏处理。

生成式 AI 正在生成

过去,一个简单网站需要设计数据库、编写后端、处理前端交互。而现在,借助生成式 AI,一个开发者甚至可以在很短时间内生成一个完整项目。

AI 与互联网安全

前段时间 Twitter 上的新闻足以让我们知道 AI 在强化互联网安全方面的巨大作用。

总结下来就是:渗透测试、安全分析、即时响应、自主决策。

虽然看起来很美好,但是 AI 在互联网安全的负面作用也真实存在着。

AI 为什么容易生成存在安全问题的代码

AI 最大的问题不是不会写安全代码,而是不知道什么时候必须考虑安全。

经验丰富的工程师有时也会因为各种原因写出有问题的代码,但是工程师会考虑这个地方是不是应当有验证。

AI 进行输出时会主要根据当前的代码上下文和任务要求生成结果,因此在安全要求没有被明确提出,或者相关安全约束分散在上下文中的情况下,AI 无法保证始终满足这些安全约束。

安全往往不是某一行代码的问题,而是整个系统的设计缺陷。一个接口的调用会涉及到路由、中间件、身份认证组件、业务逻辑等多个模块。

随着项目逐渐发展,模块会更加复杂,各个组件的权限关系和边界条件也会越来越多,这就使得 AI 难以保持完全理解整个项目的安全结构。

此外,AI 生成代码时会受到训练数据中常见实现模式的影响。虽然无法简单认为某段生成代码来自某个具体训练样本,但公共代码中大量存在的低质量实现,会使一些不安全模式成为 AI 可能复用的方案之一。

例如,在没有明确安全要求时,模型可能生成简单密码校验、缺少权限验证的接口,或者直接复用包含敏感字段的数据模型。这并不是因为 AI 认为这些方案更安全,而是在当前上下文中,这些实现方式更符合常见代码模式。

因此,AI 并不是无法生成安全代码,而是无法保证在复杂项目中始终满足所有安全约束。这也是为什么 AI 生成代码仍然需要经过代码审查、安全测试以及人工验证。

这类问题并非 AI 独有,但 AI 生成代码降低了产生这类问题的成本,因此更需要自动化测试和人工审查。

以下案例取材于现实,这个网站使用 AI 编写。

1.到底有几个真人用户?

image
image
image
image

发生了什么?

这其实是搭建注册网站时较容易出现的一个问题——没有对注册 API 进行合适的防护。

大多数注册/登录 API 进行必要的防护措施,例如 reCaptcha 人机验证,关联更多有效且属于用户的信息,对 API 接口进行速率限制。

不过这里设计时可能没有过多考虑防护问题,所以只是采用了基于 IP 的速率限制,而众所周知单纯依赖 IP 速率限制不足以形成有效保护。

More IP = Boom!

如何解决

使用反自动化保护服务可以缓解(不能解决)这个问题。

方法优势劣势
人机验证(Captcha)工具通常无法执行验证代码。行为分析算法识别准确率高。人机验证对 AI 爬虫效果有限,免费版防护效果未必很好。
关联信息这样会提高攻击者的攻击成本。受限于法律法规,且容易导致用户流失,需要额外验证信息
检测设备指纹对基本爬虫的检测率较高,检测速度快误报率高,技术难度相对较大

2.2026 年了,还有人使用弱密码吗

image
image

发生了什么?

这是很多开发者(不仅仅是 AI)会犯的常见错误——使用弱密码/访问时设定密码。

坦白说这种其实不太适合现代 Web 应用程序,因为很不安全。

想象一下,我给你装了一把高安全性的电子门锁,但是我没改默认密码,而所有人都知道默认密码是 123456。

如何解决?

请时刻记住,站点绝对不能使用弱密码(特别是管理员账户),用弱密码的网站绝对不能公开。

(事实上,内部网络通常也不建议使用弱密码,因为需要考虑到内网渗透和横向移动的可能性。例如 2014 年的 JPMorgan Chase 数据泄露事件中,攻击者获取了 JPMorgan 的应用程序和程序列表,并利用其中的信息识别漏洞、取得网络入口,最终导致与超过 8300 万个账户相关的数据遭到泄露。)

  • 初始管理员密码应当具有足够的强度(大多数密码管理器生成的密码具有高熵特性,或者使用 CSPRNG + base64 也行),有条件的情况下也可以不设置密码,改用 Passkey 等无密码登录方式。

    • 同时还省的记密码了,一举多得
  • 此外强制 MFA 也是一个有效的做法。

    • 因为 MFA 认证通常需要多因素配合,在验证方式相对独立的情况下,每多一个认证因素,泄漏的可能性就越小。
    • 但是这种方式对凭据的独立性要求相当的高,例如使用邮箱验证码和密码作为双因素认证,如果密码是通过邮件验证码找回的,那么实际上是单因素。
    • 不过这也对凭据管理带来了新的挑战,因为凭据要求的越多丢失的可能性就越大,如果你丢凭据的数量多到低于认证的最低限度,你就会被 lock out。

对于高安全性网络,还应当做到访问可审计,登录可溯源。高机密设备应当与外部互联网实现物理隔绝。

不过大多数个人网站用不到这个场景,这种手段常见于金融、国防、涉及身份信息和企业服务等需要高保密的企业(例如腾讯、阿里、华为)

3.给我看一眼嘛

{
      "id": "6279607e-202c-4713-afb4-547e07cd9775",
      "name": "晓月OwO5g3tm",
      "grade": "九年级",
      "class_name": "九年级7班",
      "student_no": "",
      "gender": "male",
      "is_anonymous": 0,
      "created_at": "2026-08-26T14:12:55.827932",
      "total_stars": 7,
      "visit_count": 4,
      "homework_count": 6,
      "has_schedule": true,
      "pe_count": 2,
      "has_resolution": true,
      "has_final": true,
      "star_keys": [
        "final",
        "homework",
        "map",
        "pe",
        "resolution",
        "schedule",
        "study"
      ],
      "game_count": 15
}
    

发生了什么?

这里产生了一个 BAC 问题,通俗易懂的说法就是你把门锁拆了。

(Broken Access Control,访问控制失效。这里缺少对用户身份和权限的验证,导致攻击者可以获取原本没有访问权限的数据)

如何解决?

与用户强相关的接口应当使用合适的凭据和验证,并进行权限验证。

(对于桌面应用程序通常是 Authorization 传递令牌,浏览器则以 Cookie 为主)。

如果网站所有者有过测试或者做过 Code Review,这个问题可能就不会发生。

再问 Req Change

因此解决方法就是针对使用情况做黑盒测试 + 代码审查。

对于复杂项目,有时只靠人力并不能完美察觉出潜在的逻辑漏洞,此时使用专业的代码分析工具(SAST 和 SCA 类工具)可以更快的找出容易被忽略的漏洞。

4.Hash 不是可以公开的理由

以下数据均为虚构或经过脱敏处理,仅用于说明安全问题,不对应任何真实用户

/api/teacher/student/{student_id} 可以直接访问。

{
  "student": {
    "id": "6279607e-202c-4713-afb4-547e07cd9775",
    "name": "晓月OwO5g3tm",
    "grade": "九年级",
    "class_name": "九年级7班",
    "student_no": "",
    "gender": "male",
    "is_anonymous": 0,
    "password_hash": "4323f8aab7b8ee17c33854ed062fbce2895f35bea81b5c41f11ff5bbbcf02ed9",
    "created_at": "2026-08-26T14:12:55.827932",
    "total_stars": 7
  }
}

SHA-256 并不是保护密码的理想选择,在大多数情况下使用应当使用 Argon2id、scrypt、bcrypt 慢 Hash 并加盐进行处理。

务必记住,“Hash”不是“不可逆加密”,只是让离线猜测成本足够高。

敏感信息不应该暴露,因为攻击者不应该获得进行离线攻击所需的材料

发生了什么?

历史上 OWASP API Security Top 10 将这一类问题称为 Excessive Data Exposure,现在需要结合 BOLA 辅助理解问题。

打个比方就是我问你家庭住址在哪,你把身份证给我看。

虽然我确实知道了你的住址,但是我也知道了你的身份证证件号。

如何解决?

  • 首先,铭记一个原则:密码无论有没有加盐绝对不能公开到 API 响应,有没有登录都不行。

  • 其次 Code Review 同样可以低成本、及时的发现问题,所以这一定是重点执行的对象。

  • 对于 API 响应不应当复用 CRUD 代码的模型。如果你坚持复用,请确保在响应时移除不必要的字段。

    • (部分 JSON 库可能支持通过注解或访问等级来决定是否序列化某些字段)
  • 如果有条件也使用 Passkey 等更安全的方式。

  • 此外,服务端不应当存储密码原文,而是应当存储 Hash 结果,这样即使服务器被入侵黑客也不能轻易拿到用户凭据(但是密码本身得足够强)。

5.永远不要相信客户端输入

/api/dbg 和 /api/dbg/list 均可无认证访问,并且 /api/dbg 可以以任意速率提交未经业务约束的 JSON 数据。

发生了什么?

这也是典型的 BAC 问题。

不过相较于案例 3,这里还有一些风险点。

没有 RCE 不代表没有风险,RCE 只是众多网络安全风险中较为严重的一种。

1.没有约束业务模型

提交任意 JSON 本身不会有什么问题,主要在于服务器怎么解释这些数据,以及调用路径上是否有组件存在可利用的漏洞。

2.没有请求速率限制

虽然前文提到了基于 IP 的速率限制对网站防护作用有限,但是对于刷量效果较为显著。

另外,此接口没有进行速率限制,在大量请求的情况下容易形成 DoS (Denial of Service,拒绝服务)攻击。

如何解决

  • API 应当使用合适的鉴权方式,例如 User AccessToken。

  • 此外也可以在 WAF 上设置规则限制请求速率避免资源浪费。

  • 针对 RCE 漏洞,请始终确保库更新到最新版本并确保涉及到的调研路径上实现逻辑正确。

  • 使用强类型的验证库可以在格式错误的情况下返回 HTTP 错误,不过请务必记住不要在 Response 说废话(指调用栈和上下文信息,一般来说只返回 400 Bad Request 就足够了)。

功能正确与安全正确不是同一个维度

一个 API 能正确返回数据,只能证明它实现了预期功能;不能证明调用者有权访问这些数据,也不能证明返回的数据都是应该公开的数据,更不能证明它能够抵御异常输入和高频请求。

小结

从这些案例可以看到,AI 生成代码的问题并不在于它完全不会编写安全代码。恰恰相反,在明确的安全要求和完善的上下文下,AI 同样能够生成相对完善的安全实现。

真正的问题在于功能正确≠功能安全,AI 可以根据上下文推导出实现方案,并迅速写出功能完整的实现。但是安全性涉及到更广泛的方面:身份认证、权限控制、速率限制、输入验证。这些要求并不是总会出现在任务需求或者可以通过局部代码自动推导。

当训练数据存在大量低质量不安全的实现时,AI 很可能套用这些模式。复杂的项目也会显著增加模型遗漏安全约束的可能性。

因此,我们可以说 AI 是一个高效的代码生成工具,但不是安全的保证人。

软件工程中最危险的情况,不是代码无法运行,而是代码运行正常,却没有任何人验证它是否应该这样运行。

对于 AI 生产的代码,不能因为功能正确就放弃代码审查、单元测试、边界验证。

我们真正需要警惕的并不是“AI 会不会写出漏洞”,而是人是否会因为 AI 写出的代码看起来正确,而放弃本应进行的安全审查。

If you enjoyed this, leave a comment~