代码审计这件事,真没那么玄乎

张开发
2026/4/16 16:06:30 15 分钟阅读

分享文章

代码审计这件事,真没那么玄乎
凌晨两点我审计一个 3000 star 的开源项目发现了一行让人无语的代码。代码审计这个事儿很多人觉得很难但其实就是找 Pattern。今天我把这几年审计 Java 应用的经验系统地整理一下。事情是这样的。上周三凌晨两点我盯着屏幕上一行代码整个人愣住了。那是一个开源的 Spring Boot 项目GitHub 上 3000 多 star。我在审计它的用户登录模块然后我就看到了这行代码String sql SELECT * FROM users WHERE username username ;我当时就想这尼玛也能过代码审查这就是典型的 SQL 注入直接把用户输入拼接到 SQL 语句里。我随手试了一个 payloadadmin OR 11整个用户表的数据全出来了。那一刻我有点懵。不是惊讶于漏洞本身而是惊讶于这种东西居然能上线还能有 3000 多 star。说实话代码审计这个事儿很多人觉得很难。什么需要深厚的技术积累、要对业务逻辑非常熟悉、没有几年的经验根本做不了。这话听着有点刺耳但我想说真没那么玄乎。我自己在开始学代码审计之前也就是个普通 Java 开发天天写 CRUD连 OWASP Top 10 都背不全。但后来我发现这玩意其实就是找 Pattern就跟学正则一样见多了就有感觉了。先说结论代码审计的核心就两件事——知道危险代码长什么样知道去哪找。一、危险 Pattern 就那几种我刚开始学审计的时候也想着要把所有漏洞类型都背下来。什么 SQL 注入、XSS、XXE、反序列化列了一大堆看着就头大。后来我发现对于 Java Web 应用来说真正高频出现的危险代码其实就 5 种。就 5 种没了。第一种字符串拼接 SQL。这个最常见也最容易被忽视。String sql SELECT * FROM users WHERE id userId;第二种MyBatis 的 ${} 用法。这个我见过太多人踩坑了。#{} 是预编译的安全。${} 是字符串替换危险。第三种动态表名/列名。这个稍微特殊一点因为表名和列名没法用预编译参数只能拼接。但可以用白名单校验。第四种Like 语句拼接。这个容易被忽视但原理是一样的用户输入还是进 SQL 了。第五种Order By 拼接。排序字段动态指定也是高危。就这 5 种。你把这 5 种 Pattern 记熟了看到代码就能条件反射一样识别出来那你的代码审计就算入门了。二、审计流程四步走知道了危险代码长什么样接下来就是去哪找的问题。我审计一个项目基本是四步走第一步定位数据入口。数据从哪进来大部分时候是 Controller。你打开项目的 controller 目录看每个接口的参数这些就是用户能控制的东西。第二步追踪数据流向。从 Controller 到 Service从 Service 到 Mapper一层一层跟下去。第三步识别危险 Pattern。到了数据访问层你就要开始找上面说的那 5 种 Pattern 了。第四步验证漏洞。找到可疑代码别急着下结论先验证一下。本地搭个环境发个请求试试看看能不能复现。三、实战我审计过的一个项目说个真实的案例。去年有个朋友的公司做了个内部管理系统让我帮忙看看有没有安全问题。系统是 Spring Boot MyBatis挺常见的技术栈。我拿到代码之后先快速扫了一遍目录结构然后直接进了 controller 目录。第一个接口就让我有点紧张。PostMapping(/login) public Map login(RequestParam String username, RequestParam String password)登录接口传 username 和 password。这种接口一般都是重灾区我立马跟了进去。跟到 Mapper 之后我就看到了这个东西select idselectByUsername SELECT * FROM users WHERE username ${username} /select我当时就愣住了。真的那种感觉就像你打开自家冰箱发现里面放着一颗定时炸弹。这是一个登录接口直接用 ${} 拼接用户输入。这意味着什么意味着任何人都可以绕过登录。我随手试了一个 payloadusername: admin OR 11password: 随便填。系统直接把我当成了 admin 用户登录成功了。后面的事情就比较常规了。我花了两天时间把整个系统审计了一遍一共发现了 7 个高危漏洞包括 SQL 注入、越权访问、密码明文存储。朋友公司修了一个星期才修完。这件事给我的触动挺大的。一个正式上线的系统有专业团队开发有代码审查流程还能出现这种低级漏洞。不是他们不专业而是真的没意识到这个问题。所以今天我才想写这篇文章。代码审计这个技能不应该是安全专家的专利每个开发者都应该会一点。四、工具我平时用什么说到工具我先声明一下工具是辅助不能替代人工。有些朋友觉得装个扫描器跑一遍就完事了。真不是这样的。工具能帮你发现一些问题但更多的是误报而且很多逻辑漏洞工具根本扫不出来。第一个FindSecBugs。这是个 IDE 插件装到 IntelliJ IDEA 里。它会在你写代码的时候实时检测发现危险代码就标红提醒你。第二个SonarQube。这个是做代码质量管理的也能扫安全问题。配置好规则之后每次提交代码自动扫描。第三个我自己写的扫描脚本。就是个 Python 脚本用正则匹配危险 Pattern。准确率一般但胜在快。再次强调工具只能辅助。真正靠谱的审计还是得人工一行一行看代码。五、学习路线普通人怎么入门最后聊聊学习路线。很多朋友问我想学代码审计从哪开始我的建议是分三步走第一步打基础。Java 基础要扎实Servlet、JDBC、MyBatis 这些框架要会用。SQL 语句要会写HTTP 协议要懂。第二步学漏洞原理。OWASP Top 10 过一遍每个漏洞类型搞清楚是怎么回事。推荐几本书《白帽子讲 Web 安全》《Web 安全深度剖析》。第三步实战练习。找个靶场项目自己搭环境自己审计自己验证。VulHub、WebGoat、DVWA这些都是经典的靶场。你要是全职学每天 8 小时三个月能入门。要是在职学每天 2 小时半年到一年吧。慢吗挺慢的。但安全这个领域本来就没有捷径。六、一些真心话写到这想聊点题外话。代码审计这个技能值得学吗我觉得值得。不是为了转行做安全而是为了写出更安全的代码。你做过审计就知道哪些地方容易出问题。写代码的时候自然就会避开这些坑。但我也不建议所有人都去学。如果你就是个业务开发天天写 CRUD那把业务逻辑搞清楚可能更重要。我自己是什么情况我就是个普通人没多聪明也没多努力。学代码审计纯粹是因为好奇想看看那些漏洞到底是怎么回事。学着学着就有点感觉了。今天写这篇文章就是想把这些经验分享给需要的人。不是什么高深的东西就是普通人能学会的那种。你要是觉得有用那就最好。要是觉得没啥用那也没关系至少我认真写了。最后代码审计这个事儿真没那么玄乎。知道危险代码长什么样知道去哪找多练习多总结。就这么简单。最后给几个建议1. 别迷信工具人工审计最靠谱2. 多审计开源项目练手又安全3. 发现漏洞别急着炫耀先验证再报告4. 保持好奇保持谦逊大时代啊朋友们。安全这事儿从来都不是一个人的战斗。

更多文章