提交 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:
# 登录暴力破解最大尝试次数
......
......@@ -74,6 +74,31 @@ def run_tests(client, auth):
# ============================================================
results.append(_test_2_8_10(client, user_token))
# ============================================================
# 2.8.11: Nginx配置外露端点探测(基于配置分析)
# ============================================================
results.extend(_test_2_8_11(client))
# ============================================================
# 2.8.12: Nacos增强端点探测(基于历史漏洞经验)
# ============================================================
results.extend(_test_2_8_12(client))
# ============================================================
# 2.8.13: Swagger文档全路径探测(基于Nginx配置分析)
# ============================================================
results.extend(_test_2_8_13(client))
# ============================================================
# 2.8.14: TLS协议版本检查(基于Nginx配置分析)
# ============================================================
results.append(_test_2_8_14(client))
# ============================================================
# 2.8.15: SQL注入检测(基于历史漏洞回归测试)
# ============================================================
results.extend(_test_2_8_15(client, user_token))
log.info(f"API8 测试完成,共 {len(results)} 个用例")
return results
......@@ -1200,3 +1225,292 @@ def _test_2_8_10(client, user_token):
response_info=response_info,
is_vulnerable=False
)
# ================================================================
# 基于参考资料增强的测试函数(2.8.11 ~ 2.8.15)
# ================================================================
def _test_2_8_11(client):
"""2.8.11: Nginx配置外露端点探测(基于配置分析)"""
log.info("[2.8.11] Nginx配置外露端点探测...")
from utils.knowledge_base import NGINX_ANALYSIS, ENHANCED_PATH_DICTIONARIES
results = []
endpoints = NGINX_ANALYSIS["exposed_paths"] + ENHANCED_PATH_DICTIONARIES["nginx_exposed_paths"]
for ep in endpoints:
path = ep["path"]
desc = ep.get("desc", "")
severity = ep.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.8.11",
name=f"Nginx外露端点可访问: {path}",
level=level,
description=f"基于Nginx配置分析,{path}({desc})无需认证即可访问(HTTP 200),该端点不应在生产环境暴露。",
request_info=f"GET {path}(无认证)",
response_info=f"HTTP {status_code}",
is_vulnerable=True,
fix_suggestion=f"在Nginx配置中限制 {path} 路径的访问,或设置IP白名单仅允许内网访问。",
metadata={"is_regression": True, "vuln_source": "Nginx配置分析"},
))
log.info(f" [!] {path} 返回 200 — {desc}")
elif status_code in (301, 302, 307, 308):
results.append(VulnResult(
test_id="2.8.11",
name=f"Nginx外露端点重定向: {path}",
level=VulnResult.LEVEL_INFO,
description=f"基于Nginx配置分析,{path}({desc})返回 {status_code} 重定向,端点存活。",
request_info=f"GET {path}(无认证)",
response_info=f"HTTP {status_code}",
is_vulnerable=False,
metadata={"is_regression": True, "vuln_source": "Nginx配置分析"},
))
else:
log.info(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" Nginx端点探测: {vuln_count} 个可访问, {safe_count} 个已关闭")
return results
def _test_2_8_12(client):
"""2.8.12: Nacos增强端点探测(基于历史漏洞经验)"""
log.info("[2.8.12] Nacos增强端点探测...")
from utils.knowledge_base import ENHANCED_PATH_DICTIONARIES
results = []
nacos_paths = ENHANCED_PATH_DICTIONARIES["nacos_enhanced_paths"]
nacos_base = client.base_url.rstrip("/")
for item in nacos_paths:
path = item["path"]
desc = item.get("desc", "")
try:
full_url = f"{nacos_base}{path}"
resp = client.session.get(full_url, verify=False, timeout=15)
status_code = resp.status_code
body = resp.text[:500] if resp.text else ""
is_high_risk = any(kw in path for kw in ["env", "heapdump", "configs", "users"])
level = VulnResult.LEVEL_HIGH if is_high_risk else VulnResult.LEVEL_MEDIUM
if status_code == 200:
sensitive_keywords = ["password", "secret", "token", "config", "service"]
has_sensitive = any(kw in body.lower() for kw in sensitive_keywords)
results.append(VulnResult(
test_id="2.8.12",
name=f"Nacos端点可访问: {path}",
level=VulnResult.LEVEL_HIGH if has_sensitive else level,
description=f"基于历史漏洞经验,{path}({desc})可匿名访问(HTTP 200)。"
+ ("响应中包含敏感信息。" if has_sensitive else ""),
request_info=f"GET {path}(无认证)",
response_info=f"HTTP {status_code}\n{body[:500]}",
is_vulnerable=True,
fix_suggestion="1. 在Nginx层面拦截/nacos/路径;2. Nacos开启鉴权;3. 关闭Actuator端点。",
metadata={"is_regression": True, "vuln_source": "HV-002/HV-005 历史漏洞"},
))
log.info(f" [!] {path} 返回 200 — {desc}")
else:
log.info(f" [✓] {path} 返回 {status_code}")
except Exception as e:
log.debug(f" {path} 请求异常: {e}")
return results
def _test_2_8_13(client):
"""2.8.13: Swagger文档全路径探测(基于Nginx配置分析)"""
log.info("[2.8.13] Swagger文档全路径探测...")
from utils.knowledge_base import ENHANCED_PATH_DICTIONARIES
results = []
swagger_paths = ENHANCED_PATH_DICTIONARIES["swagger_enhanced_paths"]
for item in swagger_paths:
path = item["path"]
desc = item.get("desc", "")
try:
resp = client.get(path, token="", account=None)
status_code = resp.status_code if resp else 0
body = resp.text[:1000] if resp and resp.text else ""
if status_code == 200:
is_swagger = any(kw in body.lower() for kw in ["swagger", "openapi", "api-docs", "knife4j", "swagger-ui"])
if is_swagger:
results.append(VulnResult(
test_id="2.8.13",
name=f"Swagger文档暴露: {path}",
level=VulnResult.LEVEL_MEDIUM,
description=f"基于Nginx配置分析,{path}({desc})暴露了API文档。Nginx仅对/exapi/做了403拦截,该路径不在拦截范围内。",
request_info=f"GET {path}(无认证)",
response_info=f"HTTP {status_code}\n{body[:500]}",
is_vulnerable=True,
fix_suggestion=f"在Nginx中对 {path} 路径添加403拦截规则。",
metadata={"is_regression": True, "vuln_source": "HV-006 Nginx配置分析"},
))
log.info(f" [!] {path} 暴露Swagger文档 — {desc}")
else:
log.info(f" [✓] {path} 返回200但非Swagger内容")
else:
log.info(f" [✓] {path} 返回 {status_code}")
except Exception as e:
log.debug(f" {path} 请求异常: {e}")
return results
def _test_2_8_14(client):
"""2.8.14: TLS协议版本检查(基于Nginx配置分析)"""
log.info("[2.8.14] TLS协议版本检查...")
import ssl
import socket
server_ip = client.config.get("target", {}).get("server_ip", "")
if not server_ip:
return VulnResult(
test_id="2.8.14", name="TLS协议版本检查",
level=VulnResult.LEVEL_INFO,
description="未配置目标服务器IP,跳过TLS检查。",
is_vulnerable=False,
metadata={"is_huawei_redline": True, "hw_check_id": "HW-002", "hw_category": "传输安全",
"hw_requirement": "TLS版本不低于1.2,推荐TLS 1.3"},
)
tls_versions = {
"TLS 1.0": ssl.TLSVersion.TLSv1 if hasattr(ssl, 'TLSVersion') else None,
"TLS 1.1": ssl.TLSVersion.TLSv1_1 if hasattr(ssl, 'TLSVersion') else None,
"TLS 1.2": ssl.TLSVersion.TLSv1_2 if hasattr(ssl, 'TLSVersion') else None,
"TLS 1.3": ssl.TLSVersion.TLSv1_3 if hasattr(ssl, 'TLSVersion') else None,
}
supported = []
unsupported = []
for name, tls_ver in tls_versions.items():
if tls_ver is None:
unsupported.append(f"{name}(Python不支持检测)")
continue
try:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
context.maximum_version = tls_ver
context.minimum_version = tls_ver
with socket.create_connection((server_ip, 443), timeout=10) as sock:
with context.wrap_socket(sock, server_hostname=server_ip) as ssock:
supported.append(name)
except (ssl.SSLError, socket.error, OSError):
unsupported.append(name)
except Exception:
unsupported.append(name)
insecure_supported = [v for v in supported if v in ("TLS 1.0", "TLS 1.1")]
missing_tls13 = "TLS 1.3" not in supported
if insecure_supported:
level = VulnResult.LEVEL_MEDIUM
desc = f"目标服务器支持不安全的TLS版本: {', '.join(insecure_supported)}。TLS 1.0/1.1已被弃用。"
is_vuln = True
elif missing_tls13:
level = VulnResult.LEVEL_INFO
desc = f"支持: {', '.join(supported)};不支持: TLS 1.3。当前TLS 1.2可接受,建议升级。"
is_vuln = False
else:
level = VulnResult.LEVEL_INFO
desc = f"支持: {', '.join(supported)};TLS配置安全。"
is_vuln = False
log.info(f" TLS检查: 支持 {supported}, 不支持 {unsupported}")
return VulnResult(
test_id="2.8.14", name="TLS协议版本检查",
level=level, description=desc,
request_info=f"SSL连接到 {server_ip}:443",
response_info=f"支持: {', '.join(supported)};不支持: {', '.join(unsupported)}",
is_vulnerable=is_vuln,
fix_suggestion="在Nginx中配置 ssl_protocols TLSv1.2 TLSv1.3;如确认不需要TLS 1.0/1.1,显式禁用。",
metadata={"is_huawei_redline": True, "hw_check_id": "HW-002", "hw_category": "传输安全",
"hw_requirement": "TLS版本不低于1.2,推荐TLS 1.3"},
)
def _test_2_8_15(client, user_token):
"""2.8.15: SQL注入检测(基于历史漏洞回归测试)"""
log.info("[2.8.15] SQL注入检测(基于历史漏洞HV-001)...")
from utils.knowledge_base import SQL_INJECTION_PAYLOADS
results = []
sqli_targets = client.config.get("sql_injection_targets", [])
if not sqli_targets:
log.info(" 未配置sql_injection_targets,跳过SQL注入检测")
return results
error_indicators = SQL_INJECTION_PAYLOADS["error_indicators"]
for target in sqli_targets:
path = target["path"]
method = target.get("method", "GET").upper()
payload_type = target.get("payload_type", "string")
desc = target.get("description", path)
if payload_type == "numeric":
payloads = SQL_INJECTION_PAYLOADS["numeric_based"]
else:
payloads = SQL_INJECTION_PAYLOADS["string_based"]
vuln_found = False
request_infos = []
response_infos = []
for payload in payloads[:5]: # 每个接口最多测试5个payload
try:
if method == "GET":
resp = client.get(f"{path}?id={payload}&keyword={payload}", token=user_token)
else:
resp = client.post(path, json_data={"keyword": payload, "name": payload, "searchKey": payload}, token=user_token)
status_code = resp.status_code if resp else 0
body = resp.text[:2000] if resp and resp.text else ""
body_lower = body.lower()
found_errors = [ind for ind in error_indicators if ind in body_lower]
if found_errors:
vuln_found = True
request_infos.append(f"{method} {path}\nPayload: {payload}")
response_infos.append(f"HTTP {status_code}\nSQL错误关键词: {', '.join(found_errors)}\n{body[:500]}")
log.info(f" [!] {path} + '{payload}' 触发SQL错误: {found_errors}")
break
except Exception as e:
log.debug(f" {path} SQL注入测试异常: {e}")
if vuln_found:
results.append(VulnResult(
test_id="2.8.15",
name=f"SQL注入风险: {path}",
level=VulnResult.LEVEL_HIGH,
description=f"基于历史漏洞回归测试(HV-001),{desc} 在接收到SQL注入载荷时,响应中包含SQL错误信息,表明可能存在SQL注入漏洞。",
request_info="\n---\n".join(request_infos),
response_info="\n---\n".join(response_infos),
is_vulnerable=True,
fix_suggestion="1. 使用PreparedStatement预编译语句;2. 对用户输入进行合法性校验;3. 使用MyBatis等安全框架。",
metadata={"is_regression": True, "vuln_source": "HV-001 长安深蓝汽车项目"},
))
else:
log.info(f" [✓] {path} 未检测到SQL注入")
return results
......@@ -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
"""
安全测试知识库模块
整合自三份参考资料的经验数据:
1. Nginx配置文件分析(unified443.conf)
2. 历史漏洞报告(南山区委、长安深蓝汽车、天津海油等)
3. 华为安全红线资料(加密规范、基线测试、红线自检)
供各测试模块导入使用,实现基于经验数据的增强测试
"""
# ============================================================
# 一、Nginx 配置分析结果
# 来源:Z:\deploy\18其它系统\安全测试\03Nginx配置文件\unified443.conf
# ============================================================
NGINX_ANALYSIS = {
# 已知外露路径(从 Nginx 配置中发现)
"exposed_paths": [
{
"path": "/nacos/",
"proxy_target": "172.17.0.1:8848",
"desc": "Nacos控制台完全对外开放,无访问限制",
"severity": "high",
},
{
"path": "/test/",
"proxy_target": "172.17.0.1:8999",
"desc": "测试端点仍然存活,不应在生产环境暴露",
"severity": "medium",
},
{
"path": "/ws",
"proxy_target": "192.168.5.44:62121",
"desc": "WebSocket端点无认证即可连接",
"severity": "high",
},
{
"path": "/onlyoffice/",
"proxy_target": "172.17.0.1:18080",
"desc": "OnlyOffice文档服务对外暴露",
"severity": "medium",
},
{
"path": "/cache/",
"proxy_target": "172.17.0.1:18080",
"desc": "OnlyOffice缓存文件代理",
"severity": "medium",
},
],
# Nginx 配置中完全缺失的安全响应头
"missing_security_headers": [
"X-Frame-Options",
"Content-Security-Policy",
"Strict-Transport-Security",
"X-Content-Type-Options",
"X-XSS-Protection",
"Referrer-Policy",
"Permissions-Policy",
],
# 上传安全风险
"upload_risks": {
"max_body_size": "300M",
"file_type_restriction": "无",
"risk": "上传限制极大且无文件类型校验",
},
# TLS 配置
"tls_config": {
"protocols": ["TLSv1.2"],
"missing": ["TLSv1.3"],
"server_tokens": "off(已安全配置)",
"ssl_ciphers": "ALL:!RSA:!CAMELLIA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SHA1",
},
# 内部 IP 暴露(在 Nginx 配置注释和 proxy_pass 中)
"internal_ips_exposed": [
"172.17.0.1:8848", # Nacos
"172.17.0.1:8999", # 主应用
"172.17.0.1:9204", # 网关
"172.17.0.1:8000", # 运维集控
"172.17.0.1:8003", # 讯飞转录
"172.17.0.1:5000", # AI服务
"172.17.0.1:9990", # 桌牌
"172.17.0.1:18080", # OnlyOffice
"192.168.9.202:8089", # 讯飞热词
"192.168.9.124:8070", # 讯飞录音
"192.168.5.44:8888", # FastDFS
],
# 速率限制
"rate_limiting": {
"configured": False,
"risk": "Nginx层面无任何rate limiting配置,所有接口可被无限请求",
},
# Swagger 仅部分拦截
"swagger_partial_block": {
"blocked_path": "/exapi/",
"potentially_exposed": ["/api/", "/nacos/", "/monitor/", "/newmeeting/", "/oldmeeting/", "/voice/"],
"risk": "Swagger仅对/exapi/做了403拦截,其他路径下的Swagger文档可能暴露",
},
}
# ============================================================
# 二、历史漏洞回归测试用例
# 来源:Z:\deploy\18其它系统\安全测试\02项目漏洞资料\
# ============================================================
HISTORICAL_VULNS = [
{
"vuln_id": "HV-001",
"title": "SQL注入 - 会议预定接口",
"original_path": "/legacy/message/book",
"mapped_paths": ["/api/message/book", "/oldmeeting/api/message/book"],
"vuln_type": "SQL_INJECTION",
"severity": "high",
"source_project": "长安深蓝汽车",
"detection_method": "IAST插桩检测",
"regression_note": "验证会议预定接口是否已使用预编译语句",
},
{
"vuln_id": "HV-002",
"title": "Spring Actuator 信息泄露 - Nacos",
"mapped_paths": ["/nacos/actuator/", "/nacos/actuator/health", "/nacos/actuator/beans"],
"vuln_type": "INFO_DISCLOSURE",
"severity": "medium",
"source_project": "南山区委",
"detection_method": "XDR告警+手动验证",
"regression_note": "验证Nacos Actuator端点是否已关闭或被Nginx拦截",
},
{
"vuln_id": "HV-003",
"title": "安全响应头缺失(全站)",
"mapped_paths": ["全局"],
"vuln_type": "MISSING_HEADERS",
"severity": "medium",
"source_project": "厦门银行总行大厦、龙华儿童医院",
"detection_method": "华为Web漏扫",
"regression_note": "验证X-Frame-Options、CSP、HSTS等安全头是否已配置",
},
{
"vuln_id": "HV-004",
"title": "内部IP地址泄露",
"mapped_paths": ["多个接口"],
"vuln_type": "INFO_DISCLOSURE",
"severity": "low",
"source_project": "厦门银行总行大厦",
"detection_method": "华为Web漏扫",
"regression_note": "验证响应中是否不再暴露内网IP",
},
{
"vuln_id": "HV-005",
"title": "Nacos 未授权访问",
"mapped_paths": ["/nacos/", "/nacos/v1/cs/configs", "/nacos/v1/ns/service/list"],
"vuln_type": "UNAUTH_ACCESS",
"severity": "high",
"source_project": "南山区委",
"detection_method": "攻防演练",
"regression_note": "验证Nacos是否开启鉴权,配置列表和服务列表是否需Token",
},
{
"vuln_id": "HV-006",
"title": "Swagger 文档暴露",
"mapped_paths": ["/swagger-ui.html", "/v2/api-docs"],
"vuln_type": "INFO_DISCLOSURE",
"severity": "medium",
"source_project": "历史多个项目",
"detection_method": "手动探测",
"regression_note": "验证各路径下的Swagger文档是否已全部拦截",
},
{
"vuln_id": "HV-007",
"title": "固定验证码 csba",
"mapped_paths": ["/platform/api/auth/login"],
"vuln_type": "WEAK_AUTH",
"severity": "medium",
"source_project": "需求文档已确认",
"detection_method": "已知问题",
"regression_note": "记录为已知安全问题,验证是否已改为随机验证码",
},
{
"vuln_id": "HV-008",
"title": "密码SHA256无加盐哈希",
"mapped_paths": ["登录接口"],
"vuln_type": "WEAK_CRYPTO",
"severity": "medium",
"source_project": "网络抓包确认",
"detection_method": "已知问题",
"regression_note": "验证是否已升级为bcrypt/argon2等加盐哈希",
},
{
"vuln_id": "HV-009",
"title": "WebSocket端点无认证",
"mapped_paths": ["/ws"],
"vuln_type": "UNAUTH_ACCESS",
"severity": "high",
"source_project": "Nginx配置分析",
"detection_method": "配置审查",
"regression_note": "验证WebSocket连接是否需要认证",
},
{
"vuln_id": "HV-010",
"title": "HTTP方法未限制",
"mapped_paths": ["全局"],
"vuln_type": "MISCONFIG",
"severity": "medium",
"source_project": "厦门银行总行大厦",
"detection_method": "华为Web漏扫",
"regression_note": "验证TRACE/OPTIONS等方法是否已限制",
},
]
# ============================================================
# 三、SQL 注入测试载荷
# ============================================================
SQL_INJECTION_PAYLOADS = {
# 字符串型注入
"string_based": [
"' OR '1'='1",
"' OR '1'='1' --",
"' OR '1'='1' /*",
"1' OR '1'='1",
"' UNION SELECT NULL--",
"' UNION SELECT NULL,NULL--",
"admin'--",
"test' AND '1'='1",
"test' AND '1'='2",
],
# 数字型注入
"numeric_based": [
"1 OR 1=1",
"1 OR 1=1 --",
"1 UNION SELECT 1--",
"1 AND 1=1",
"1 AND 1=2",
"999999.999",
"0+1",
"1*1",
],
# 搜索型注入
"search_based": [
"%' OR '1'='1",
"%' OR '%'='",
"' AND '%'='",
"_' OR '_'='",
],
# SQL 错误响应特征(小写,用于检测响应中是否包含SQL错误信息)
"error_indicators": [
"sql syntax",
"mysql",
"sqlstate",
"ora-",
"postgresql",
"sqlerror",
"odbc",
"jdbc",
"incorrect syntax",
"unclosed quotation",
"quoted string not properly terminated",
"syntax error",
"unterminated string",
"nativeexception",
"sqlexception",
],
}
# ============================================================
# 四、华为安全红线检查项
# 来源:Z:\deploy\18其它系统\安全测试\01安全测试资料\
# ============================================================
HUAWEI_REDLINE_CHECKS = [
{
"check_id": "HW-001",
"category": "加密规范",
"requirement": "密码存储必须使用加盐哈希(如bcrypt/scrypt/Argon2),不得使用单纯SHA256",
"test_method": "检查登录接口密码加密方式",
"current_status": "使用SHA256无加盐(已知问题KN-02)",
},
{
"check_id": "HW-002",
"category": "传输安全",
"requirement": "所有API通信必须使用HTTPS,且TLS版本不低于1.2,推荐TLS 1.3",
"test_method": "检查TLS协议版本",
},
{
"check_id": "HW-003",
"category": "鉴权机制",
"requirement": "所有非公开接口必须经过鉴权校验,Token应有有效期限和刷新机制",
"test_method": "无Token访问需认证接口",
},
{
"check_id": "HW-004",
"category": "速率限制",
"requirement": "对外接口必须配置速率限制,防止暴力破解和DDoS",
"test_method": "连续高频请求检测限流",
},
{
"check_id": "HW-005",
"category": "输入校验",
"requirement": "所有用户输入必须进行严格的参数校验和过滤,防止SQL注入和XSS",
"test_method": "发送SQL注入和XSS载荷",
},
{
"check_id": "HW-006",
"category": "安全响应头",
"requirement": "Web应用必须配置完整的安全响应头(X-Frame-Options、CSP、HSTS等)",
"test_method": "检查HTTP响应头",
},
{
"check_id": "HW-007",
"category": "配置管理",
"requirement": "中间件管理界面(如Nacos)不得对外暴露",
"test_method": "探测Nacos等管理端点",
},
{
"check_id": "HW-008",
"category": "日志审计",
"requirement": "关键操作(登录、权限变更)必须有审计日志",
"test_method": "检查是否有操作日志接口",
},
]
# ============================================================
# 五、增强路径字典
# ============================================================
ENHANCED_PATH_DICTIONARIES = {
# 基于 Nginx 配置的已知外露路径
"nginx_exposed_paths": [
{"path": "/test/", "desc": "Nginx配置中代理到8999的测试端点", "severity": "medium"},
{"path": "/onlyoffice/", "desc": "OnlyOffice文档服务入口", "severity": "medium"},
{"path": "/onlyoffice/web-apps/", "desc": "OnlyOffice Web应用", "severity": "medium"},
{"path": "/cache/", "desc": "OnlyOffice缓存代理", "severity": "medium"},
{"path": "/ws", "desc": "WebSocket端点(可能无认证)", "severity": "high"},
],
# 基于历史漏洞经验扩展的 Nacos 路径
"nacos_enhanced_paths": [
{"path": "/nacos/", "desc": "Nacos控制台首页"},
{"path": "/nacos/v1/cs/configs?dataId=&group=&tenant=", "desc": "Nacos配置列表"},
{"path": "/nacos/v1/ns/service/list?pageNo=1&pageSize=100", "desc": "Nacos服务列表"},
{"path": "/nacos/v1/auth/login", "desc": "Nacos登录接口"},
{"path": "/nacos/v1/auth/users?pageNo=1&pageSize=10", "desc": "Nacos用户列表"},
{"path": "/nacos/actuator/", "desc": "Nacos Actuator根路径"},
{"path": "/nacos/actuator/health", "desc": "Nacos Actuator健康检查"},
{"path": "/nacos/actuator/beans", "desc": "Nacos Actuator Bean列表"},
{"path": "/nacos/actuator/env", "desc": "Nacos Actuator环境变量(高危)"},
{"path": "/nacos/actuator/heapdump", "desc": "Nacos Actuator堆转储(高危)"},
],
# 基于Nginx配置分析,不仅限于 /exapi/ 下的 Swagger
"swagger_enhanced_paths": [
{"path": "/swagger-ui.html", "desc": "Swagger UI 根路径"},
{"path": "/swagger-ui/", "desc": "Swagger UI 目录"},
{"path": "/v2/api-docs", "desc": "Swagger v2 JSON"},
{"path": "/v3/api-docs", "desc": "OpenAPI 3.0 JSON"},
{"path": "/doc.html", "desc": "knife4j文档页面"},
{"path": "/api/swagger-ui.html", "desc": "/api/下的Swagger UI"},
{"path": "/api/v2/api-docs", "desc": "/api/下的Swagger JSON"},
{"path": "/api/doc.html", "desc": "/api/下的knife4j"},
{"path": "/newmeeting/v2/api-docs", "desc": "新版会议Swagger"},
{"path": "/oldmeeting/v2/api-docs", "desc": "旧版会议Swagger"},
{"path": "/monitor/api2/api/v2/api-docs", "desc": "运维集控Swagger"},
{"path": "/voice/v2/api-docs", "desc": "讯飞转录Swagger"},
{"path": "/platform/v2/api-docs", "desc": "统一平台Swagger"},
{"path": "/nacos/v2/api-docs", "desc": "Nacos下的Swagger"},
],
# 历史漏洞中提到的旧版/遗留路径
"legacy_paths": [
{"path": "/legacy/message/book", "desc": "历史SQL注入漏洞路径(旧版映射)", "severity": "high"},
{"path": "/legacy/api/auth/login", "desc": "旧版登录接口"},
{"path": "/legacy/api/user/info", "desc": "旧版用户信息接口"},
{"path": "/api/upload/", "desc": "上传目录暴露", "severity": "medium"},
{"path": "/api/download/", "desc": "下载目录暴露", "severity": "medium"},
{"path": "/upload/", "desc": "根上传目录"},
{"path": "/download/", "desc": "根下载目录"},
{"path": "/files/", "desc": "文件服务目录"},
{"path": "/static/", "desc": "静态资源目录"},
{"path": "/temp/", "desc": "临时文件目录"},
{"path": "/backup/", "desc": "备份目录"},
{"path": "/log/", "desc": "日志目录"},
{"path": "/.git/", "desc": "Git仓库暴露"},
{"path": "/.env", "desc": "环境变量文件暴露"},
{"path": "/.DS_Store", "desc": "macOS目录信息文件"},
],
}
......@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论