fix: 六引擎误报根因修复 — 解包递归、YARA 恒真规则、签名分级、real_type 溢出
检测范围与证据链修复,不改裁决口径(口径改动在下一条提交)。 - extractor:zip/tar 成员在超限分支外漏加回扫描队列,解包后内容永远不参与检测; zip 目录条目被当成内嵌对象;tar 超限成员先落盘不删。递归真正生效后深扫耗时可测。 - clamav:_HIGH/_MEDIUM/_UNWANTED 关键词是小写,而签名名是 "Win.Trojan..." 大小写混排, 分级判定恒不命中全走默认档;改统一大写匹配。超过 clamd MaxFileSize 的裸奔区间 (1G~1.5G) 新增 ClamAVSkippedSizeLimit(30) — 按"不可扫描不放行"进复核。 - yara:pe.yar C1 系列改用导入表判定,不再靠裸子串命中字符串表; linux.yar C7 多条规则条件恒真(裸 nc/fetch 之类)已收紧;C8/C3 相应收窄。 - structure:DangerousExecutableExtension 是载体信号而非恶意行为,critical 权重 45→35, 不再作为把中低置信度信号一起顶过 block_score 的底座。 - scanner/documents:real_type 拼进 libmagic 对 MSI/OLE 的元数据串实测 334+ 字符, 超列宽导致整条 scan_tasks INSERT 连 findings 一起丢(被拒文件不留痕)→ 列宽 256→512,migrate.sql 补 ALTER。
This commit is contained in:
@@ -56,6 +56,19 @@ EML_EXTS = {".eml", ".msg"}
|
||||
# 带 VBA 宏的 Office 扩展名(用于 VBA 纯文本扫描触发)
|
||||
VBA_MACRO_OFFICE_EXTS = OLE_EXTS | OOXML_EXTS | {".bas", ".vba", ".cls", ".frm"}
|
||||
|
||||
# OOXML 包内的内嵌 OLE 部件目录
|
||||
EMBED_PREFIX_RE = re.compile(r"^(?:word|xl|ppt)/embeddings/.+")
|
||||
|
||||
# 内嵌对象中的办公载体:文档互嵌(子表格/图表/PDF)是正常用法,不等于藏可执行
|
||||
OFFICE_PART_EXTS = {
|
||||
".docx", ".docm", ".xlsx", ".xlsm", ".pptx", ".pptm",
|
||||
".doc", ".xls", ".ppt", ".pdf", ".rtf", ".xml", ".txt", ".csv",
|
||||
".htm", ".html", ".wmf", ".emf", ".bin",
|
||||
}
|
||||
|
||||
# 内嵌部件里直接判定为可执行对象的扩展名
|
||||
EXEC_PART_EXTS = {".exe", ".dll", ".scr", ".js", ".jse", ".vbs", ".vbe", ".bat", ".cmd", ".ps1", ".hta", ".com", ".msi"}
|
||||
|
||||
# VBA 自动执行入口关键词
|
||||
VBA_AUTOEXEC_PATTERNS = [
|
||||
r"Sub\s+AutoOpen\s*\(", r"Sub\s+AutoExec\s*\(", r"Sub\s+AutoNew\s*\(",
|
||||
@@ -211,14 +224,16 @@ class DocumentEngine(Engine):
|
||||
else:
|
||||
parser.close()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
# 宏流解析不了 = 内容不可判定。这类畸形 OLE 常被用来探测解析器异常,
|
||||
# 给 0 分等于"看不懂就放行",落人工复核。
|
||||
findings.append(
|
||||
Finding(
|
||||
engine=self.name,
|
||||
layer=self.layer,
|
||||
severity=Severity.LOW.value,
|
||||
severity=Severity.MEDIUM.value,
|
||||
rule="OleToolsUnavailable",
|
||||
detail=f"VBA 宏解析失败:{exc}",
|
||||
weight=0.0,
|
||||
weight=30.0,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -407,6 +422,24 @@ class DocumentEngine(Engine):
|
||||
"excerpt": excerpt,
|
||||
}
|
||||
|
||||
def _looks_like_executable(self, zf: Any, name: str) -> bool:
|
||||
"""判断内嵌部件是否为可执行载荷(扩展名 + 文件头魔数)。
|
||||
|
||||
oleObject1.bin 之类的外壳里可能装着真正的 PE,光看扩展名会漏;
|
||||
反之把每个 .bin 都判成可执行又会拦掉正常的图表/子文档。
|
||||
"""
|
||||
if os.path.splitext(name)[1].lower() in EXEC_PART_EXTS:
|
||||
return True
|
||||
try:
|
||||
with zf.open(name) as fp:
|
||||
head = fp.read(1 << 20)
|
||||
except Exception: # noqa: BLE001
|
||||
return False
|
||||
if head[:2] == b"MZ" or head[:4] in (b"\x7fELF", b"\xca\xfe\xba\xbe"):
|
||||
return True
|
||||
# OLE 复合容器(Package/Ole10Native)内嵌 PE:找 MZ..PE 头
|
||||
return bool(re.search(rb"MZ[\x00-\xff]{0,64}PE\x00\x00", head))
|
||||
|
||||
def _scan_ooxml(self, target: ScanTarget) -> List[Finding]:
|
||||
"""检测 OOXML(docx/xlsx/pptx)中的外部引用与外部链接。"""
|
||||
findings: List[Finding] = []
|
||||
@@ -429,9 +462,11 @@ class DocumentEngine(Engine):
|
||||
weight=45.0,
|
||||
)
|
||||
)
|
||||
if name.startswith("word/embeddings/") or name.startswith("xl/embeddings/") or name.startswith("ppt/embeddings/"):
|
||||
# 内嵌 OLE 部件。zip 目录条目(以 / 结尾、长度为 0)不是部件——
|
||||
# PowerPoint 导出的包常带空的 ppt/embeddings/ 目录,按文件处理会凭空报内嵌对象。
|
||||
if EMBED_PREFIX_RE.match(name) and not name.endswith("/"):
|
||||
embedded_ext = os.path.splitext(name)[1].lower()
|
||||
if embedded_ext in {".exe", ".dll", ".scr", ".js", ".vbs", ".bat", ".bin"}:
|
||||
if self._looks_like_executable(zf, name):
|
||||
findings.append(
|
||||
Finding(
|
||||
engine=self.name,
|
||||
@@ -442,6 +477,17 @@ class DocumentEngine(Engine):
|
||||
weight=75.0,
|
||||
)
|
||||
)
|
||||
elif embedded_ext in OFFICE_PART_EXTS:
|
||||
findings.append(
|
||||
Finding(
|
||||
engine=self.name,
|
||||
layer=self.layer,
|
||||
severity=Severity.LOW.value,
|
||||
rule="EmbeddedObject",
|
||||
detail=f"文档内嵌办公对象:{name}",
|
||||
weight=5.0,
|
||||
)
|
||||
)
|
||||
else:
|
||||
findings.append(
|
||||
Finding(
|
||||
|
||||
Reference in New Issue
Block a user