资讯中心

红队视角下的Java Web代码审计:从漏洞定位到快速打点

📅 2026/10/19 1:01:20
红队视角下的Java Web代码审计:从漏洞定位到快速打点
打了几年红队我越来越确认一件事Java Web的代码审计是打点阶段性价比最高的技术动作之一。很多人觉得代码审计是安服仔的日常红队就该在黑盒里猜接口、扫目录、挂字典等一个撞大运的弱口令或者未授权接口。但实际参与过几个大项目之后你会发现真正拉开差距的恰恰是“有没有条件拿到代码、拿到代码之后能不能快速定位关键漏洞”这件事。这篇文章我不打算讲那种从零开始的Java代码审计教程那至少要写一本书。我想聚焦一个红队实际场景在有限的时间窗口内拿到一套Java Web系统的源码或部分源码如何从代码层面快速确认高风险漏洞并把它转化成实际的服务器控制权。也就是从漏洞定位、到利用链构造、再到打点成功的完整闭环。先泼一盆冷水代码审计不是“看代码找漏洞”这么简单。红队场景下的审计本质上是在海量业务代码里做风险熵值排序——先找出哪些地方最可能“炸”再去验证它。你需要的是方法论而不是逐行读代码的耐心。1. 为什么红队打点要把代码审计放在第一位1.1 黑盒“碰运气”的天花板黑盒测试的局限性这几年越来越明显。早期的Web系统你扫个目录就能发现admin.jsp、upload.do、api/v1/user/list这些接口字典一挂就完事。但现在的Java Web项目几乎全部走Spring Boot RESTful API风格路径全部自定义参数全是JSON体接口还不带后缀。你拿传统字典去扫耗费大量时间精力结果发现路径覆盖率连一成都不到。更麻烦的是现在Java生态里各种网关、过滤器、拦截器、权限注解满天飞。黑盒情况下你根本不知道哪些接口被拦截了、哪些参数被过滤了、哪些接口压根没接入认证体系。你只能靠登录态的Cookie盲目试成功率非常低。1.2 拿到代码等于拿到了“攻击面全景图”代码审计最大的价值不是“找漏洞”而是帮你快速画出整个应用的攻击面。拿到源码之后你能看到哪些接口免认证比如没有加登录注解的Controller方法路由映射的真实路径而不是猜所有第三方组件的版本直接对照漏洞库打交互参数的类型与校验逻辑判断能不能注入或者绕过内网地址、云厂商AK/SK、数据库口令这类“彩蛋”配置这个过程通常跑在第一步代码结构梳理。把项目导进IDEA先看目录结构再看pom.xml中的依赖清单最后看配置文件和路由注解。本质上你做的事情是让攻击面从“信封外摸索”变成“直接看设计图纸”。1.3 红队场景下什么情况下会拿到源码聊多了容易抽象说点实际的。很多人问我“你们做红队是不是很少有机会拿到源码”其实恰恰相反。在多数授权项目中我们会用到以下几种途径拿代码客户自己提供源码很多单位的内部系统是外包开发的源码就存在服务器上或Git仓库里授权范围内直接拿。开源项目二次开发大量政企系统基于开源框架如若依、RuoYi、SpringBlade、JeeSite做的二开你只要定位到它基于哪个版本直接对比开源commit记录就能锁定漏洞点。服务器反编译如果拿到的是打包好的WAR或JAR直接丢进反编译工具还原代码。对红队来说反编译出来的代码虽然没有注释但控制流和配置完整足够用于漏洞挖掘。供应链泄露不少小外包商的代码在GitHub、Gitee上泄露或挂在某下载站。实战中这也是一个常见突破口。2. 审计前的准备环境与信息收集决定审计效率2.1 先看依赖和后端技术栈拿到代码的第一件事不是急着读业务代码而是打开配置文件把技术栈和依赖盘清楚。这里我指的是框架方向Spring Boot、Spring Cloud、Spring MVC、Struts2、Play Framework还是老旧的ServletJSP。安全组件Spring Security、Shiro、Sa-Token、JWT拦截器。高危组件Fastjson、Log4j2、XStream、Commons-Collections、SnakeYAML、MyBatis有特殊Sink点。这些信息通常集中在pom.xmlMaven项目或build.gradleGradle项目。打开之后建议直接搜索几个关键词fastjson、log4j、shiro、spring-boot-starter-actuator、druid。有了组件清单你就能对照已知CVE或者公开的利用PoC做“组件漏洞打点”。这个过程可以非常快——如果你看到fastjson版本是1.2.47之前、log4j版本是2.14之前基本上不用往下读代码直接掏利用工具测试。2.2 配置文件里的“意外之喜”Java Web项目的配置信息是代码审计里被严重低估的宝藏点。尤其是application.yml、application.properties、config包下的常量类里面经常躺着数据库账号口令明文或不强加密Redis密码、消息队列凭证OSS、COS的SecretKeyJWT签名密钥内网服务调用地址邮件服务号的密码这些配置信息一旦拿到很多漏洞根本不需要“攻击”直接“登录”就行。例如你发现生产环境JWT密钥是硬编码的abcd1234那伪造管理员Token就是顺手的事。我的习惯是先搜正则再看配置。搜索password、secret、accessKey、token、jwt等关键词正则匹配出所有值不为空的字段逐个看。不要小看这一步很多项目的“漏洞”其实是运维偷懒埋下的。2.3 反编译场景下的特殊处理如果是反编译项目代码读起来会比源码累很多。有几个技巧可以减少痛苦用IDEA直接拖入JARIDEA对JAR包的反编译支持做得不错。也可以搭配插件如FernFlowerIDEA内置。Jadx更适合Android反编译但用来反编译普通JAR也很好用输出可直接阅读的.java文件。先反编译再全局搜索反编译完的代码仓库建议直接全局搜索不要“读”代码。因为反编译代码里缺少注释和格式化逐行阅读效率极低。另外我踩过一个坑反编译工具对Lambda表达式和泛型还原得并不好经常会把匿名内部类拆成一堆class$1、class$2。遇到这种类建议直接去JD-GUI或者用工具链重新反编译该单独类或者干脆用JAVAP命令查看字节码别在上面浪费太多时间。3. 漏洞定位三板斧从入口点到危险函数的数据流追踪3.1 第一板斧直接搜危险Sink点Java Web代码审计的Sink点就是可能执行恶意操作的危险函数。实战中最高频的Sink类型如下我把它们列出来的时候建议你直接收藏作为日常搜索关键词清单Runtime.getRuntime().exec() ProcessBuilder() Class.forName() / ClassLoader.loadClass() Method.invoke() SpelExpressionParser().parseExpression() OgnlUtil.getValue() / Ognl.getValue() FreemarkerProcessBuilder() TemplateEngine.process() new XMLDecoder() SAXParser / DocumentBuilder JNDI lookup() / jndi 搜索: InitialContext.lookup SQL拼接相关createStatement、prepareStatement MyBatis ${} 语法 文件操作相关FileOutputStream、IOUtils.copy、transferTo用这些关键词做全局搜索然后人工判断每个命中点是否外部可控。所谓的可控就是参数能通过HTTP请求、MQ消息、定时任务配置等外部输入传入到这个Sink。红队场景里这个搜索动作要在IDE的全局搜索框里完成推荐打开Scope - Whole Project。命中之后跟着调用栈逆向往上看确认数据流从哪里进来。3.2 第二板斧Web入口点批量梳理危险函数命中并不等于可利用。你还需要确认Sink点是否有入口连通。Java Web项目的入口包括Controller/RestController注解的类RequestMapping/GetMapping/PostMapping/PutMapping等路由映射WebFilter实现类中doFilter逻辑HandlerInterceptor的preHandle和postHandle定时任务类Scheduled——这部分如果读写外部文件或调远程接口也可能成为攻击面JSP/Servlet文件建议做法全局搜索RequestMapping和GetMapping等注解把每个路径对应到方法签名顺手记录是否是免认证入口。免认证入口是打点阶段的高危信号可以直接放入“候选攻击入口”清单。3.3 第三板斧正向数据流追踪第三板斧其实是最核心也最费时的。但红队实战中没必要对每个入口都做正向数据流而是挑高危入口优先做优先级别从高到低免认证入口文件上传/文件下载接口接口参数直接映射到对象反序列化或Bean绑定接收JSON的接口和Fastjson漏洞联动概率高动态SQL模板渲染比如Freemarker、Velocity以文件下载接口为例典型漏洞代码如下RequestMapping(/download) public void download(String fileName, HttpServletResponse response) throws IOException { String basePath /app/upload/; File file new File(basePath fileName); // 返回文件内容 }这里如果fileName可控且没有过滤../就是任意文件下载漏洞再配合读取/etc/shadow或Web环境配置文件如application.yml可以直接把数据库密码拿到手。3.4 典型漏洞链拆解Fastjson反序列化Java生态中真正的“打点之王”当属Fastjson反序列化。这里不想背诵CVE编号而是想带你走一遍审计视角的发现过程。审计时如果项目使用了Fastjson且版本较低比如1.2.47及之前你要做的第一件事是确认哪些接口直接接收了JSON并通过JSON.parseObject()或JSON.parse()处理了。搜索这两个方法后标注所有入口方法。然后要检查是否开启了autoType默认开启。实战中最常用的验证方法是提交一段带type的JSON看后端是否报错显示“autoType is not support”。如果后端暴露了报错信息这几乎等于告诉你“它尝试解析了type字段”。一旦确认可利用下一步就是围绕RMI/LDAP加载恶意类的服务端设计。但这里有一个很关键的阻碍目标机器能不能访问你的恶意服务内网隔离环境下出网受限所以实战里要提前准备多个方案同一内网服务器上起恶意服务、或者直接利用目标能访问到的内部IP。反序列化漏洞的红队打法我总结成一句话从代码层面确认Sink从依赖版本和AutoType状态确认可利用性从网络层面确认出网条件三者都成立打点成功率才会高。4. 从漏洞到控制权的利用链搭建4.1 代码漏洞如何“翻译”成服务器控制权很多初学者容易卡在“我确认了漏洞存在但怎么变成Shell”。实际上漏洞利用的本质是把代码层面的问题变成运行时行为可控。你不需要“万能利用工具”而是要根据目标环境去组合利用链。举个例子。如果你在审计中发现了一个MyBatis的${}注入点而这个查询语句被一个管理员接口调用那么你可以用堆叠注入写文件前提是数据库账号有FILE权限用INTO OUTFILE写入Web目录下的JSP木马或者用load_file()读取服务器上的敏感文件比如本地的application.yml如果数据库账号权限较高还可以尝试UDF提权到操作系统在红队实战中SQL注入利用我见过最高效的路径并不是“立刻写马”而是先读配置、再拖库、再找后台弱口令、最后从容打点。写成一句话把时间花在“读配置”上通常比“直接写马”更能掌控全局。4.2 命令执行与WebShell的选择当你拿到代码执行或命令执行漏洞后控制权落地的核心选择是WebShell类型。Java Web环境里我推荐的内存马/WebShell路径大致是这几类JSP WebShell如果应用容器支持JSP解析写一个带混淆的JSP木马是通用做法。但注意现在的WAF对JSP常见字符串比如Runtime、ProcessBuilder、getInputStream都有检测建议直接做字节码绕过。简单有效的方式是用ClassLoader配合Base64解码加载字节码。Filter型内存马不需要落盘直接注入一个实现了Filter接口的恶意类到应用容器中。由于它不在Web目录常规文件扫描无法发现适合做持久化。Servlet型内存马注册一个恶意Servlet到容器通过特定路径触发。Spring Controller内存马在Spring容器中动态注册一个Controller方法适合Spring Boot应用。我个人在实战中如果是为了“快速打点拿数据”首选的其实是JSP WebShell——简单直接、兼容性好、变更少。但如果是为了“长期潜伏、后续横向”Filter型内存马更合适。4.3 出网限制与备选Shell方案很多内网目标的网络策略极其严格只能访问同网段少数IPDNS出网被禁HTTP出网被白名单。这种情况下你的反弹Shell往往拿不到连接恶意代码也拉不下来。这时候最实用的思路是放弃“反弹”思路改成“写文件”思路。代码执行后先把WebShell内容写入Web目录再通过HTTP直接访问控制。这也是为什么我说“先确认Web根目录”是打点阶段的核心动作之一。另一个备选方案是日志投毒。如果目标系统有日志写入的能力比如参数值被打印到error.log你可以把一段JSP写入到可以被包含的日志文件中再通过文件包含漏洞或者直接访问日志落地的路径触发。但这个方式的成功率完全取决于环境不宜作为主方案。4.4 防御者的视角如何堵住这类链做红队久了你会发现一个残酷的事实多数漏洞不是“挖出来”的而是“配置不当”和“历史积累”造成的。所以站在防御者视角我强烈建议开发团队优先做三件事一是把所有第三方依赖的版本进行集中管理并定期用SCA工具扫描比如OWASP Dependency-Check、Mend、Trivy。二是对API接口做最小权限控制不要因为“内网就不加认证”。三是对关键Sink点做统一封装例如全项目通过一个SQLUtil类访问数据库而不是到处写createStatement、到处拼接${}。封装的目的是让安全团队有一个统一的“卡点”去部署加固逻辑而不是满项目地找零散的Sink。5. 快速打点中容易“卡壳”的几个细节5.1 代码版本和已部署版本的错位这是红队拿源码审计时最容易翻车的地方。我记得有一次项目审计发现在git仓库的UserController中存在一个上传漏洞路径是/api/user/uploadAvatar没有限制文件类型。当时我在测试环境试了整整一小时怎么打都不成功。后来发现原因很简单生产环境部署的jar包并不是当前git分支的代码。这个系统已经迭代了十几版有些接口在代码里已经重写了但部署包还停留在三年前的版本。反而当时线上运行的那个版本存在一个老旧的/upload接口这个接口在git仓库里早就被删除了。这个教训让我记住了一个习惯拿到源码后先去验证线上系统是否真的运行着这份代码。验证方式很多比如比较某个接口的返回头、错误提示页特征或者直接搜生产环境暴露的特征class文件。如果差异太大立刻把“线上反编译”作为第二选项。5.2 框架版本“升级”带来的利用链失效很多开发团队会定期升级依赖版本这本来是件好事但对红队来说意味着你以往熟悉的利用链经常失效。比如Spring Security 5.7直接移除了WebSecurityConfigurerAdapter导致很多老文章里讲的配置绕过思路就此失效再比如Fastjson从1.2.68开始增加了autoType白名单校验机制老的JdbcRowSetImpl链打不进去。我踩过的典型例子是某个项目用到了Shiro版本是1.7.1。按照之前对Shiro 1.5.3的利用经验我以为可以正常打SimplePrincipalCollection反序列化结果发现官方早已修复了相关反序列化入口。白白浪费一晚上。正确的做法是拿到依赖清单后先做一轮“版本—漏洞”对照确定哪些组件仍然可用哪些已经修复。不要凭着记忆里的老PoC盲目尝试。5.3 多模块Maven项目的“审计黑洞”Java Web系统现在很少是单一Maven模块往往是parent-child多模块结构。我的经验是不要把时间花在每一个子模块上而有意识地抽象出“核心业务模块”和“基础设施模块”。快速判断方法很简单看controller包、service包、mapper包。Controller多的一般是Web入口Service层逻辑最多Mapper层可能嵌着SQL注入风险。而基础设施模块——比如通用工具类、配置中心、网关模块——一旦出现漏洞影响范围通常覆盖全部业务模块优先级反而更高。多模块项目还有一个问题模块间互相依赖会导致审计时数据流追踪特别冗长。一个参数从A模块进来到B模块的Service再穿透到C模块的Mapper。实际工作中我会用IDEA的Find Usages功能快速跳转把调用链拉通后再对最终Sink点做可控性判断。5.4 关于“服务器控制权”的合规边界这段话一定要说。做红队测试所有动作都必须以合法授权为前提。无论是代码审计还是后续的利用都必须在客户书面授权范围内执行。拿到服务器控制权只是过程不是目的——你最终要交付的是漏洞报告和修复建议而不是“展示你可以拿下它”。在实际项目中我一般会在控制权落地的第一时间收集关键证据比如当前用户权限、敏感文件列表、网络连接情况截图存档后立刻回退权限不给业务造成影响。这是专业红队的基本素养。6. 实战中的几条“保命”经验最后分享几条代码审计红队打点路上实打实趟出来的经验。第一不要忽略“不起眼”的接口。很多高危漏洞藏在导出、下载、PDF生成这类“边缘接口”里比如POI的XML外部实体注入、JasperReport的模板注入、iText的任意文件读取。审计时如果你的精力有限优先看文件相关接口收益通常远高于业务逻辑接口。第二日志文件是块宝。拿到代码后建议全局搜logback或log4j配置。很多开发为了排查问题会在日志里打印SQL参数、用户输入甚至服务端异常堆栈。你能从日志文件里读出一大批敏感信息比如日志路径配合任意文件读取漏洞轻松拖走数据库密码。第三备份文件是最后的甜点。有些系统很贴心地提供了.bak、.zip、/backup目录。红队测到后期我会顺手测试几个常见的备份路径比如/app.jar.bak、/web.config.old、/backup/prod.sql。如果目标项目代码审计没挖出明显的洞备份文件往往是打开局面的突破口。第四做一张“接口-漏洞-利用链”的速查表。每拿下一套系统我都会整理一张内部速查表记录接口路径、认证状态、漏洞类型、利用链、最终落地方式WebShell地址或命令执行证据。这套信息在写报告时价值极高更重要的是它能在后续横向渗透中帮你快速判断同一类型系统的弱点。我一直觉得Java Web代码审计之所以是红队技能树里最硬核的一环不是因为它“难”而是因为它需要你同时在代码逻辑、框架机制、网络环境和利用链设计之间来回切换视角。打点这件事说到底就是一个“不确定信息逐步收敛”的过程。代码审计能让你把不确定性压到最低把主动权攥在自己手里。这篇文章讲的是我自己的打点路线未必是唯一答案但希望它能在你面对一套陌生Java系统时帮你少走我走过的弯路。

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案