关于 performing-web-application-vulnerability-triage
用于审查 DAST 和 SAST 扫描结果的 Web 应用安全分流技能。帮助安全与开发团队验证告警,依据 OWASP 方法评估风险,并确定修复优先级。
主要功能
- 01按 OWASP Top 10 分类发现项
- 02验证真实与误报
- 03计算 OWASP 风险评级
- 04手动测试 SQL 注入与 XSS
- 05生成分流报告
适用场景
- 01审查 DAST 和 SAST 扫描结果
- 02确定 Web 漏洞修复优先级
- 03验证疑似 SQL 注入或 XSS
- 04整理结构化发现项以便跟踪
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill performing-web-application-vulnerability-triage安装后在 Claude Code 中输入/performing-web-application-vulnerability-triage确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdstandards.mdworkflows.mdscripts/agent.py详细介绍
Web 应用程序漏洞分诊
概述
Web 应用程序漏洞分诊是指审查 DAST(动态应用程序安全测试)和 SAST(静态应用程序安全测试)工具的发现结果,以验证真实阳性、驳回误报、使用 OWASP 风险评级方法分配风险等级,并确定修复优先级。有效的分诊可以减少告警疲劳,让开发团队专注于最重要的漏洞。
适用场景
- 开展涉及 Web 应用程序漏洞分诊的安全评估时
- 遵循相关安全事件的事件响应流程时
- 开展定期安全测试或审计活动时
- 通过动手测试验证安全控制时
前置条件
- DAST 扫描结果(OWASP ZAP、Burp Suite、Acunetix)
- SAST 扫描结果(Semgrep、SonarQube、Checkmarx、Snyk Code)
- Python 3.9+ 和
requests、beautifulsoup4 - 用于手动验证的 Burp Suite Professional 或 OWASP ZAP
- DefectDojo 或类似的发现结果管理工具
OWASP 风险评级方法
风险计算
Risk = Likelihood x Impact
可能性因素(0-9 分制)
| 因素组 | 因素 | 描述 |
|---|---|---|
| 威胁主体 | 技能水平 | 攻击者的技术能力有多强? |
| 威胁主体 | 动机 | 攻击者的动机有多强? |
| 威胁主体 | 机会 | 需要哪些资源或访问权限? |
| 威胁主体 | 规模 | 潜在威胁主体群体有多大? |
| 漏洞 | 发现难度 | 发现该漏洞有多容易? |
| 漏洞 | 利用难度 | 利用该漏洞有多容易? |
| 漏洞 | 认知程度 | 该漏洞的知名度有多高? |
| 漏洞 | 入侵检测 | 利用行为被检测到的可能性有多大? |
影响因素(0-9 分制)
| 因素组 | 因素 | 描述 |
|---|---|---|
| 技术 | 机密性 | 可能泄露多少数据? |
| 技术 | 完整性 | 可能破坏多少数据? |
| 技术 | 可用性 | 可能导致多少服务不可用? |
| 技术 | 可追责性 | 能否将操作追溯到攻击者? |
| 业务 | 财务损失 | 收入损失、监管罚款 |
| 业务 | 声誉损失 | 品牌信任度受损 |
| 业务 | 不合规 | 面临违规风险 |
| 业务 | 隐私侵犯 | PII/PHI 泄露量 |
风险矩阵
| 低影响(0-3) | 中等影响(3-6) | 高影响(6-9) | |
|---|---|---|---|
| 高可能性(6-9) | 中 | 高 | 严重 |
| 中等可能性(3-6) | 低 | 中 | 高 |
| 低可能性(0-3) | 注意 | 低 | 中 |
分诊流程
步骤 1:按 OWASP Top 10 分类
OWASP_TOP_10_2021 = {
"A01": "Broken Access Control",
"A02": "Cryptographic Failures",
"A03": "Injection",
"A04": "Insecure Design",
"A05": "Security Misconfiguration",
"A06": "Vulnerable and Outdated Components",
"A07": "Identification and Authentication Failures",
"A08": "Software and Data Integrity Failures",
"A09": "Security Logging and Monitoring Failures",
"A10": "Server-Side Request Forgery",
}
CWE_TO_OWASP = {
"CWE-79": "A03", # XSS -> Injection
"CWE-89": "A03", # SQL Injection
"CWE-78": "A03", # OS Command Injection
"CWE-352": "A01", # CSRF -> Access Control
"CWE-22": "A01", # Path Traversal
"CWE-200": "A02", # Information Exposure
"CWE-327": "A02", # Weak Cryptography
"CWE-287": "A07", # Authentication Issues
"CWE-918": "A10", # SSRF
"CWE-502": "A08", # Deserialization
"CWE-611": "A05", # XXE -> Misconfiguration
}
步骤 2:验证真实阳性与误报
def triage_finding(finding):
"""Classify finding as true_positive, false_positive, or needs_review."""
fp_indicators = [
"Content-Security-Policy header not set", # Often informational
"X-Content-Type-Options header missing", # Low severity header
"Cookie without SameSite attribute", # Context dependent
]
for indicator in fp_indicators:
if indicator.lower() in finding.get("title", "").lower():
if finding.get("severity", "").lower() in ("info", "low"):
return "false_positive", "Common informational finding"
# Check for confirmed exploitation evidence
if finding.get("evidence") and finding.get("confidence", "").lower() == "certain":
return "true_positive", "Scanner confirmed exploitation"
# SAST findings need manual code review
if finding.get("source") == "sast":
if finding.get("cwe") in ["CWE-89", "CWE-78", "CWE-79"]:
return "needs_review", "Injection finding requires manual code review"
return "needs_review", "Requires manual validation"
步骤 3:计算风险评分
def calculate_risk_score(finding, app_context):
"""Calculate OWASP risk rating for a web application finding."""
# Likelihood factors
likelihood = {
"skill_level": 6 if finding["cwe"] in ["CWE-89", "CWE-79"] else 4,
"motive": 7, # Financial gain
"opportunity": 7 if finding.get("authenticated") == False else 4,
"size": 9 if finding.get("internet_facing") else 4,
"ease_of_discovery": 8 if finding.get("scanner_detected") else 5,
"ease_of_exploit": 7 if finding.get("exploit_available") else 4,
"awareness": 6,
"intrusion_detection": 3 if app_context.get("waf_enabled") else 8,
}
# Impact factors
impact = {
"confidentiality": 9 if "data_exposure" in finding.get("tags", []) else 5,
"integrity": 9 if finding["cwe"] in ["CWE-89", "CWE-78"] else 4,
"availability": 7 if "dos" in finding.get("tags", []) else 2,
"accountability": 3 if app_context.get("logging_enabled") else 7,
"financial": 7 if app_context.get("processes_payments") else 3,
"reputation": 6 if app_context.get("customer_facing") else 2,
"compliance": 8 if app_context.get("pci_scope") else 3,
"privacy": 9 if app_context.get("handles_pii") else 2,
}
likelihood_score = sum(likelihood.values()) / len(likelihood)
impact_score = sum(impact.values()) / len(impact)
risk_score = likelihood_score * impact_score
if risk_score >= 42:
risk_level = "Critical"
elif risk_score >= 24:
risk_level = "High"
elif risk_score >= 12:
risk_level = "Medium"
elif risk_score >= 3:
risk_level = "Low"
else:
risk_level = "Note"
return {
"likelihood_score": round(likelihood_score, 1),
"impact_score": round(impact_score, 1),
"risk_score": round(risk_score, 1),
"risk_level": risk_level,
}
步骤 4:生成分诊报告
# Process DAST/SAST results through triage pipeline
python3 scripts/process.py \
--input zap_results.json \
--format zap \
--app-context app_config.json \
--output triage_report.json
手动验证技术
SQL 注入验证
# Test parameter with single quote
GET /search?q=test' HTTP/1.1
# Test with boolean-based payload
GET /search?q=test' AND 1=1-- HTTP/1.1
GET /search?q=test' AND 1=2-- HTTP/1.1
# Time-based verification
GET /search?q=test'; WAITFOR DELAY '0:0:5'-- HTTP/1.1
XSS 验证
# Reflected XSS test
GET /search?q=<script>alert(document.domain)</script> HTTP/1.1
# Check if output is encoded
GET /search?q="><img src=x onerror=alert(1)> HTTP/1.1
# DOM-based XSS
GET /page#<img src=x onerror=alert(1)> HTTP/1.1
参考资料
评论
支持 Markdown