每到演练季临近,写业务代码的同事总会跑来问同一类问题:这事儿跟我有关系吗?我一个写 CRUD 的,能做点什么?说实话,几年前我也这么想,觉得护网行动是安全部门的事,是那些天天盯着流量图、手里握着态势感知平台的人该操心的。直到有一年,我们一个自己人写的接口被当成突破口,凌晨两点被叫起来改代码,我才彻底明白:网络安全这件事,防守方的短板往往不在安全团队,而在每一个写代码的人手里。这本手册就是把这些年踩过的坑、做过的整改、写过的检查单整理出来,做成一份给普通程序员的实战参考。
它不讲高深的理论,也不要求你懂逆向和流量分析。它讲的是:演练期间一个普通开发者到底要做什么、按什么顺序做、做到什么程度算合格。适合刚入行一两年的后端、前端、测试和初级运维,也适合那些年年参与、但每次都是被动接活、没系统梳理过一遍的人。整套内容我会按照“资产梳理 → 风险收敛 → 代码自查 → 监控告警 → 应急处置”这条主线展开,每一段都给出可以直接照抄的清单和参数。
1. 先搞懂演练的评分逻辑,再谈技术动作
很多人一上来就想着装个扫描器、跑一遍工具,这属于典型的“先拿锤子找钉子”。演练不是考试,它有一套很明确的评分导向:看你有没有被打穿、打穿了多久被发现、被发现后多久止住。理解了这个,你的所有技术动作才有取舍依据。
1.1 演练到底在考什么
防守方的分数大致由三块构成:失分项(系统被拿下、数据被拿走、权限被维持)、发现分(你能不能在对方动作的早期感知到)、处置分(从发现到止损的用时)。这三块里,失分项权重最高,也最容易失控,因为它取决于你资产里的短板有多短。
我见过太多团队把 90% 的精力花在“买设备、接平台”上,结果一台测试服务器上跑着三个月前的老版本组件,端口直接对公网开着,日志还没开。这种情况下,平台再贵也救不了你。所以有一个很朴素的判断标准:任何一个能被公网直接访问、版本落后、口令简单、日志缺失的东西,都算高危。这个判断不需要任何工具,靠人肉过一遍就能砍掉一大半风险。
还有一点容易被忽略:演练考的往往不是“最高深的那条路径”,而是“最省事的那条路径”。对方也在算成本,一个默认口令能进的后台,没人会去啃你的加密算法。这意味着基础工作的收益远高于炫技。
1.2 小白程序员在其中的真实位置
一个普通开发在演练里通常承担三类角色:资产责任人(你负责的系统你最清楚)、代码责任人(你写的接口你最清楚)、第一响应人(半夜出事第一个被叫起来的人)。这三类角色都不需要你成为安全专家,但都需要你对自己那摊东西心里有数。
最尴尬的情况是:安全部门拉了一张资产表下来让你确认,你看了半天说“这个 IP 我不认识”。这不是你的错,是流程的错——但演练期间没人有时间追责流程,你就是得把它认下来。所以我一直建议,在演练开始前两周,把自己名下的服务、域名、端口、依赖组件、数据表列一张清单,哪怕很粗糙,也比临时抓瞎强。
顺带说一句,别把“我不懂安全”当挡箭牌。防守这件事,八成的有效性来自“知道自己有什么、知道它什么版本、知道谁能访问它”,这些恰恰是开发最该知道的。
1.3 一条能落地的防守时间轴
我把整个周期拆成四个阶段,每个阶段的目标明确、动作有限,不至于让人无从下手:
| 阶段 | 时间点 | 核心目标 | 关键动作 |
|---|---|---|---|
| 备查期 | 演练前 30 到 15 天 | 摸清家底 | 资产台账、依赖清单、账号梳理 |
| 收敛期 | 演练前 15 到 3 天 | 砍掉明显短板 | 弱口令整改、版本升级、暴露面关闭 |
| 值守期 | 演练进行中 | 早发现、快处置 | 告警盯守、日志巡查、应急值班 |
| 复盘期 | 演练结束后一周 | 把临时措施变成长效机制 | 时间线还原、根因分析、整改闭环 |
这张表的价值在于:备查期做不完的事,不要在值守期硬补。值守期改代码是大忌,一来容易改出新问题,二来出了问题没人敢背。备查期该完成的整改,宁可提前一周完成,也不要卡在最后一天。
2. 资产梳理:所有防守动作的地基
我常说一句话:资产不清,一切归零。你连自己有多少个对外域名都不知道,谈什么防护?资产梳理听着枯燥,但它是投入产出比最高的一件事,没有之一。做完这一遍,你会发现至少三五个“原来这东西还开着”的惊喜。
2.1 为什么必须先做资产清单而不是先扫漏洞
漏洞扫描的前提是“扫的对象是对的”。如果清单里漏了一个域名,那这个域名上的漏洞你永远扫不到;如果清单里混了一堆已经下线的 IP,那你会花大量时间在噪声上。更麻烦的是,扫描器对不熟悉的资产经常误报,你需要人工确认,而确认的前提还是“我知道这是什么”。
我的做法是自下而上和自上而下交叉验证:自下而上,从代码仓库、发布平台、容器编排配置里把服务名和端口捞出来;自上而下,从域名解析记录、负载均衡配置、机房出口流量里把对外暴露的东西拉出来。两边对不上的部分,就是你最该关注的“影子资产”。
还有一个更土但更有效的办法:让每个团队自己报。报上来的东西可能有遗漏,但配合出口流量的实际访问记录一比对,遗漏立刻就现形了。流量不会说谎,有访问就说明有东西在跑。
2.2 一份能真正用起来的资产台账长什么样
很多人做的台账只有 IP 和负责人,这在演练里几乎没法用。一份合格的台账,字段设计要服务于“判断风险”和“找人处置”两个目的。我常用的字段如下:
| 字段 | 填写要求 | 为什么需要 |
|---|---|---|
| 资产标识 | 域名或 IP 加端口 | 唯一识别 |
| 业务归属 | 具体到系统名和模块 | 出问题知道影响面 |
| 对外暴露 | 是/否,以及暴露方式 | 决定风险等级 |
| 组件与版本 | 应用、中间件、数据库全列 | 判断有无已知问题 |
| 数据等级 | 是否含个人信息、是否含核心数据 | 决定处置优先级 |
| 责任人 | 主责人加备份人 | 半夜叫得醒 |
| 部署位置 | 哪个环境、哪个网段 | 隔离时快速定位 |
| 上线方式 | 手工发布还是流水线 | 紧急回滚可行性 |
| 日志情况 | 是否采集、保留多久 | 事后能不能查 |
这张表填起来累,但填完你就有了一个可以直接拿来决策的数据库。我最喜欢“日志情况”这一列——每次填这一列,都能发现几个日志压根没开的服务,而日志缺失在事件处置里的杀伤力,不亚于一个高危漏洞。
2.3 影子资产与暴露面收敛
影子资产是演练里最常见的失分点,来源一般是这么几类:测试环境直接绑公网域名、开发为了方便开的管理后台、临时做数据同步开的数据库端口、老系统下线了但域名没解绑、CDN 回源地址被直接访问。这些东西通常没人认领,因为“它本来就不该存在”。
收敛的原则很简单:能关就关,不能关就加限制。管理后台能不暴露公网就不暴露,实在要暴露,加一层访问控制,只允许固定出口访问;测试环境统一挂到内网,需要外网访问的走审批;数据库端口一律不对公网开放,这是红线;老域名做一次全量清理,没用的解析记录直接删掉。
注意:收敛暴露面时不要“一刀切”。有些看似管理后台的入口其实是业务必需的对接通道,直接关掉会导致业务中断,演练期间业务中断同样算事故。关之前先查访问日志,确认最近有没有真实流量。
2.4 一个容易被忽视的细节:账号资产
资产不只是服务器和域名,账号也是一种资产,而且是最容易被利用的那种。我在梳理时会把三类账号单独列出来:运维类账号(堡垒机、跳板机、云控制台)、应用间调用账号(服务之间的固定凭证)、第三方对接账号(合作方用来调接口的账号)。
这三类账号的共同问题是:开了就没人管,权限越给越大,离职了也不回收。演练前必须做一轮清理:删掉不用的、降权超范围的、轮换长期未改的。尤其是第三方对接账号,很多是明文写在对接文档里的,一旦泄露,对方能直接以合法身份调你的接口,日志里看起来完全正常,这种最难查。
3. 漏洞与弱口令:把八成风险按下去
防守有个残酷的现实:你不可能做到零漏洞,但你可以做到让对方觉得打你不划算。绝大多数低成本路径都指向同一批问题——弱口令、老版本组件、默认配置、无鉴权接口。把这四类按下去,你的风险曲线会明显平缓。
3.1 漏洞治理的优先级怎么排
漏洞列表拉出来动辄几百条,全修不现实,必须排优先级。我的排序逻辑是三要素相乘:可利用性 × 暴露程度 × 影响面。
可利用性看的是“要不要前置条件”,比如一个需要登录后才能触发的漏洞,优先级明显低于匿名可触发的;暴露程度看的是“公网能不能碰到”,内网漏洞在演练里的即时威胁小很多,但要注意内网横向的风险;影响面看的是“打穿之后能拿到什么”,能直接读到核心数据表的优先级最高。
按这个逻辑排完,你会发现真正需要立刻处理的往往只有一二十条,剩下的可以排队或者用其他手段兜底(比如加个访问控制、关掉相关功能入口)。这种“分层处理”的思路,比一股脑全修要现实得多。
3.2 弱口令与默认配置的批量整改
弱口令是演练里性价比最高的突破口,没有之一。它的可怕之处在于:不需要任何技术门槛,试一下就进去了,而且日志里看起来就像一次正常登录。
整改的时候不要一个个改,要批量做。第一步,把所有用到口令的地方列出来:数据库、缓存、消息队列、管理后台、堡垒机、云控制台、应用配置里的固定凭证。第二步,定一套口令规则:长度不低于 16 位、大小写数字符号混合、不含业务词和年份、同一口令不复用。第三步,用统一的口令管理方式下发,别再用聊天工具发口令,也别写在代码注释里。
默认配置同样危险:管理后台的默认路径、默认账号、默认示例页面、默认错误页、默认开启的调试接口。这些东西的共同特征是“装完就在那儿,没人动过”。我的做法是做一份装机基线,新机器、新服务一律按基线配置,把默认项全部改掉或关掉,这样就不用靠人记。
3.3 中间件与框架的版本基线
版本落后是最常见的问题,也是最容易补的。你要做的是三件事:建立组件清单、比对已知问题、制定升级计划。
组件清单要精确到版本号,包括应用框架、Web 服务器、数据库、缓存、消息中间件、日志组件、序列化库。有了清单之后,把它和公开的漏洞信息做比对,重点关注那些“不需要登录就能触发”的。
升级的时候有个现实问题:老系统不敢升,怕升完跑不起来。这种时候我的建议是先做隔离,再排升级。隔离的手段包括:在前面加一层反向代理做访问控制、关掉不必要的功能模块、限制请求大小和请求方法。这些临时措施不能根治,但能在演练窗口内把风险压住,等演练结束再从容升级。这不是偷懒,这是资源有限的现实选择。
3.4 补丁窗口与灰度策略
演练期间改东西,最怕改出事故。所以补丁和升级必须有窗口和灰度。
窗口上,避开业务高峰,尽量选在凌晨低峰期,并且提前通知相关方。灰度上,先在一台或一个小流量节点上升级,观察半小时到一小时,确认没有异常报错、没有性能劣化,再逐步放量。回滚方案必须提前准备好,包括旧版本包、配置备份、数据回滚脚本,而且要真的演练一遍回滚,不能只写在文档里。
提示:演练期间所有变更都要留痕,谁改的、改了什么、什么时候改的、验证结果如何。事后复盘时,这份变更记录往往是定位问题的关键线索,也能证明你的处置动作是合规的。
4. 代码层的安全:程序员真正能自己解决的部分
前面说的资产、口令、版本,多少还要依赖运维和安全团队配合。而代码层的安全问题,是开发完全可以自己闭环的,也是最能体现“程序员在防守中的价值”的地方。我带过几次代码安全自查,发现的问题高度集中,翻来覆去就是那几类。
4.1 一份能直接照着查的代码自查清单
与其去背一堆分类名词,不如拿一张清单逐项过。我常用的自查清单大概是这样:
| 检查项 | 具体看什么 | 常见问题 |
|---|---|---|
| 输入校验 | 所有外部输入是否做类型、长度、格式校验 | 直接拼接进查询或命令 |
| 输出编码 | 返回给页面的内容是否按上下文编码 | 用户内容原样输出 |
| 身份认证 | 每个接口是否校验登录态 | 漏加拦截器 |
| 权限校验 | 是否校验“当前用户能否操作该资源” | 只校验登录不校验归属 |
| 文件处理 | 上传类型、大小、存储路径、访问方式 | 上传后可被直接执行 |
| 敏感信息 | 日志、响应、报错里是否带敏感字段 | 报错页打出堆栈和配置 |
| 外部请求 | 服务端发起请求的目标地址是否受限 | 任意地址可请求 |
| 反序列化 | 是否反序列化不可信数据 | 直接反序列化请求体 |
这张表我建议每个接口都过一遍,尤其是那些“新加的、急着上线的、别人写的”接口。演练里被突破的,十有八九是这类没人仔细看过的边角代码。
4.2 参数校验与上下文输出编码
参数校验的核心思路是白名单:明确允许什么,而不是枚举禁止什么。比如一个只接受数字的 ID 参数,就用类型强转加范围判断;一个只接受枚举值的状态参数,就用枚举校验;一个文件名参数,就限制字符集和长度。
输出编码的关键在“上下文”。同样的用户输入,放到 HTML 正文、HTML 属性、JS 变量、URL 参数里,编码方式是不一样的。很多团队犯的错是“统一做了一次转义”,看起来安全,实际在某个上下文里仍然能被绕过。比较稳妥的做法是用成熟的模板引擎,它的自动转义是按上下文来的,然后明确禁掉“原样输出”的写法,在代码评审里把这类写法列为必须修改项。
4.3 越权问题:只校验登录是不够的
越权是我在自查里发现最多的问题,也是最容易被低估的。典型场景:接口校验了登录态,但没校验“这个订单是不是当前用户的”;后台接口校验了管理员身份,但没校验“这个管理员有没有这个菜单的权限”;接口用前端传上来的用户 ID 做查询,而不是用会话里的用户 ID。
排查方法很土但很好用:把每个带资源 ID 的接口列出来,逐个人工构造“换个 ID”的请求,看能不能拿到别人的数据。这件事可以做成脚本自动跑,用一个账号的凭证去访问另一个账号的资源,返回 200 且有数据就是问题。演练前把这一步做完,能砍掉一大半高危问题。
4.4 依赖组件与密钥管理
依赖组件的风险在于“你不知道你引了什么”。一个中等规模的项目,传递依赖可能有几百个,其中某个间接引入的组件出了问题是常有的事。所以要做两件事:生成依赖清单并锁版本,定期比对已知问题。锁版本很关键,不锁版本意味着每次构建拉到的都是最新版,某天上游发了个有问题的版本,你会毫无察觉地中招。
密钥管理是另一个高频雷区。硬编码在代码里的数据库口令、写在配置文件里的第三方密钥、提交到仓库的证书文件,这些都是“一旦代码泄露就全线失守”的东西。正确的做法是把密钥从代码里彻底剥离,走环境变量或配置中心,并且在代码提交前做一次敏感信息扫描,把这类内容拦在仓库外面。已经提交过的,要立刻轮换,因为提交历史里的东西删不干净。
5. 监控与日志:让异常有迹可循
我在应急处置里最怕听到的一句话是“我们没开日志”。没有日志,你连“什么时候进来的、从哪进来的、动了什么”都说不清,处置就只能靠猜,而猜的代价通常是扩大隔离范围,伤及业务。监控和日志这件事,平时做是成本,演练时做是救命。
5.1 日志该记什么、留多久
日志不是越多越好,但关键的四类必须记全:认证日志(登录、登出、失败尝试、口令修改)、权限变更日志(账号增删、角色调整、授权操作)、敏感操作日志(数据导出、批量查询、配置修改、文件上传)、应用异常日志(报错、超时、外部请求失败)。
保留时间上,很多合规要求是不少于六个月,实际做的时候建议按这个下限来,而且要做到集中采集、异地留存。本地日志最大的问题是“出事之后第一件事就是被清理”,所以必须实时同步到独立的日志平台,本机只作为缓存。
还有一个细节:日志内容本身要脱敏。手机号、证件号、口令、令牌这些东西不能明文进日志,否则日志平台反而成了泄露源。
5.2 值得重点关注的那几类告警
告警不在于多,在于准。我一般会优先配这几类:
- 暴力破解类:同一账号或同一来源短时间大量登录失败,触发阈值可以设成 5 分钟内 10 次。
- 异常登录类:非工作时间登录、非常用地区登录、同一账号短时间内多地登录。
- 异常外联类:服务器主动向外部陌生地址发起连接,尤其是非常见端口。
- 可疑文件类:Web 目录下出现新增的可执行脚本文件、文件内容被批量修改。
- 批量数据操作类:短时间大量查询或导出,超过日常基线数倍。
- 权限变更类:非预期时间的新增管理员、权限提升操作。
这几类告警的共同点是噪音相对可控、指向性明确。宁可少配几条准的,也不要配一堆天天响的,响多了就没人看了,这是监控体系失效最常见的原因。
5.3 告警降噪与值守排班
降噪的手段有三个:白名单(已知的正常行为,比如定时任务、健康检查)、聚合(同类告警合并成一条,避免刷屏)、分级(分成必须立刻处理、当天处理、仅记录三档)。
值守排班要落实到人,不能写“安全组负责”。我的做法是排一张表:每天一个主值、一个备份,明确联系方式,明确“什么级别找谁”。同时把处置手册贴在值班群里,内容包括:收到这类告警先看什么、去哪查日志、什么情况下升级上报、什么情况下先隔离。手册要短,一页纸能看完,太长没人看。
6. 应急响应:真出事那几十分钟怎么走
演练期间真出事的时候,最大的敌人不是对方,是慌。人在慌的时候容易做两件事:一是急着把机器重装,二是急着把服务全停。前者毁掉证据,后者扩大影响。所以我一直强调,应急处置要有一套固定动作,事先练过,事到临头照着做就行。
6.1 分级、上报与止损的先后顺序
发现异常后的第一分钟,先做判断:影响范围多大、是否涉及核心数据、是否还在持续。基于这个判断分三级:影响核心数据或大面积服务不可用的,立刻上报并启动最高级别响应;影响单台服务器或单个非核心功能的,按常规流程处置;仅为可疑但未确认的,记录并持续观察。
顺序上,我的原则是先止损、再取证、后修复。止损指的是切断持续损害,比如把被影响的机器从负载均衡摘掉、封掉可疑来源、禁用可疑账号。取证指的是保留现场,包括内存中的进程信息、网络连接状态、关键日志、可疑文件样本。修复才是重装、打补丁、改配置。
注意:千万不要在没取证之前就重装系统或者删日志。很多人图省事,一出事就重装,结果复盘时说不清到底怎么进来的,整改也就无从下手,下次照样中招。
6.2 处置动作的实操顺序
我把处置拆成六步,按顺序走,不要跳:
- 确认现象:从告警或人工发现出发,先确认“这是真的还是误报”,看日志、看进程、看连接。
- 隔离影响:摘流量、断外联、锁账号,把损害控制在最小范围。
- 保留证据:导出日志、保存进程和连接快照、备份可疑文件,做好哈希记录。
- 定位入口:从日志往前倒推,找到第一次异常访问的时间点和来源,判断入口是漏洞、弱口令还是配置问题。
- 清除与修复:清除异常账号、异常文件、异常计划任务,修补入口问题。
- 恢复与验证:恢复服务,持续观察一段时间,确认没有二次进入。
这六步里,第四步最耗时也最关键。定位不到入口,你做的清除都是治标,对方随时能再来一次。
6.3 复盘怎么写才有用
复盘不是写检讨,也不是走流程。一份有用的复盘至少包含:完整时间线(几点几分发生了什么、谁做了什么)、根因分析(入口是什么、为什么没防住、为什么没早点发现)、改进项清单(具体动作、责任人、完成时间)。
我最看重的是时间线里的“发现耗时”和“处置耗时”两个数字。前者反映监控能力,后者反映流程效率。这两个数字每一轮都应该比上一轮小,如果一直没变化,说明改进项根本没落地。改进项要少而具体,写“加强安全意识”这种等于没写,写“把管理后台的公网访问权限收敛到固定出口,本周五前完成”才有意义。
7. 常见问题与排查速查
演练期间的问题高度重复,把它们整理成一张速查表,能省下大量现场思考时间。下面这些是我这些年被问得最多、也最容易卡住的几类。
7.1 高频问题速查表
| 现象 | 可能原因 | 排查动作 | 处置建议 |
|---|---|---|---|
| 日志里大量 404 和异常路径请求 | 自动化扫描 | 看来源 IP 是否集中、UA 是否异常 | 限流加封禁,确认无成功响应 |
| 管理后台出现陌生登录 | 口令泄露或弱口令 | 核对登录时间、来源、操作记录 | 立即改口令、封来源、查操作痕迹 |
| 服务器对外发起陌生连接 | 程序被植入或配置错误 | 查进程、查定时任务、查启动项 | 断外联、保留样本、定位入口 |
| 页面被插入异常内容 | 输入未过滤或文件被改 | 比对文件哈希、查上传接口 | 恢复文件、修入口、查同类文件 |
| 接口返回大量数据 | 越权或未分页 | 用另一账号复现、看参数 | 补权限校验、加限制 |
| 数据库连接数异常升高 | 慢查询或异常访问 | 看连接来源、看执行语句 | 限流、临时封禁、优化语句 |
| 员工反馈账号被锁定 | 撞库尝试 | 看失败登录来源分布 | 加固口令策略、加验证码 |
| 测试环境可从公网访问 | 暴露面收敛不彻底 | 查解析记录和端口映射 | 关闭公网入口或加访问控制 |
7.2 几个踩过的坑,写下来提醒后来人
第一个坑是过度依赖工具。有一年我们接了一堆扫描报告,按报告修了两周,结果演练第一天就被一个报告里没提的接口打穿了——那个接口是半年前临时加的,压根没进过扫描范围。这件事让我彻底改变了顺序:先保证资产清单完整,再谈扫描。
第二个坑是改配置不测试。演练前一周为了收紧迫切改了一条访问控制规则,结果把合作方的回调地址挡了,业务侧报了一堆失败。教训是:任何收敛动作,改完立刻验证主流程,别等到第二天业务反馈。
第三个坑是日志留了但查不到。日志是集中采集了,但没建索引、没做结构化,出事的时候想按时间戳筛一条记录,翻了半小时没找到。后来我们把关键字段做了结构化解析,查询时间从半小时降到几秒。
第四个坑是只盯公网忘了内网。大家习惯性认为内网安全,结果有一次是从一台内网测试机横向过去的,那台机器上还留着默认口令。内网的边界防护和账号管理,该做的一样不能少。
我个人在实际操作中的体会是,护网行动这件事,拉开差距的从来不是谁的工具更高级,而是谁的基础工作更扎实。资产清单是不是真的完整、口令是不是真的改干净了、日志是不是真的能查到、出事的时候是不是真有人能在十分钟内到位,这几件事做到了,成绩不会差。反过来,这几件事做不到,买再多的设备也只是给自己一点心理安慰。所以如果你今年只打算做一件事,我建议从那张资产台账开始填,把“日志情况”这一列老老实实填完——填的过程中你大概率会发现几个自己都不知道的东西,那才是真正需要花时间的地方。