# 漏洞成立条件判断表

本文档定义各类漏洞的精确判断条件，避免"看到危险函数就报漏洞"的假阳性问题。

---

## 1. Fastjson 反序列化

### 判断流程

```
发现 JSON.parseObject() / JSON.parse() 调用
↓
检查版本：
  < 1.2.24 → 直接可利用（TemplatesImpl/JdbcRowSetImpl 利用链）
  1.2.25-1.2.41 → 检查 autoType：
    - autoType=true → L;描述符绕过
  1.2.42 → 检查 autoType：
    - autoType=true → LL;;双写绕过
  1.2.43 → 检查 autoType：
    - autoType=true → [数组描述符绕过
  1.2.44-1.2.45 → 检查 autoType：
    - autoType=true → 新 gadget 绕过黑名单
  1.2.47 → 无需 autoType：
    - Class 缓存绕过（最严重版本）
  1.2.48-1.2.68 → 检查 expectClass：
    - Throwable/AutoCloseable 子类绕过
  1.2.69-1.2.80 → 检查 classpath：
    - groovy → 可利用
    - commons-io ≥ 2.x → 可利用
  ≥ 1.2.83 → 检查 safeMode：
    - safeMode = true → 安全
    - safeMode = false → 风险
```

### Fastjson 危险版本速查

| 版本范围 | 绕过方式 | 需要 AutoType |
|----------|----------|---------------|
| ≤ 1.2.24 | TemplatesImpl/JdbcRowSetImpl | 否 |
| 1.2.25-41 | L;描述符 | 是 |
| 1.2.42 | LL;;双写 | 是 |
| 1.2.43 | [数组描述符 | 是 |
| 1.2.44-46 | 黑名单绕过 | 是 |
| 1.2.47 | Class缓存绕过 | **否**（最危险） |
| 1.2.48-67 | 黑名单更新 | 是 |
| 1.2.68 | expectClass绕过 | 否 |
| 1.2.69-80 | 新gadget | 视情况 |
| ≥ 1.2.83 | safeMode | 需配置 |

### 关键配置检查

```bash
# 检查版本
grep -rn "fastjson" pom.xml
grep -rn "fastjson" build.gradle

# 检查 autoType 配置
grep -rn "ParserConfig.getGlobalInstance().setAutoTypeSupport\|safeMode" --include="*.java"
```

---

## 2. Jackson 反序列化

### 判断流程

```
发现 ObjectMapper.readValue() / enableDefaultTyping() 调用
↓
检查配置：
  enableDefaultTyping() 已调用 → 检查 polymorphic type validation：
    - 无验证 → 可利用
    - 有白名单验证 → 检查白名单是否可绕过
  activateDefaultTyping() 已调用 → 同上
  未开启多态类型 → 需要检查是否有 @JsonTypeInfo 注解
```

### 关键配置检查

```bash
# 检查多态类型配置
grep -rn "enableDefaultTyping\|activateDefaultTyping\|@JsonTypeInfo" --include="*.java"
```

---

## 3. JNDI 注入

### 判断流程

```
发现 InitialContext.lookup(userInput) 调用
↓
检查 JDK 版本：
  < 8u191 → 直接可利用（远程类加载）
  ≥ 8u191 → trustURLCodebase 默认 false，需要本地 Gadget：
    - classpath 有 Tomcat → BeanFactory + ELProcessor 可利用
    - classpath 有 Groovy → GroovyClassLoader 可利用
    - 有 SecurityManager → 检查权限配置
```

### 关键配置检查

```bash
# 检查 JNDI 调用
grep -rn "InitialContext\.lookup\|JdbcRowSetImpl\|setDataSourceName" --include="*.java"

# 检查 JDK 版本
java -version
```

---

## 4. Velocity SSTI

### 判断流程

```
发现 Velocity.evaluate() / VelocityEngine.evaluate() 调用
↓
检查 SecureUberspector 配置：
  未配置 → 可利用（反射调用 Runtime.exec）
  已配置 → 检查自定义 Uberspector 是否有绕过
↓
检查模板内容来源：
  来自用户输入 → 可利用
  来自数据库（用户可写）→ 可利用
  硬编码模板 → 不可利用（但检查是否有模板注入点）
```

### 关键配置检查

```bash
# 检查 Velocity 使用
grep -rn "Velocity\.evaluate\|VelocityEngine\|mergeTemplate" --include="*.java"

# 检查 SecureUberspector 配置
grep -rn "SecureUberspector\|runtime.introspector.uberspect" --include="*.java"
```

### 安全配置示例

```java
VelocityEngine ve = new VelocityEngine();
ve.setProperty("runtime.introspector.uberspect", 
    "org.apache.velocity.util.introspection.SecureUberspector");
```

---

## 5. FreeMarker SSTI

### 判断流程

```
发现 Template.process() / FreeMarkerConfigurer 调用
↓
检查配置：
  new() 内置指令未禁用 → 可利用
  API 内置指令未启用 → 部分缓解
↓
检查模板来源：
  用户可控 → 可利用
```

### 关键配置检查

```bash
# 检查 FreeMarker 使用
grep -rn "freemarker\.template\|Template\.process\|FreeMarkerConfigurer" --include="*.java"

# 检查安全配置
grep -rn "setNewBuiltinClassResolver\|setAPIBuiltinEnabled" --include="*.java"
```

---

## 6. Thymeleaf SSTI

### 判断流程

```
发现 SpringTemplateEngine / TemplateEngine.process() 调用
↓
检查模板解析器配置：
  用户输入作为模板名 → 路径穿越 → 可能导致 SSTI
  用户输入作为模板内容 → 直接 SSTI
```

### 关键配置检查

```bash
# 检查 Thymeleaf 使用
grep -rn "SpringTemplateEngine\|TemplateEngine\.process\|ThymeleafViewResolver" --include="*.java"
```

---

## 7. SQL 注入

### MyBatis ${} 注入

```
发现 ${param} 在 SQL 语句中
↓
检查参数来源：
  直接来自用户输入 → 可注入
  经过预处理/白名单 → 检查过滤是否可绕过
```

### JDBC 原生注入

```
发现 Statement.executeUpdate() / executeQuery() 使用字符串拼接
↓
检查拼接内容：
  包含用户输入 → 可注入
  仅硬编码常量 → 不可注入
```

### 关键检查

```bash
# MyBatis ${} 注入
grep -rn '\$\{' --include="*.xml"

# JDBC 原生注入
grep -rn "Statement\|createStatement\|executeQuery\|executeUpdate" --include="*.java"
grep -rn '"+.*+"\|.*+.*+' --include="*.java" | grep -i "select\|insert\|update\|delete"
```

---

## 8. SSRF

### 判断流程

```
发现 URL() / HttpURLConnection / HttpClient / RestTemplate 调用
↓
检查 URL 来源：
  来自用户输入 → 可 SSRF
  来自配置文件 → 检查配置文件是否用户可修改
↓
检查协议限制：
  无限制 → 可访问 file://、gopher:// 等
  仅 HTTP/HTTPS → 限制利用范围
```

### 关键检查

```bash
# 检查 SSRF 入口点
grep -rn "URL(\|HttpURLConnection\|HttpClient\|RestTemplate\|WebClient" --include="*.java"

# 检查 URL 参数来源
grep -rn "@RequestParam\|@PathVariable\|@RequestBody" --include="*.java" | grep -i url
```

---

## 9. 文件上传漏洞

### 判断流程

```
发现 MultipartFile / getOriginalFilename() / transferTo() 调用
↓
检查文件名验证：
  无验证 → 路径穿越 + 任意文件写入
  后缀白名单 → 检查是否可绕过（双写、空字节、大小写）
  后缀黑名单 → 检查是否遗漏危险后缀
↓
检查文件内容验证：
  无验证 → 可上传恶意文件
  有验证 → 检查验证是否可绕过
```

### 关键检查

```bash
# 检查文件上传点
grep -rn "MultipartFile\|getOriginalFilename\|transferTo" --include="*.java"

# 检查文件名验证
grep -rn "getOriginalFilename\|endsWith\|startsWith" --include="*.java" | grep -i file
```

### 文件上传绕过技术（来自 javasec.org）

#### 1. QP编码绕过

Apache commons fileupload 从 1.3 开始支持 RFC 2047 Header 值编码：

```
原始文件名: 测试.jsp
QP编码后: =?UTF-8?Q?=E6=B5=8B=E8=AF=95=2Ejsp?=
```

**Payload示例**:
```
Content-Disposition: form-data; name="file"; filename="=?UTF-8?Q?=E6=B5=8B=E8=AF=95=2Ejsp?="
```

#### 2. filename* 绕过（Spring MVC）

Spring 4/5 支持 RFC 5987 的 filename* 参数：

```
Content-Disposition: form-data; name="file"; filename*="UTF-8''1.jsp"
Content-Disposition: form-data; name="file"; filename*="UTF-8'1.jpg'1.jsp"
```

Spring 会解析 `filename*` 参数，`1.jpg` 会被丢弃，最终文件名为 `1.jsp`。

#### 3. Content-Type 校验绕过

仅检查 `getContentType()` 可被绕过：
- 修改请求包的 Content-Type 头
- 使用合法类型但内容为恶意代码

#### 4. 双扩展名绕过

```
shell.php.jpg
shell.jsp%00.jpg (空字节截断，低版本JDK)
```

---

## 10. 命令注入

### 判断流程

```
发现 Runtime.exec() / ProcessBuilder 调用
↓
检查命令构造方式：
  字符串拼接用户输入 → 可注入
  数组形式传入 → 检查数组元素是否用户可控
↓
检查输入验证：
  无验证 → 直接可注入
  有黑名单 → 检查是否可绕过（编码、命令分隔符变种）
```

### 关键检查

```bash
# 检查命令执行点
grep -rn "Runtime\.getRuntime\|ProcessBuilder\|exec(" --include="*.java"

# 检查命令参数来源
grep -rn "@RequestParam\|@PathVariable" --include="*.java" | grep -i "cmd\|command\|exec"
```

---

## 11. 认证绕过

### 判断流程

```
发现 @PreAuthorize / @Secured / hasRole 等注解缺失
或
发现 permitAll() / anonymous() 配置
↓
检查端点敏感程度：
  敏感操作（删除、修改、导出）→ 可能是认证绕过
  非敏感操作 → 需要确认是否设计如此
↓
检查是否有其他认证机制：
  Filter 层认证 → 检查 Filter 匹配规则
  Interceptor 层认证 → 检查拦截器配置
```

### 关键检查

```bash
# 检查安全注解
grep -rn "@PreAuthorize\|@Secured\|@RolesAllowed\|hasRole\|hasAuthority" --include="*.java"

# 检查 permitAll 配置
grep -rn "permitAll\|anonymous\|authenticated" --include="*.java"

# 检查 Controller 端点
grep -rn "@GetMapping\|@PostMapping\|@PutMapping\|@DeleteMapping" --include="*.java"
```

---

## 12. SpEL 注入

### 判断流程

```
发现 SpelExpressionParser / parseExpression / evaluateExpression 调用
↓
检查表达式来源：
  硬编码 → 不可利用
  用户输入 → 可注入
↓
检查上下文：
  StandardEvaluationContext → 完全可控，高危
  SimpleEvaluationContext → 限制反射，但仍需检查
```

### 关键检查

```bash
# 检查 SpEL 使用
grep -rn "SpelExpressionParser\|parseExpression\|evaluateExpression\|StandardEvaluationContext" --include="*.java"
```

---

## 13. SnakeYAML 反序列化

### 判断流程

```
发现 Yaml() 构造或 yaml.load() 调用
↓
检查配置：
  无 SafeConstructor → 可利用（加载任意类）
  有 SafeConstructor → 部分缓解，但仍需检查
↓
检查版本：
  < 1.31 → 多个 RCE 漏洞
  ≥ 2.0 → 默认启用 SafeConstructor
```

### 关键检查

```bash
# 检查 SnakeYAML 使用
grep -rn "new Yaml\|yaml.load\|YamlParser" --include="*.java"
```

---

## 14. MVEL 表达式注入

### 判断流程

```
发现 MVEL.eval() / MVEL.executeExpression() 调用
↓
检查表达式来源：
  硬编码 → 不可利用
  用户输入 → 可利用（直接 RCE）
```

### 关键检查

```bash
# 检查 MVEL 使用
grep -rn "MVEL.eval\|MVEL.executeExpression\|MVEL.compileExpression" --include="*.java"
```

---

## 15. XXE (XML External Entity)

### 判断流程

```
发现 XMLReader / SAXParser / DocumentBuilder / XMLInputFactory 使用
↓
检查安全配置：
  未禁用外部实体 → 可利用（读取文件/SSRF）
  已禁用 → 检查是否有绕过方式
```

### 关键检查

```bash
# 检查 XML 解析器
grep -rn "XMLReader\|SAXParser\|DocumentBuilder\|XMLInputFactory" --include="*.java"

# 检查安全配置
grep -rn "setFeature.*external\|disallow-doctype-decl\|IS_SUPPORTING_EXTERNAL_ENTITIES" --include="*.java"
```

### 安全配置示例

```java
// SAXParser 安全配置
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
```

---

## 使用指南

1. **先识别危险模式**：通过 Layer 1 预扫描发现危险函数调用
2. **再判断成立条件**：根据本文档的判断流程逐一检查
3. **记录判断依据**：在报告中说明每一步的检查结果
4. **标记正确状态**：完全确认 → CONFIRMED，有不确定因素 → HYPOTHESIS

---

## 16. 业务逻辑漏洞 - 代码分析判断

### 16.1 支付金额篡改

**代码分析要点**：

```
检查支付接口代码：
1. 金额参数是否来自前端传入？
   - @RequestParam BigDecimal amount → 危险
   - 从数据库/订单表读取 → 安全
2. 是否有后端金额校验？
   - 检查是否与订单金额一致
   - 检查是否 >= 0
3. 价格是否可被篡改？
   - 商品单价是否从数据库读取
   - 折扣是否可被前端控制
```

**关键检查**：

```bash
# 搜索支付相关代码
grep -rn "pay\|payment\|amount\|price" --include="*.java" | grep -i "controller\|service"

# 检查金额参数来源
grep -rn "@RequestParam.*amount\|@RequestBody.*amount" --include="*.java"
```

**判断示例**：
```java
// ❌ 危险：金额来自前端
@PostMapping("/pay")
public Result pay(@RequestParam BigDecimal amount, @RequestParam String orderId) {
    return paymentService.pay(amount, orderId);
}

// ✅ 安全：金额从订单读取
@PostMapping("/pay")
public Result pay(@RequestParam String orderId) {
    Order order = orderService.getById(orderId);
    return paymentService.pay(order.getAmount(), orderId);
}
```

### 16.2 库存并发问题

**代码分析要点**：

```
检查库存扣减代码：
1. 是否有并发控制？
   - synchronized 关键字
   - 数据库悲观锁 (SELECT FOR UPDATE)
   - Redis 分布式锁
   - 乐观锁 (version 字段)
2. 库存检查和扣减是否原子操作？
   - 先查后扣 → 并发问题
   - UPDATE ... WHERE stock > 0 → 原子操作
```

**关键检查**：

```bash
# 搜索库存相关代码
grep -rn "stock\|inventory\|库存" --include="*.java" | grep -i "update\|decrease\|deduct"

# 检查锁使用
grep -rn "synchronized\|@Lock\|RedisLock\|SELECT.*FOR UPDATE" --include="*.java"
```

**判断示例**：
```java
// ❌ 危险：先查后扣，非原子操作
public boolean deductStock(Long productId, int count) {
    Product product = productDao.getById(productId);
    if (product.getStock() >= count) {
        product.setStock(product.getStock() - count);  // 并发时可能超卖
        productDao.update(product);
        return true;
    }
    return false;
}

// ✅ 安全：原子操作
@Update("UPDATE product SET stock = stock - #{count} WHERE id = #{id} AND stock >= #{count}")
int deductStock(@Param("id") Long id, @Param("count") int count);
```

### 16.3 订单状态机绕过

**代码分析要点**：

```
检查订单状态流转：
1. 是否有状态机校验？
   - 状态流转规则是否硬编码
   - 是否可从前端直接修改状态
2. 敏感操作是否校验前置状态？
   - 发货 → 订单必须是"已支付"
   - 退款 → 订单必须是"已支付"或"已发货"
```

**关键检查**：

```bash
# 搜索状态更新代码
grep -rn "setStatus\|updateStatus\|status =" --include="*.java" | grep -i "order\|订单"

# 检查状态校验
grep -rn "if.*status\|switch.*status\|stateMachine" --include="*.java"
```

---

## 17. 越权漏洞 - 代码分析判断

### 17.1 水平越权

**代码分析要点**：

```
检查数据访问接口：
1. 数据查询是否校验归属？
   - 查询条件是否包含 userId
   - userId 是否从 Session/Token 获取（不可伪造）
2. 数据修改是否校验归属？
   - UPDATE/DELETE 是否有 userId 条件
   - 是否检查数据归属
```

**关键检查**：

```bash
# 搜索通过 ID 查询的接口
grep -rn "getById\|findById\|selectById\|getOne" --include="*.java" | grep -i "controller"

# 检查是否有 userId 校验
grep -rn "userId\|user_id\|createBy\|ownerId" --include="*.java" | grep -i "where\|condition\|filter"
```

**判断示例**：
```java
// ❌ 危险：无归属校验
@GetMapping("/order/{id}")
public Order getOrder(@PathVariable Long id) {
    return orderService.getById(id);  // 任何登录用户都能查看
}

// ✅ 安全：校验归属
@GetMapping("/order/{id}")
public Order getOrder(@PathVariable Long id, @AuthenticationPrincipal User user) {
    Order order = orderService.getById(id);
    if (!order.getUserId().equals(user.getId())) {
        throw new AccessDeniedException("无权访问");
    }
    return order;
}
```

### 17.2 垂直越权

**代码分析要点**：

```
检查权限控制：
1. 接口是否有权限注解？
   - @PreAuthorize("hasRole('ADMIN')")
   - @Secured("ROLE_ADMIN")
2. 权限配置是否完整？
   - 所有管理接口是否有权限控制
   - 是否有遗漏的接口
3. 前后端权限是否一致？
   - 前端隐藏按钮 vs 后端无校验
```

**关键检查**：

```bash
# 找出所有管理接口
grep -rn "@.*Mapping\|@RequestMapping" --include="*.java" | grep -i "admin\|manage\|delete\|update"

# 检查这些接口是否有权限注解
grep -rn "@PreAuthorize\|@Secured\|@RolesAllowed" --include="*.java"
```

**判断示例**：
```java
// ❌ 危险：管理接口无权限控制
@RestController
@RequestMapping("/admin/user")
public class AdminUserController {
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {  // 任何登录用户都能删除
        userService.delete(id);
    }
}

// ✅ 安全：有权限控制
@RestController
@RequestMapping("/admin/user")
public class AdminUserController {
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public void deleteUser(@PathVariable Long id) {
        userService.delete(id);
    }
}
```

---

## 18. 依赖安全 - 版本分析

### 18.1 危险依赖版本检查

**Maven 项目**：

```bash
# 检查 pom.xml 中的依赖版本
grep -E "<(groupId|artifactId|version)>" pom.xml

# 关键依赖版本检查
grep -rn "log4j\|fastjson\|shiro\|struts\|spring-boot-starter-parent" --include="pom.xml"
```

**Gradle 项目**：

```bash
# 检查 build.gradle 中的依赖版本
grep -rn "implementation\|compile\|version" --include="build.gradle"
```

### 18.2 联网搜索验证漏洞

**使用 web_search 工具查询漏洞**：

```
搜索格式：<组件名> <版本号> CVE vulnerability
示例：
- "log4j 2.14.1 CVE"
- "fastjson 1.2.79 vulnerability"  
- "shiro 1.2.4 CVE"
- "spring boot 2.5.0 CVE"
```

**关键漏洞快速参考**：

| 依赖 | 危险版本 | 安全版本 | CVE | 搜索关键词 |
|------|----------|----------|-----|------------|
| Log4j2 | < 2.17.1 | ≥ 2.17.1 | CVE-2021-44228 | log4j Log4Shell |
| Fastjson | < 1.2.83 | ≥ 1.2.83 | 多个 RCE | fastjson autoType |
| Shiro | < 1.13.0 | ≥ 1.13.0 | CVE-2016-4437 等 | shiro rememberme |
| Spring | < 5.3.18 | ≥ 5.3.18 | CVE-2022-22965 | Spring4Shell |
| Tomcat | < 9.0.62 | ≥ 9.0.62 | 多个 RCE | tomcat CVE |
| Struts2 | 多个版本 | 最新 | 多个 RCE | struts2 CVE |
| Jackson | 多个版本 | 最新 | 多个反序列化 | jackson deserialization |

**联网搜索工作流**：

```
1. 读取 pom.xml 提取依赖信息
   <dependency>
     <groupId>org.apache.logging.log4j</groupId>
     <artifactId>log4j-core</artifactId>
     <version>2.14.1</version>  ← 提取版本
   </dependency>

2. 使用 web_search 搜索漏洞
   query: "log4j-core 2.14.1 CVE vulnerability"
   
3. 分析搜索结果
   - 查找 NVD (nvd.nist.gov) 链接
   - 查找官方安全公告
   - 确认漏洞严重程度和利用条件

4. 验证是否受影响
   - 对比版本范围
   - 检查是否有缓解配置
   - 评估实际风险

5. 输出结论
   - 漏洞名称和 CVE
   - 严重程度
   - 影响范围
   - 修复建议（升级版本）
```

**搜索结果分析示例**：

```
搜索 "log4j 2.14.1 CVE" 后可能得到：

1. NVD 页面: https://nvd.nist.gov/vuln/detail/CVE-2021-44228
   - CVSS 评分: 10.0 (Critical)
   - 影响版本: Apache Log4j2 2.0-beta9 through 2.15.0
   - 修复版本: 2.17.1+

2. 官方公告: https://logging.apache.org/log4j/2.x/security.html
   - 确认 2.14.1 在受影响范围内
   - 建议立即升级到 2.17.1+

结论：该依赖存在 Log4Shell 漏洞 (CVE-2021-44228)，
      需要升级到 log4j-core 2.17.1 或更高版本。
```

### 18.3 常用漏洞信息源

| 来源 | URL | 说明 |
|------|-----|------|
| **NVD** | https://nvd.nist.gov/ | 美国国家漏洞数据库 |
| **CVE** | https://cve.mitre.org/ | CVE 官方 |
| **GitHub Advisory** | https://github.com/advisories | GitHub 安全公告 |
| **Snyk Vulnerability DB** | https://security.snyk.io/ | Snyk 漏洞库 |
| **Maven Repository** | https://mvnrepository.com/ | 依赖版本信息 |

### 18.4 判断方法

1. 读取 `pom.xml` 或 `build.gradle`
2. 提取依赖版本号
3. **使用 web_search 搜索漏洞信息**
4. 对比安全版本
5. 标记需要升级的依赖

**代码示例**：

```xml
<!-- pom.xml -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.79</version>  <!-- 危险版本，需搜索验证 -->
</dependency>
```

**搜索验证**：
```
web_search: "fastjson 1.2.79 CVE vulnerability"
→ 发现多个 RCE 漏洞
→ 建议升级到 1.2.83+
```

---

## 19. 运行时配置 - 配置文件分析

### 19.1 Session 安全配置

**检查 application.yml/properties**：

```yaml
# 检查 Session 超时
server:
  servlet:
    session:
      timeout: 30m  # 超时时间

# 检查 Cookie 配置
server:
  servlet:
    session:
      cookie:
        http-only: true   # 必须 true
        secure: true      # 生产环境必须 true
        same-site: strict # CSRF 防护
```

**关键检查**：

```bash
# 检查 Session 配置
grep -rn "session\|cookie" --include="*.yml" --include="*.properties" | grep -i "timeout\|secure\|http-only"
```

### 19.2 敏感端点暴露

**检查 Actuator 配置**：

```yaml
# 危险配置
management:
  endpoints:
    web:
      exposure:
        include: "*"  # 暴露所有端点

# 安全配置
management:
  endpoints:
    web:
      exposure:
        include: health,info  # 仅暴露必要端点
  endpoint:
    health:
      show-details: never  # 不显示详情
```

### 19.3 数据库连接安全

**检查数据源配置**：

```yaml
# 检查密码是否明文
spring:
  datasource:
    password: root123  # ❌ 明文密码
    
# 安全配置
spring:
  datasource:
    password: ${DB_PASSWORD}  # ✅ 环境变量
```

---

## 24. Oracle Java 安全编码指南要点（官方权威）

### 24.1 基础原则

| 原则 | 说明 |
|------|------|
| **最小权限** | 代码以最小权限运行，限制攻击面 |
| **信任边界** | 跨边界数据必须验证和净化 |
| **封装** | 字段 private，接口简洁一致 |
| **第三方代码安全** | 跟踪安全更新，使用依赖检查工具 |

### 24.2 拒绝服务防护

| 攻击类型 | 防护措施 |
|----------|----------|
| **大图像/向量** | 限制尺寸 |
| **整数溢出** | 使用 `Math.addExact()`，检查 `current > max - extra` |
| **Zip炸弹** | 限制解压后大小 |
| **XML实体扩展** | 设置 `FEATURE_SECURE_PROCESSING` |
| **哈希冲突** | 避免用户输入作为哈希键 |
| **正则回溯** | 限制正则复杂度 |

### 24.3 敏感信息保护

| 场景 | 规范 |
|------|------|
| **异常信息** | 净化后再传播，不暴露文件路径 |
| **日志记录** | 禁止记录密码、SSN 等高度敏感信息 |
| **内存清理** | 敏感数据用后清零（char[]） |

### 24.4 注入防护

| 注入类型 | 防护措施 |
|----------|----------|
| **SQL注入** | 使用 `PreparedStatement`，避免动态 SQL |
| **XML/HTML注入** | 使用库进行编码，输出转义 |
| **命令注入** | 避免用户输入在命令行，使用编码/Base64 |
| **XXE** | 禁用 DTD，设置安全特性 |
| **JNDI注入** | 禁用远程代码加载，设置安全属性 |

### 24.5 反序列化安全

```java
// 使用反序列化过滤器 (JEP 290)
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
    "java.base/*;com.example.SafeClass;!*"
);
ObjectInputStream ois = new ObjectInputStream(input);
ois.setObjectInputFilter(filter);
```

### 24.6 访问控制

| 措施 | 说明 |
|------|------|
| **类可见性** | 非 API 类声明为 package-private |
| **方法可见性** | 非 API 方法声明为 private |
| **final类** | 防止恶意子类覆盖方法 |
| **sealed类** | Java 15+，限制可继承的类 |
| **模块封装** | 非导出包对外不可见 |

---

## 26. 组件配置安全检查

### 26.1 Spring Boot Actuator 配置安全

| 配置项 | 危险配置 | 安全配置 |
|--------|----------|----------|
| **端点暴露** | `management.endpoints.web.exposure.include=*` | `include=health,info` |
| **管理端口** | 与应用端口相同 | `management.server.port=8081` |
| **访问权限** | 默认 unrestricted | `management.endpoints.access.default=none` |
| **安全认证** | 无 | Spring Security + ENDPOINT_ADMIN |

**检查命令**：
```bash
grep -rn "management.endpoints.web.exposure.include\|management.server.port" --include="*.yml" --include="*.properties"
```

### 26.2 Shiro rememberMe 密钥安全

| 版本 | 问题 | 解决方案 |
|------|------|----------|
| ≤ 1.2.4 | 默认硬编码密钥 | 升级到 1.7.0+ 并自定义密钥 |
| 1.2.5-1.7.0 | 密钥可爆破 | 升级到 1.7.0+ |
| ≥ 1.7.0 | 安全 | 自定义密钥 |

**默认密钥**：`kPH+bIxk5D2deZiIxcaaaA==`

**检查命令**：
```bash
grep -rn "cipherKey\|rememberMe" --include="*.xml" --include="*.ini" --include="*.yml"
```

### 26.3 Druid 监控安全

| 配置项 | 风险 |
|--------|------|
| `druid.stat-view-servlet.enabled=true` | /druid/index.html 未授权访问 |
| 无 login-username/password | 敏感信息泄露 |

**检查命令**：
```bash
grep -rn "druid.stat-view-servlet" --include="*.yml" --include="*.properties"
```

### 26.4 Nacos 认证安全

| 配置 | 说明 |
|------|------|
| 默认无认证 | 任何人可读写配置 |
| `nacos.core.auth.enabled=true` | 启用认证 |

### 26.5 数据库连接安全

| 配置项 | 风险 |
|--------|------|
| 明文密码 | 配置文件泄露导致数据库被攻击 |
| 明文 JDBC URL | 可能包含敏感信息 |

**安全配置示例**：
```yaml
spring:
  datasource:
    password: ${DB_PASSWORD}
    url: ${DB_URL}
```

---

## 27. 代码审计检查清单汇总

| 类别 | 检查方法 | 工具/命令 |
|------|----------|-----------|
| **业务逻辑** | 代码分析 | Read + 逻辑追踪 |
| **越权漏洞** | 参数追踪 + 权限检查 | grep + Read |
| **依赖安全** | 版本对比 | 读取 pom.xml |
| **运行时配置** | 配置文件分析 | 读取 .yml/.properties |

---

## 21. JDBC Attack（来自 Y4tacker/JavaSec）

### 判断流程

```
发现 DriverManager.getConnection() / DataSource.setUrl() 调用
↓
检查 URL 是否用户可控：
  用户可控 → JDBC Attack 风险
  硬编码 → 安全
↓
检查 JDBC URL 参数：
  MySQL autoDeserialize=true → 反序列化 RCE
  H2 INIT=RUNSCRIPT → RCE
  PostgreSQL loggerLevel/socketFactory → RCE
  Apache Derby 网络模式 → SSRF
  SQLite 恶意数据库文件 → 代码执行
```

### 各数据库攻击向量

| 数据库 | 危险参数 | 攻击类型 |
|--------|----------|----------|
| **MySQL** | `autoDeserialize=true` | 反序列化 RCE |
| **H2** | `INIT=RUNSCRIPT FROM 'http://...'` | RCE |
| **PostgreSQL** | `socketFactory/socketFactoryArg` | RCE |
| **Apache Derby** | 网络模式 | SSRF |
| **SQLite** | 恶意数据库文件 | 本地代码执行 |
| **IBM DB2** | JNDI 注入 | RCE |
| **ModeShape** | JNDI 注入 | RCE |

### 关键检查

```bash
# 检查 JDBC URL 是否用户可控
grep -rn "DriverManager.getConnection\|setUrl\|setJdbcUrl" --include="*.java"

# 检查危险参数
grep -rn "autoDeserialize\|INIT=\|RUNSCRIPT\|socketFactory" --include="*.java"
```

---

## 22. 内存马检测（来自 Y4tacker/JavaSec）

### 判断流程

```
发现动态注册组件代码
↓
检查注册类型：
  addFilter → Filter 型内存马
  addServlet → Servlet 型内存马
  addListener → Listener 型内存马
↓
检查组件内容：
  包含命令执行代码 → 内存马
  正常业务逻辑 → 安全
```

### 内存马类型

| 类型 | 注入方式 | 检测方法 |
|------|----------|----------|
| **Filter 型** | `addFilter()` | 检查 FilterChain |
| **Servlet 型** | `addServlet()` | 检查 ServletMapping |
| **Listener 型** | `addListener()` | 检查 EventListener |
| **Valve 型** | `getPipeline().addValve()` | Tomcat 特有 |
| **Interceptor 型** | Spring 拦截器 | 检查 HandlerInterceptor |
| **Controller 型** | 动态注册 Controller | Spring 特有 |
| **Agent 型** | Java Instrument | JVM 层面 |

### 关键检查

```bash
# 检查动态注册
grep -rn "addFilter\|addServlet\|addListener\|addValve\|registerMapping" --include="*.java"

# 检查可疑类名
grep -rn "MemShell\|MemoryShell\|WebShell" --include="*.java"
```

---

## 23. 反序列化利用链速查（来自 Y4tacker/JavaSec）

### Commons Collections 利用链

| 链 | 触发条件 | 依赖版本 |
|----|----------|----------|
| **CC1** | `InvokerTransformer.transform()` | CC 3.1-4.0 |
| **CC2** | `InvokerTransformer.transform()` + `TemplatesImpl` | CC 4.0 |
| **CC3** | `InstantiateTransformer.transform()` | CC 3.1-4.0 |
| **CC5** | `BadAttributeValueExpException.readObject()` | CC 3.1-4.0 |
| **CC6** | `TiedMapEntry.hashCode()` | CC 3.1-4.0 |
| **CC7** | `Hashtable.readObject()` | CC 3.1-4.0 |

### 其他常见利用链

| 链 | 触发条件 | 依赖 |
|----|----------|------|
| **CB1** | `BeanComparator.compare()` | Commons Beanutils |
| **JDK7u21** | `AnnotationInvocationHandler.readObject()` | JDK < 7u21 |
| **JDK8u20** | 反射绕过 | JDK 7u21-8u20 |
| **C3P0** | `JndiRefForwardingDataSource` | C3P0 |
| **FileUpload** | `DiskFileItem.readObject()` | Commons FileUpload |
| **AspectJWeaver** | 写文件 | AspectJWeaver |
| **ROME** | `ToStringBean.toString()` | ROME |

### SnakeYAML 利用链

```
触发条件：
  new Yaml().load(userInput)
  未使用 SafeConstructor

利用类：
  ScriptEngineManager
  JNDI
  Spring PropertyPathFactoryBean
```

### Hessian 利用链

```
触发条件：
  new HessianInput().readObject()
  new Hessian2Input().readObject()

特点：
  hessian-only-jdk 链无需第三方依赖
  支持 JDK 11 的 jdk.jfr.internal.Utils 利用
```
| **并发安全** | 锁机制检查 | grep + 代码分析 |
| **状态机** | 状态流转检查 | Read + 流程图 |