Souza2003/Vulnerability_Remediation_-_Verification
GitHub: Souza2003/Vulnerability_Remediation_-_Verification
这是一个针对 WebGoat 漏洞靶场的代码级安全修复实战项目,详细记录了结合 SAST 与 DAST 工具发现并修复 Java Spring Boot 应用中高危漏洞的全流程。
Stars: 0 | Forks: 0
# 🔼 漏洞修复与验证 — WebGoat 2023.4
**模块:** 软件开发网络安全
**项目:** 网络安全理学硕士 2025–26 | 都柏林商学院
**工具:** Semgrep · OWASP ZAP · Burp Suite · Windsurf · Java Spring Boot · Docker
## 概述
对 OWASP 的 intentionally vulnerable Java Spring Boot Web 应用程序 **WebGoat 2023.4** 进行了安全审计和代码级修复。使用 SAST (Semgrep) 和 DAST (OWASP ZAP) 工具识别出了三个高/严重级别漏洞,随后对其进行了全面修复和验证。
## 安全态势:修复前 vs 修复后
| | 修复前 | 修复后 |
|---|---|---|
| Semgrep 发现总数 | 156 | 153 |
| 严重漏洞 | 3 个活跃 | 0 (已全部修复) |
| 风险评级 | 高风险 | 已降低 |
| ZAP 重新扫描中的 PII 泄露 | 已检测到 | 未检测到 |
## 已修复漏洞
| # | 漏洞 | 工具 | 受影响文件 | 严重性 | 状态 |
|---|---|---|---|---|---|
| 1 | SQL 注入 | SAST — Semgrep | `Assignment5.java` (第 59–65 行) | 高危/严重 | ✅ 已完全修复 |
| 2 | 路径遍历 | SAST — Semgrep | `ProfileUploadRetrieval.java` + `FileServer.java` | 高危/严重 | ✅ 已完全修复 |
| 3 | PII 泄露 | DAST — OWASP ZAP | `CrossSiteScriptingLesson5a.java` (第 76 行) | 高危 | ✅ 已完全修复 |
## 漏洞 1 — SQL 注入 (CWE-89)
**根本原因:** 用户输入被直接拼接到 SQL 字符串中。虽然调用了 `prepareStatement()` 但从未真正实现参数化 —— 没有 `?` 占位符或 `setString()` 调用。
**修复措施:** 将字符串拼接替换为正确的参数化查询。
```
// BEFORE — vulnerable
PreparedStatement statement = connection.prepareStatement(
"select password from challenge_users where userid = '"
+ username_login + "' and password = '" + password_login + "'");
// AFTER — fixed
PreparedStatement statement = connection.prepareStatement(
"select password from challenge_users where userid = ? and password = ?");
statement.setString(1, username_login);
statement.setString(2, password_login);
```
**新增安全层:**
- 使用 `?` 占位符和 `setString()` 绑定的参数化查询
- 通过 `StringUtils.hasText()` (已有) 进行输入验证
- 通用错误处理 —— 原始数据库错误不会到达 HTTP 响应
## 漏洞 2 — 路径遍历 (CWE-22)
**根本原因:** 现有的过滤器只检查了字面上的 `..` 和 `/` —— 很容易被 URL 编码(`%2e%2e`, `%2f`)绕过。`getOriginalFilename()` 被直接使用而未经验证。
**修复措施:** 对两个受影响的文件实施了三层防御。
```
// AFTER — ProfileUploadRetrieval.java
// Layer 1: Whitelist — reject non-alphanumeric IDs
if (id != null && !id.matches("[a-zA-Z0-9_-]+")) {
return ResponseEntity.badRequest().body("Invalid id parameter");
}
// Layer 2: Strip directory components
String safeId = id != null ? FilenameUtils.getName(id) : null;
var catPicture = new File(catPicturesDirectory, (safeId == null ? RandomUtils.nextInt(1,11) : safeId) + ".jpg");
// Layer 3: Canonical path boundary check
if (!catPicture.getCanonicalPath().startsWith(catPicturesDirectory.getCanonicalPath())) {
return ResponseEntity.badRequest().body("Access denied");
}
```
```
// AFTER — FileServer.java
String originalName = myFile.getOriginalFilename();
if (originalName == null || !originalName.matches("[a-zA-Z0-9._-]+")) {
throw new IllegalArgumentException("Invalid filename");
}
String safeFilename = FilenameUtils.getName(originalName);
File destination = new File(destinationDir, safeFilename);
if (!destination.getCanonicalPath().startsWith(destinationDir.getCanonicalPath())) {
throw new SecurityException("Path traversal attempt detected");
}
```
## 漏洞 3 — PII 泄露 (CWE-359)
**根本原因:** 用户提供的信用卡号(Maestro BIN `505664`)在 `/CrossSiteScripting/attack5a` 端点的 HTTP 响应体中未经屏蔽地回传。
**修复措施:** 在卡号出现在任何 HTTP 响应之前对其进行屏蔽,将最后 4 位以外的所有数字替换为 `*`。
## 使用的工具
| 工具 | 用途 |
|---|---|
| Semgrep | SAST — 静态源代码分析 |
| OWASP ZAP | DAST — 运行时漏洞扫描 |
| Burp Suite | HTTP 请求/响应的手动验证 |
| Windsurf | 具有差异比较视图的 IDE,用于查看代码更改 |
| Docker | WebGoat 环境容器化 |
## 核心要点
- 仅使用 `prepareStatement()` **并不** 能使查询参数化 —— 还需要 `?` 占位符和 `setString()` 调用。
- URL 编码可以绕过简单的字符串匹配过滤器;规范路径解析才是防御路径遍历的正确方法。
- SAST 和 DAST 是互补的 —— Semgrep 捕获了代码级的缺陷;ZAP 捕获了静态分析遗漏的运行时 PII 泄露。
- 消除了 3 个严重发现;应用程序从高风险转变为安全态势得到了显著改善。
标签:AppImage, Burp Suite, CISA项目, CWE-200, CWE-22, CWE-89, DAST, DevSecOps, Docker, JS文件枚举, MSc网络安全, OWASP ZAP, PII泄露, SAST, Semgrep, Spring Boot, SQL查询, WebGoat, Web应用防火墙, WordPress安全扫描, 上游代理, 个人信息泄露, 代码安全审计, 安全扫描, 安全防御评估, 恶意软件分析, 数据泄露, 时序注入, 漏洞修复, 盲注攻击, 网络安全, 网络安全培训, 请求拦截, 路径遍历, 软件安全开发, 隐私保护