后端代码安全审计不是“走查一遍代码有没有明显漏洞”,而是要把业务逻辑、数据流、权限边界和第三方依赖全部放进攻击者的视角里重新过一遍。很多团队做审计时只盯着SQL注入和XSS,结果真正的风险往往出现在接口越权、批量数据导出、异步任务未鉴权、以及看似无害的内部接口暴露上。审计流程的价值不在于发现多少个低危问题,而在于是否覆盖了高价值攻击路径。

审计流程的第一步:确定审计边界与资产清单

后端代码审计不能一上来就打开整个仓库乱翻。先要明确这次审计覆盖哪些服务、哪些模块、哪些API版本。把仓库里所有对外暴露的HTTP接口、RPC服务、消息队列消费者、定时任务、Webhook回调全部列出来。很多团队只审计Controller层,却忽略了定时任务和消息消费者同样在执行业务逻辑,攻击者如果能够伪造消息或者触发任务重放,危害不比直接调接口小。

资产清单至少包含:接口路径、请求方法、是否需要认证、角色权限要求、是否涉及敏感数据、是否调用外部服务、是否有文件上传下载、是否有异步处理。清单整理出来后,审计的优先级自然就清楚了。凡是涉及资金、用户隐私、权限变更、文件处理、外部回调的接口,全部列为高危审计对象。

权限模型审计:越权比注入更常见

后端代码里最常见的严重漏洞不是注入,而是越权。水平越权和垂直越权在大量业务系统里反复出现。审计时要重点看每一个接口是否真的校验了当前用户对目标资源的归属关系。例如用户查看订单详情,代码里只校验了登录态,却直接根据请求参数中的订单ID查询数据库,没有校验该订单是否属于当前用户,这就是典型的水平越权。

垂直越权则表现为普通用户能够调用管理员接口。审计时要检查路由中间件、拦截器、注解配置是否完整覆盖了所有需要管理员权限的接口。有些框架里权限注解只加在部分方法上,其他方法因为命名不规范或者遗漏,直接裸奔。还要注意权限校验不能只在前端做,后端必须独立校验。审计时看到前端隐藏按钮、菜单控制权限,但后端接口没有对应校验的,一律判定为高危。

输入验证与注入防护:不要只盯着SQL

SQL注入仍然是后端审计的重点,但现在的ORM框架已经能挡住大部分简单拼接。真正容易出问题的地方在于动态排序字段、动态表名、原生SQL拼接、以及报表查询里的自定义条件。审计时要搜索代码中所有字符串拼接SQL的地方,尤其是使用MyBatis时${}和#{}混用的情况。凡是用户输入能够进入${}的部分,必须确认是否有白名单校验。

除了SQL注入,命令注入、模板注入、表达式注入同样需要关注。后端代码中如果调用了Runtime.exec、ProcessBuilder、或者模板引擎渲染用户输入,必须检查参数是否经过严格过滤。还有XML外部实体注入,在解析XML的接口中如果允许外部实体,攻击者可以读取服务器文件。审计时看到XML解析相关代码,要确认是否禁用了DOCTYPE和外部实体。

敏感数据保护:日志、响应和存储三个维度

审计后端代码时,敏感数据的暴露往往比想象中更严重。第一个维度是日志。很多开发为了方便调试,在日志里打印了完整请求参数、用户密码、身份证号、银行卡号、Token。这些日志一旦被攻击者获取,或者被内部人员滥用,就是严重的数据泄露。审计时要检查log.info、log.debug中是否打印了敏感字段,尤其是登录接口、支付接口、用户注册接口。

第二个维度是接口响应。后端接口返回给前端的数据是否包含了不该返回的字段。例如用户列表接口返回了密码哈希、盐值、内部ID、权限标记。审计时要逐个接口检查返回的DTO对象,确认没有多余字段。第三个维度是存储。数据库中的敏感字段是否加密存储,配置文件中的数据库密码、第三方密钥是否明文硬编码在代码里。很多团队把密钥直接写在application.yml或者常量类里,代码一旦泄露,全部服务沦陷。

文件上传与下载:绕过方式比想象中多

文件上传是后端审计中必须单独处理的一类风险。审计时不能只看文件扩展名校验,还要看文件内容校验、存储路径、访问方式。攻击者可以上传一个扩展名为.jpg的文件,但内容实际上是JSP或者PHP脚本。如果存储路径在Web目录下且能被解析,直接拿到Webshell。即使存储路径不在Web目录下,如果下载接口存在路径穿越,攻击者也能读取服务器上的任意文件。

审计文件下载接口时,要重点看文件名参数是否直接拼接到文件读取路径中。例如代码中使用FileInputStream读取用户传入的filename参数,没有做路径规范化处理,攻击者传入../../etc/passwd就能读取系统文件。正确做法是使用文件ID映射到实际存储路径,或者对文件名做严格的白名单校验,并限制在指定目录内。

加密与认证:算法选择比代码实现更关键

后端代码审计中,加密相关的检查不能只停留在“是否使用了加密”。要确认使用的算法是否安全。例如MD5、SHA1用于密码存储已经不安全,应该使用bcrypt、scrypt或者Argon2。对称加密中DES、3DES已经被认为不安全,应该使用AES-GCM。随机数生成要使用SecureRandom而不是Random。JWT令牌要检查签名算法是否允许none,密钥是否足够强,过期时间是否合理。

认证流程本身也要审计。登录接口是否有暴力破解防护,验证码是否可绕过,找回密码流程是否存在逻辑漏洞。例如找回密码时,验证码校验和密码重置是否在同一个步骤完成,攻击者是否可以通过修改响应包绕过验证码。审计时要特别关注多步骤流程中的状态管理,确认每一步的校验结果不会被客户端篡改。

依赖与配置审计:漏洞可能来自第三方

后端代码审计不能只看自己写的代码。第三方依赖的漏洞同样致命。审计时要生成依赖清单,检查是否存在已知CVE漏洞。特别是Fastjson、Log4j、Shiro、Spring框架等曾经爆出过严重漏洞的组件。如果项目中使用的是旧版本,必须标记为高危。还要检查依赖的来源是否可信,是否使用了私有仓库,是否存在供应链投毒风险。

配置文件审计同样重要。检查生产环境配置是否关闭了调试模式,是否暴露了actuator端点,是否配置了正确的CORS策略,是否限制了跨域请求的来源。很多生产事故是因为开发配置直接上线,导致Spring Boot Actuator的/env、/heapdump端点暴露,攻击者可以直接获取环境变量中的数据库密码和密钥。

业务逻辑漏洞:工具扫不出来的高危问题

业务逻辑漏洞是自动化工具很难发现的,必须靠人工审计。典型场景包括:订单金额是否由前端传入,支付回调是否校验签名和金额,优惠券是否可以重复使用,库存扣减是否存在并发问题,邀请奖励是否可以被刷。审计时要画出核心业务流程的时序图,逐步检查每个环节的状态流转是否合理,是否有缺失的校验步骤。

例如一个典型的支付漏洞:前端提交订单时传入了商品价格,后端直接使用该价格创建支付单,没有从数据库重新查询商品价格。攻击者修改请求参数中的价格字段为0.01元,就能以极低价格购买商品。这类问题在代码层面看每一行都没错,但整体业务逻辑存在缺陷。审计时必须结合业务场景理解代码意图,而不是孤立地看单个函数。

审计报告与修复优先级

审计完成后,输出的报告不能只是一堆漏洞列表。每个漏洞要包含:漏洞描述、影响范围、复现步骤、代码位置、修复建议、风险等级。风险等级要结合可利用性和业务影响来评定。例如一个需要管理员权限才能触发的低危问题,可能不如一个无需认证即可利用的越权问题严重。修复优先级应该按照“远程可利用、无需认证、影响核心数据”来排序。

修复完成后必须进行回归验证,确认漏洞真正被修复,而不是仅仅在表面做了过滤。很多团队修复越权漏洞时只在单个接口加了校验,其他类似接口仍然存在同样问题。审计人员要检查同类模式是否全部修复,避免“打补丁式”修复留下遗漏。

后端代码安全审计是一个持续的过程,不是上线前做一次就结束了。每次功能迭代、依赖升级、架构调整后,都应该重新评估风险面。把审计流程固化到开发流程中,比依赖一次性的外部审计更有效。真正有效的审计不是找到最多的漏洞,而是让团队建立起对安全边界的清晰认知。