Die Oberfläche ist lokalisiert; Skill-Beschreibungen und -Dokumente werden per KI automatisch in Ihre Sprache übersetzt. Code, Befehle, Pfade und Fachbegriffe bleiben im Original, maßgeblich ist das Dokument des Autors.
Skills entdecken
Entwicklung · SKILL.md

performing-web-application-vulnerability-triage

performing-web-application-vulnerability-triage

使用 OWASP 风险评级方法论对 DAST/SAST 扫描器的 Web 应用程序漏洞发现进行分类,区分真阳性和假阳性,并确定修复优先级。

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill-Dokumentation

GitHub

name: performing-web-application-vulnerability-triage description: 使用 OWASP 风险评级方法论对 DAST/SAST 扫描器的 Web 应用程序漏洞发现进行分类,区分真阳性和假阳性,并确定修复优先级。 domain: cybersecurity subdomain: vulnerability-management tags: [web-application, vulnerability-triage, owasp, dast, sast, burp-suite, zap, false-positive, risk-rating] version: "1.0" author: mahipal license: Apache-2.0

执行 Web 应用程序漏洞分类

概述

Web 应用程序漏洞分类(Triage)是审查 DAST(动态应用安全测试)和 SAST(静态应用安全测试)工具发现的过程,用于验证真阳性、排除假阳性、使用 OWASP 风险评级方法论分配风险等级,并确定修复优先级。有效的分类减少告警疲劳,使开发团队专注于最重要的漏洞。

前置条件

  • DAST 扫描结果(OWASP ZAP、Burp Suite、Acunetix)
  • SAST 扫描结果(Semgrep、SonarQube、Checkmarx、Snyk Code)
  • Python 3.9+,安装 requests、beautifulsoup4
  • Burp Suite Professional 或 OWASP ZAP 用于手动验证
  • DefectDojo 或类似工具用于发现管理

OWASP 风险评级方法论

风险计算

风险 = 可能性 × 影响

可能性因素(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": "访问控制失效",
    "A02": "加密失败",
    "A03": "注入",
    "A04": "不安全设计",
    "A05": "安全配置错误",
    "A06": "脆弱和过时组件",
    "A07": "身份识别和认证失败",
    "A08": "软件和数据完整性失败",
    "A09": "安全日志记录和监控失败",
    "A10": "服务器端请求伪造(SSRF)",
}

CWE_TO_OWASP = {
    "CWE-79": "A03",   # XSS -> 注入
    "CWE-89": "A03",   # SQL 注入
    "CWE-78": "A03",   # OS 命令注入
    "CWE-352": "A01",  # CSRF -> 访问控制
    "CWE-22": "A01",   # 路径遍历
    "CWE-200": "A02",  # 信息泄露
    "CWE-327": "A02",  # 弱加密
    "CWE-287": "A07",  # 认证问题
    "CWE-918": "A10",  # SSRF
    "CWE-502": "A08",  # 反序列化
    "CWE-611": "A05",  # XXE -> 配置错误
}

步骤 2:验证真阳性与假阳性

def triage_finding(finding):
    """将发现分类为 true_positive、false_positive 或 needs_review。"""
    fp_indicators = [
        "Content-Security-Policy header not set",  # 通常为信息性
        "X-Content-Type-Options header missing",    # 低严重性标头
        "Cookie without SameSite attribute",        # 取决于上下文
    ]

    for indicator in fp_indicators:
        if indicator.lower() in finding.get("title", "").lower():
            if finding.get("severity", "").lower() in ("info", "low"):
                return "false_positive", "常见信息性发现"

    # 检查已确认的利用证据
    if finding.get("evidence") and finding.get("confidence", "").lower() == "certain":
        return "true_positive", "扫描器已确认利用"

    # SAST 发现需要手动代码审查
    if finding.get("source") == "sast":
        if finding.get("cwe") in ["CWE-89", "CWE-78", "CWE-79"]:
            return "needs_review", "注入发现需要手动代码审查"

    return "needs_review", "需要手动验证"

步骤 3:风险评分计算

def calculate_risk_score(finding, app_context):
    """计算 Web 应用程序发现的 OWASP 风险等级。"""
    # 可能性因素
    likelihood = {
        "skill_level": 6 if finding["cwe"] in ["CWE-89", "CWE-79"] else 4,
        "motive": 7,  # 经济利益
        "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 = {
        "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 = "严重"
    elif risk_score >= 24:
        risk_level = "高"
    elif risk_score >= 12:
        risk_level = "中"
    elif risk_score >= 3:
        risk_level = "低"
    else:
        risk_level = "注意"

    return {
        "likelihood_score": round(likelihood_score, 1),
        "impact_score": round(impact_score, 1),
        "risk_score": round(risk_score, 1),
        "risk_level": risk_level,
    }

步骤 4:生成分类报告

# 通过分类流程处理 DAST/SAST 结果
python3 scripts/process.py \
  --input zap_results.json \
  --format zap \
  --app-context app_config.json \
  --output triage_report.json

手动验证技术

SQL 注入验证

# 使用单引号测试参数
GET /search?q=test' HTTP/1.1

# 使用基于布尔的载荷测试
GET /search?q=test' AND 1=1-- HTTP/1.1
GET /search?q=test' AND 1=2-- HTTP/1.1

# 基于时间的验证
GET /search?q=test'; WAITFOR DELAY '0:0:5'-- HTTP/1.1

XSS 验证

# 反射型 XSS 测试
GET /search?q=<script>alert(document.domain)</script> HTTP/1.1

# 检查输出是否已编码
GET /search?q="><img src=x onerror=alert(1)> HTTP/1.1

# DOM 型 XSS
GET /page#<img src=x onerror=alert(1)> HTTP/1.1

参考资料

Gespeicherte Skills