本文目录导读:

- 第一层:认证与授权漏洞(你是谁?能干什么?)
- 第二层:输入验证与注入(数据可信吗?)
- 第三层:敏感数据泄露与加密强度(数据安全吗?)
- 第四层:文件与资源管理(边界安全吗?)
- 第五层:第三方组件漏洞(依赖健壮吗?)
- 实操工具链与定位“三板斧”
- 总结:防守漏洞识别的“必须做”清单
在Java综合案例中识别和定位防守漏洞,本质上是一个“代码审计 + 运行时观察”的过程,漏洞不会自己跳出来,你需要有一套系统化的排查思路。
针对“防守”场景,我将其拆解为五大核心漏洞面,并给出具体的识别信号和定位工具/方法。
第一层:认证与授权漏洞(你是谁?能干什么?)
这是防守的第一道门,也是最容易被攻击的地方。
| 漏洞特征 | 识别信号(代码/日志) | 定位方法(问题定位) |
|---|---|---|
| 会话固定/劫持 | 会话ID在登录前后不改变;URL中携带JSESSIONID。 |
使用抓包工具(如Burp Suite)对比登录前后的Cookie,如果仅靠Cookie中的固定值而没有Token,且该值不变,即存在风险。 |
| 越权访问 (IDOR) | 查询语句使用用户可控参数直接查库,如UPDATE user SET ... WHERE id = {request.getParameter("id")}。 |
业务逻辑测试:登录普通用户A,抓包修改请求中的user_id为别的用户ID,若返回了别人的数据,则存在水平越权。 |
| JWT/Token密钥硬编码 | 代码中直接出现SecretKey或HS256常量,且没有从环境变量读取。 |
静态扫描:使用grep -r "secret" src/ 或 IDE的全局搜索,检查SecurityConfig或JwtUtil类中是否有默认密钥。 |
第二层:输入验证与注入(数据可信吗?)
攻击者最常用的入口,主要是通过构造恶意输入让后端解析器“失手”。
| 漏洞特征 | 识别信号(代码/日志) | 定位方法(问题定位) |
|---|---|---|
| SQL注入 | 日志中出现SQLSyntaxErrorException;代码使用String拼接SQL(而非PreparedStatement)。 |
报错注入:在搜索框输入或1 AND 1=1,观察500错误页面是否暴露了完整的SQL语句或堆栈信息。 |
| XSS (跨站脚本) | 前端将后端返回的text通过innerHTML直接插入页面,后端未过滤<script>
| |
| 命令注入 | 代码中调用了Runtime.getRuntime().exec()或ProcessBuilder,且参数未经过白名单校验。 |
延迟测试:在输入框中输入; sleep 10,观察接口响应是否恰好延迟10秒。 |
第三层:敏感数据泄露与加密强度(数据安全吗?)
防守不仅仅是防攻击,还要防“裸奔”。
| 漏洞特征 | 识别信号(代码/日志) | 定位方法(问题定位) |
|---|---|---|
| 密码明文存储 | 数据库表中password字段直接存储明文字符串,或在日志中打印出username=xx, pass=yy。 |
连库排查:查询数据库SELECT * FROM user LIMIT 5,如果密码看起来像是123456而非$2a$10$...(BCrypt),即存在漏洞。 |
| 越权导出/批量爬取 | API接口未做分页限制或频控(即没有RateLimiter)。 |
压测验证:使用脚本一次性请求/api/user/list?pageSize=100000,若返回全量数据且无403/429错误,则属于数据泄露。 |
| 日志泄露敏感信息 | 日志中打印了CardUtil或AESUtil的密钥,或打印了完整的Authorization头。 |
日志分析:在logback.xml或log4j2.xml中查找是否有%msg包含token或password字段的Pattern。 |
第四层:文件与资源管理(边界安全吗?)
这类漏洞往往导致服务器被直接拿下(RCE)。
| 漏洞特征 | 识别信号(代码/日志) | 定位方法(问题定位) |
|---|---|---|
| 任意文件上传 | 上传接口仅用getOriginalFilename()获取后缀,未校验Content-Type,且存储路径在Web根目录下。 |
上传测试:尝试上传一个.jsp或.php为恶意代码),然后直接访问该文件路径,若执行成功,即存在RCE风险。 |
| 路径穿越 (Zip Slip) | 使用new File(basePath + userInput)时,未对进行过滤。 |
构造Payload:在文件名中包含../../../../etc/passwd,查看下载接口是否返回了系统文件内容。 |
| 不安全反序列化 | 代码中存在ObjectInputStream.readObject(),且没有使用ObjectInputFilter。 |
工具探测:使用ysoserial生成一个针对Commons-Collections的Payload,将其通过Cookie或POST body传给接口,观察是否触发异常(如ClassNotFoundException或系统命令执行)。 |
第五层:第三方组件漏洞(依赖健壮吗?)
这属于“防”的盲区,使用过时的库也属于防守失职。
| 漏洞特征 | 识别信号 | 定位方法 |
|---|---|---|
| 已知CVE组件 | pom.xml或build.gradle中使用了Log4j1.x、Spring Boot < 2.5、Fastjson < 1.2.83等。 |
依赖扫描:使用Maven dependency-check 或 OWASP Dependency Check工具,运行后生成HTML报告,直接列出漏洞组件的具体路径和版本。 |
实操工具链与定位“三板斧”
在综合案例中,不要手读代码,请按以下顺序操作:
① 黑盒测试(找外部入口)
工具:Burp Suite (免费版足够) 操作:配置代理 → 访问所有接口 → 查看
HTTP History→ 寻找带参数的GET/POST请求 → 直接右键Send to Repeater修改参数值。
② 灰盒测试(定位代码位置)
工具:IDEA/IntelliJ 全局搜索(Ctrl+Shift+F) 或 Arthas(在线诊断) 操作:当你在数据包中看到某个报错
异常类名(如org.hibernate.exception.SQLGrammarException)时,直接在IDE中搜索该异常类的引用,或搜索writeObject、exec(等危险关键字,能快速缩小到具体的Service或Controller类。
③ 日志联动(查看攻击链)
工具:ELK 或 云日志服务 操作:拿到攻击者的IP,在日志中搜索该IP的访问记录,按时间线排序,查看其第一次访问的URL是哪个,然后去对应的实体类中寻找未校验的字段。
防守漏洞识别的“必须做”清单
面对一个综合案例,优先排查以下3个位置,命中率最高:
XxxController.java里的@RequestParam和@RequestBody:看参数是否直接传给了Service层去做SQL操作,且没有任何@Valid注解或白名单校验。XxxFilter.java或XxxInterceptor.java:检查doFilterInternal方法中是否合理地放行了某个路径,比如unfiltered路径中含有/admin或/download。application.yml中的spring.datasource和logging.level:看是否为开发便利把SQL日志打印级别设为了DEBUG,这会导致SQL语句泄露,配合前端参数即可构造注入。
在防守场景中,“审计日志”是你的第一目击证人,如果代码里连操作日志(谁、何时、做了什么操作)都没有,那本身就是最大的防守漏洞。