提交 495ecfeb authored 作者: 陈泽健's avatar 陈泽健

feat(security): 增强API安全测试功能支持历史漏洞回归和华为安全红线检查

- 新增config.yaml配置项支持Nginx配置分析、SQL注入测试目标和历史漏洞回归测试
- 扩展report_generator.py支持历史漏洞回归验证和华为安全红线合规性检查报告生成
- 实现test_api08_misconfig.py新增5个测试函数:Nginx外露端点探测、Nacos增强端点探测、
  Swagger文档全路径探测、TLS协议版本检查、SQL注入检测(基于历史漏洞回归测试)
- 增强test_api09_inventory.py实现Legacy旧版接口探测(基于历史漏洞映射)
- 新增utils/knowledge_base.py知识库模块,整合Nginx配置分析、历史漏洞数据、
  SQL注入载荷和华为安全红线检查项
- 扩展VulnResult类增加metadata字段用于标记回归测试和华为安全红线检查属性
上级 e59bf9c6
......@@ -56,3 +56,4 @@ __pycache__/
/AuxiliaryTool/ScriptTool/ApiSecurityTest/reports/
/AuxiliaryTool/ScriptTool/RemoteUpdate/reports/
/AuxiliaryTool/FunctionalTestReportGeneration/testcases/
/AuxiliaryTool/ScriptTool/ApiSecurityTest/requirements.txt
......@@ -64,6 +64,55 @@ report:
# 报告文件名前缀
prefix: "api_security_report"
# Nginx 配置分析结果(来自 unified443.conf 分析)
nginx_analysis:
# 已知端口映射(从Nginx配置中提取的内部服务端口)
known_port_mappings:
nacos: 8848
test_endpoint: 8999
gateway: 9204
monitor: 8000
voice: 8003
ai: 5000
onlyoffice: 18080
fastdfs: 8888
# 已知外露路径(需验证是否仍可访问)
known_exposed_paths:
- /nacos/
- /test/
- /ws
- /onlyoffice/
- /cache/
# 已知TLS配置
tls_versions:
- TLSv1.2
server_tokens_off: true
# SQL注入测试目标接口(基于历史漏洞 HV-001 映射)
sql_injection_targets:
- path: "/api/message/book"
method: "POST"
description: "会议预定接口(历史SQL注入漏洞映射)"
payload_type: "string"
- path: "/api/manageUser/getManagerPage"
method: "POST"
description: "用户列表查询接口"
payload_type: "string"
- path: "/api/conference/select"
method: "POST"
description: "会议查询接口"
payload_type: "string"
- path: "/api/message/getMessagePageList"
method: "POST"
description: "会议列表分页接口"
payload_type: "string"
# 历史漏洞回归测试配置
regression_testing:
enabled: true
# 历史漏洞路径返回404时,标记为"已修复(接口已下线)"
mark_404_as_fixed: true
# 测试限制配置(防止影响服务稳定性)
limits:
# 登录暴力破解最大尝试次数
......
......@@ -280,10 +280,18 @@ def _test_2091_hidden_api_detection(client, auth):
log.info("[2.9.1] 隐藏接口探测 - 扫描路径字典...")
results = []
# 动态合并知识库中的增强路径
from utils.knowledge_base import ENHANCED_PATH_DICTIONARIES
all_hidden_paths = list(HIDDEN_PATHS)
for item in ENHANCED_PATH_DICTIONARIES["nginx_exposed_paths"] + ENHANCED_PATH_DICTIONARIES["legacy_paths"]:
p = item["path"]
if p not in all_hidden_paths:
all_hidden_paths.append(p)
# 存储发现的活跃隐藏接口
discovered_paths = []
for path in HIDDEN_PATHS:
for path in all_hidden_paths:
try:
# 不带 Token 直接请求,测试未授权访问
resp = client.get(path, token="", account=None)
......@@ -981,6 +989,19 @@ def run_tests(client, auth):
description=f"测试执行异常: {e}", is_vulnerable=False,
))
# ============================================================
# 2.9.8: Legacy旧版接口探测(基于历史漏洞映射)
# ============================================================
try:
all_results.extend(_test_2098_legacy_api_detection(client))
except Exception as e:
log.error(f"[2.9.8] Legacy旧版接口探测执行异常: {e}")
all_results.append(VulnResult(
test_id="2.9.8", name="Legacy旧版接口探测",
level=VulnResult.LEVEL_INFO,
description=f"测试执行异常: {e}", is_vulnerable=False,
))
# 统计结果
vuln_count = sum(1 for r in all_results if r.is_vulnerable)
log.info("=" * 50)
......@@ -989,3 +1010,94 @@ def run_tests(client, auth):
log.info("=" * 50)
return all_results
# ================================================================
# 基于参考资料增强的测试函数
# ================================================================
def _test_2098_legacy_api_detection(client):
"""2.9.8: Legacy旧版接口探测(基于历史漏洞映射)"""
log.info("[2.9.8] Legacy旧版接口探测(基于历史漏洞映射)...")
from utils.knowledge_base import ENHANCED_PATH_DICTIONARIES, HISTORICAL_VULNS
results = []
regression_config = client.config.get("regression_testing", {})
mark_404_as_fixed = regression_config.get("mark_404_as_fixed", True)
# 收集所有历史漏洞映射路径
test_paths = []
# 从知识库的 legacy_paths 获取
for item in ENHANCED_PATH_DICTIONARIES["legacy_paths"]:
test_paths.append({
"path": item["path"],
"desc": item.get("desc", ""),
"severity": item.get("severity", "medium"),
"source": "历史漏洞/配置分析",
})
# 从 HISTORICAL_VULNS 提取映射路径
for vuln in HISTORICAL_VULNS:
for mapped_path in vuln.get("mapped_paths", []):
if mapped_path != "全局" and mapped_path != "多个接口":
test_paths.append({
"path": mapped_path,
"desc": vuln["title"],
"severity": "high" if vuln["severity"] == "high" else "medium",
"source": f"{vuln['vuln_id']} {vuln['source_project']}",
})
# 去重
seen = set()
unique_paths = []
for tp in test_paths:
if tp["path"] not in seen:
seen.add(tp["path"])
unique_paths.append(tp)
log.info(f" 共 {len(unique_paths)} 个Legacy/历史漏洞路径待检测")
for tp in unique_paths:
path = tp["path"]
desc = tp.get("desc", "")
source = tp.get("source", "")
severity = tp.get("severity", "medium")
try:
# 先匿名访问
resp = client.get(path, token="", account=None)
status_code = resp.status_code if resp else 0
if status_code == 200:
level = VulnResult.LEVEL_HIGH if severity == "high" else VulnResult.LEVEL_MEDIUM
results.append(VulnResult(
test_id="2.9.8",
name=f"历史漏洞路径仍可访问: {path}",
level=level,
description=f"基于历史漏洞回归测试,{path}({desc})仍可匿名访问(HTTP 200)。来源: {source}",
request_info=f"GET {path}(无认证)",
response_info=f"HTTP {status_code}",
is_vulnerable=True,
fix_suggestion=f"下线或限制 {path} 路径的访问。",
metadata={"is_regression": True, "vuln_source": source},
))
log.info(f" [!] {path} 返回 200 — {desc}(来源: {source})")
elif status_code == 404 and mark_404_as_fixed:
results.append(VulnResult(
test_id="2.9.8",
name=f"历史漏洞路径已下线: {path}",
level=VulnResult.LEVEL_INFO,
description=f"基于历史漏洞回归测试,{path}({desc})返回404,接口已下线。来源: {source}",
request_info=f"GET {path}(无认证)",
response_info=f"HTTP 404",
is_vulnerable=False,
metadata={"is_regression": True, "vuln_source": source},
))
else:
log.debug(f" {path} 返回 {status_code}")
except Exception as e:
log.debug(f" {path} 请求异常: {e}")
vuln_count = sum(1 for r in results if r.is_vulnerable)
safe_count = sum(1 for r in results if not r.is_vulnerable)
log.info(f" Legacy探测: {vuln_count} 个仍可访问, {safe_count} 个已修复/已下线")
return results
......@@ -18,7 +18,7 @@ class VulnResult:
def __init__(self, test_id, name, level, description,
request_info="", response_info="",
is_vulnerable=False, fix_suggestion=""):
is_vulnerable=False, fix_suggestion="", metadata=None):
"""
初始化测试结果
......@@ -31,6 +31,7 @@ class VulnResult:
response_info: 响应信息(用于复现)
is_vulnerable: 是否存在漏洞
fix_suggestion: 修复建议
metadata: 额外元数据(如 is_regression/is_huawei_redline 标记)
"""
self.test_id = test_id
self.name = name
......@@ -40,6 +41,7 @@ class VulnResult:
self.response_info = response_info
self.is_vulnerable = is_vulnerable
self.fix_suggestion = fix_suggestion
self.metadata = metadata or {}
# OWASP 模块定义,用于覆盖矩阵
......@@ -358,6 +360,37 @@ class ReportGenerator:
L.append(f"| {kn_id} | {desc} | {level} | {source} |")
L.append("")
# ========== 五.五、历史漏洞回归验证 ==========
regression_results = [r for r in self.results if r.metadata.get("is_regression")]
if regression_results:
L.append("## 五.五、历史漏洞回归验证\n")
L.append("> 以下测试用例基于历史漏洞报告和Nginx配置分析,验证已知安全问题是否已修复。\n")
L.append("| 编号 | 漏洞来源 | 测试项 | 当前状态 | 风险等级 | 详情 |")
L.append("|------|---------|--------|---------|---------|------|")
for r in regression_results:
source = r.metadata.get("vuln_source", "历史漏洞报告")
status = "🔴 未修复" if r.is_vulnerable else "✅ 已修复/已验证安全"
desc_short = r.description[:80] + "..." if len(r.description) > 80 else r.description
L.append(f"| {r.test_id} | {source} | {r.name} | {status} | {r.level} | {desc_short} |")
L.append("")
# ========== 五.六、华为安全红线合规性检查 ==========
hw_results = [r for r in self.results if r.metadata.get("is_huawei_redline")]
if hw_results:
L.append("## 五.六、华为安全红线合规性检查\n")
L.append("> 以下检查项基于华为安全红线要求,验证系统是否符合安全基线标准。\n")
L.append("| 检查编号 | 检查类别 | 要求 | 测试结果 | 合规状态 |")
L.append("|---------|---------|------|---------|---------|")
for r in hw_results:
hw_id = r.metadata.get("hw_check_id", "")
hw_category = r.metadata.get("hw_category", "")
hw_requirement = r.metadata.get("hw_requirement", "")
if len(hw_requirement) > 60:
hw_requirement = hw_requirement[:57] + "..."
compliance = "🔴 不合规" if r.is_vulnerable else "✅ 合规"
L.append(f"| {hw_id} | {hw_category} | {hw_requirement} | {r.name} | {compliance} |")
L.append("")
# ========== 六、测试环境与工具 ==========
L.append("## 六、测试环境与工具\n")
L.append("| 项目 | 详情 |")
......@@ -365,7 +398,7 @@ class ReportGenerator:
L.append(f"| 目标服务器 | {self._extract_server_info()} |")
L.append("| 测试工具 | Python + requests + pycryptodome |")
L.append("| 测试框架 | 自研 ApiSecurityTest |")
L.append("| 测试标准 | OWASP API Security Top 10 (2019) |")
L.append("| 测试标准 | OWASP API Security Top 10 (2019) + 华为安全红线 + 历史漏洞回归 |")
L.append("| 报告格式 | Markdown(一份总报告) |")
L.append("")
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论