跳到正文
>_ITDITDWeb 安全平台

安全指南

4 种常见的安全错误:默认设置、遗忘的服务、缺少监控、过度信任输入校验

真实的安全事故很少涉及高深的攻击。按背后的假设来归类,原因可以归结为四种想法——每一种都曾经是对的,所以没有人重新审视。

发布于 2026-09-05 更新于 2026-10-04 最后核实 2026-09-05 3 分钟阅读

把实际发生的事故排在一起看,高深的攻击手法几乎不出现。出现的是少数几种反复出现的模式,而这些模式不按技术、而按背后的假设来归类时最清楚。

① 认为默认值是安全的(什么都没设置)

为方便开发而选的默认值

详细的错误信息 · 管理界面可访问 · 宽泛的权限

↓ 原样上线

向任何来看的人展示内部细节

结构、路径、版本和内部值都能被读到

默认值是对所有人都不至于出问题的值——而不是对你的生产环境安全的值。
这种模式的样子,以及要检查什么
生产环境开着调试输出
错误页面是否暴露了环境变量、文件路径或堆栈跟踪?打开一个不存在的 URL,亲眼看看返回了什么。各框架的具体情况见框架指南
管理界面可以访问
数据库管理工具和管理后台能从互联网访问。不要只依赖认证——叠加 IP 限制或网络层的拦截
安全头未设置,或照抄过时的清单
见哪些安全头仍然重要、哪些已经不重要。已废弃的安全头,加上反而可能有害
保留了薄弱的存储方式
密码的存储方式见哈希与加盐。「已经加密了」并不是对存储方式的说明
更新已经停止
在支持期结束后继续运行某个语言、框架或 CMS。见用机器监控依赖包和支持结束实际意味着什么

② 认为不用的东西无害(什么都没关闭)

**你的攻击面,更多来自你不再使用的东西,而不是你构建的东西。**一样东西一旦不再使用,就会在不知不觉中脱离监控和审查。

这种模式的样子,以及要检查什么
密钥留在公开目录里
.env、备份、导出文件、配置文件。绝不能放在公开目录里的东西/共享主机上的放置位置
存储仍然是公开的
开启阻止并不会删除现有的公开策略。公开的存储桶
悬空的 DNS 记录
删除了资源却没删 DNS 记录,任何人都可以认领这个名字、接管子域名。子域名接管
注册和管理路径仍然开着
开放注册是否仍然启用?通过 HTTP 实测,而不是看配置(认证与授权的区别)。不要让一个可被猜到的 URL 成为「隐藏」某个页面的唯一手段
以为已经注销的账号
解约服务和删除账号是两回事,在你删除之前数据一直保留。当你的主机服务商被入侵时
旧的密钥、令牌和权限
离职同事的账号、没有有效期的令牌、过宽的权限范围。SSH 密钥与最小权限/密码管理器

不要把清点范围限定在正在运行的东西上

如果只审查「目前在用的东西」,这种模式根本找不出来。范围要覆盖你曾经创建过的一切——子域名、账号、密钥、存储桶、预发布环境、第三方订阅。不再使用的东西,在删除之前仍然是资产。如何建立清单:资产清点检查表。

③ 认为出事了会发现(没有监控)

损害的大小,与其说取决于入侵本身,不如说取决于它在被发现之前持续了多久。而大多数环境根本没有发现问题的机制。

常见的状态

・有访问日志,但没有人看
・没有认证尝试的审计日志(所以事后无法还原「哪些东西被看到了」)
・配置了速率限制,但没人能看到它何时触发
・是否公开由几层设置组合决定,单看任何一层都得不出答案

最终只能对是否发生过什么回答「不知道」。

值得具备的最低限度

・新用户注册时发通知(一个信号就足以发现异常的那一个)
・记录认证的成功和失败,并设定保留期限
・用机器监控依赖包漏洞(人跟不上 → osv-scanner)
・记录触发限制的情况,并在激增时告警(速率限制与滥用防护)

不需要全部都有。一个真正能用的发现问题的手段,就能防止事故拖成长期事件。

没有日志时,诚实的回答是「不知道」,而不是「什么都没发生」

事件响应中最危险的做法,是把没有记录当作什么都没发生的证据。没有记录时,唯一站得住的说法是「不知道」——这种情况下,要按已被入侵的前提行动,把可能暴露的东西都轮换掉。组织层面的最低要求见组织安全基线。

④ 认为校验过的输入是安全的

关于输入,真正的问题不是「这个值对不对」,而是「我让这个输入决定了多少事情」。交出去的决定越多,校验就越跟不上。

按交给外部的决定来归类
只有值
普通的输入。长度、格式、范围的检查都有效——安全的一侧
连结构也交出去
接收整个嵌套对象并合并的设计。原型污染
连类型也交出去
会重建对象的格式。攻击在你的值检查运行之前就已经成功。不安全的反序列化
放到哪里
上传的文件最终落在可以被执行的位置。文件上传漏洞
请求来自谁
信任请求头来判断客户端的身份。X-Forwarded-For 伪造与可信代理

数一数你交出去的决定,就能看出危险的地方。而根本原因通常是同一个:想用校验去解决本该用结构解决的问题。改变你接受的格式,比再加一项检查更可靠。

按顺序来做

1

看看生产环境实际呈现的样子(①)

不存在的 URL、会出错的请求、管理路径——通过 HTTP 请求它们,看返回了什么。重点是看输出,而不是看配置。安全头可以用安全头检测工具一次测完。

2

写下你曾经创建过的一切(②)

子域名、账号、密钥、存储桶、第三方服务。诀窍是不要按「是否仍在运行」来筛选。用资产清点检查表建立清单,不用的条目要一直处理到删除(而不只是停用)。

3

只建立一个发现问题的手段(③)

想一次搭好完整的监控,结果往往是什么都没有。从一个开始——新注册通知、登录失败激增,或依赖包漏洞邮件。只做一个,并确认它真的会触发(配置了却从未验证的监控,等于没有监控)。

4

数一数你的输入能决定什么(④)

写出外部数据决定的是只有值,还是还包括结构、类型和存放位置。凡是决定了值以外东西的地方,都是应优先修改的地方。

5

把更新做成机制(让 ① 不再回来)

第一种模式放着不管一定会回来。把依赖包和框架的更新交给机器监控,是唯一现实的答案(osv-scanner 入门/实用的 CVE 修复手册)。只存在于文档里的流程,忙的时候最先被跳过。

本站的观点:四种想法都曾经是对的

四者的共同点是每一种在某个时候都是正确的。开发期间默认值是合理的;不用的东西当时确实没在用;规模小的时候你确实会发现;输入校验也确实解决过很多问题。正因如此,它们才一直不被审视。

我们的立场是定期问一问:一个曾经正确的假设,是从什么时候开始不再正确的。这种检查比增加更多技术更便宜、更有效。还要注意两者性质上的不同:检查表告诉你该做什么,却不告诉你为什么会遗漏——如果原因没变,同样的东西还会在同样的地方被遗漏。

接下来阅读

FAQ

Q安全工作应该从哪里开始?
A

检查自己的环境符合四种模式中的哪几种,比学习单个攻击手法更快见效。生产环境的设置是否还是默认值?是否有你创建后从未关闭、仍然开着的东西?出了问题你能发现吗?你让外部输入决定了多少事情?本文给出了每一项的具体检查方法,并链接到更深入的文章。

Q小型个人网站也适用吗?
A

模式相同,只是优先顺序不同。对个人或小团队来说,最先见效的两项是检查默认值(生产环境是否开着调试输出?)和清点从未关闭的东西(公开目录里的密钥、不用的子域名、闲置的账号)。可观察性需要一些机制,可以稍后再做——但哪怕只有一个信号,比如新用户注册时发通知,也能大幅缩短问题未被发现的时间。

Q这和检查表有什么不同?
A

检查表告诉你该做什么;本文讲的是为什么会遗漏。如果遗漏的原因没有改变,光列出项目也没有用——同样的东西还会在同样的地方被遗漏。四种想法都曾经是对的,所以它们才会一直不被审视。需要具体步骤时,请从各节的链接进入检查表文章。

Q我只有时间做一件事,该做哪件?
A

在第三项(能够发现问题)上做好一件事。前两项放着不管会变成事故,但没有第三项,你连事故发生了都不知道。损害的大小,与其说取决于入侵本身,不如说取决于它在未被发现的情况下持续了多久。保留日志、加一个通知、每月做一次清点:其中任何一项,都是防止事故拖成长期事件的回报最高的投入。