Files
MeshSate/rules/linux.yar
zhaolei b6a004bdb7 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。
2026-11-02 20:26:56 +08:00

331 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// =============================================================================
// MeshSafe L2B YARA 规则集 —— Linux / 跨平台后门专项(C7)
// =============================================================================
//
// 设计原则:
// - 光闸摆渡场景,所有规则 2-3 特征组合命中,避免单一关键词误伤合法 Shell/Python 代码
// - 覆盖范围:反弹 Shell、持久化(crontab/authorized_keys/systemd/LD_PRELOAD)、
// Rootkit 特征、挖矿通用特征
// - 命中后作为 finding 交给 PolicyEngine 权重累加
//
// 维护:
// - 新后门工具/家族出现时优先补充 "工具名 + 持久化手段" 组合
// =============================================================================
// =============================================================================
// C7-1 反弹 Shell(多种语言实现)
// =============================================================================
rule C7_Linux_ReverseShell_Bash {
meta:
risk_level = "critical"
category = "C7"
false_positive_rate = "low"
reference = "MITRE ATT&CK T1059.004 Bash"
description = "Bash 反弹 Shell 组合:/dev/tcp + bash -i 或 sh -c"
strings:
$devtcp = /\/dev\/tcp\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{2,5}/ ascii
$bash_i = "bash -i" ascii
$sh_c = /sh\s+-c\s+['"]bash -i/ ascii
$exec3 = "exec 3<>/dev/tcp/" ascii
$exec4 = "exec 4>&0 0>&1 1>&4" ascii
condition:
// /dev/tcp/IP:PORT + bash -i 这两个必须同时出现
$devtcp and ($bash_i or $sh_c or $exec3)
or
// exec fd 重定向链
$exec3 and $exec4
}
rule C7_Linux_ReverseShell_NC {
meta:
risk_level = "critical"
category = "C7"
false_positive_rate = "medium"
reference = "MITRE ATT&CK T1059.004 Netcat"
description = "nc/ncat 反弹 Shell:-e/-c 参数指定 bash 或 sh"
strings:
$nc1 = /nc\s+[\w.-]+\s+\d{2,5}\s+-e\s+(\/bin\/(ba)?sh|bash|sh)/ ascii
$nc2 = /ncat\s+[\w.-]+\s+\d{2,5}\s+-e\s+(\/bin\/(ba)?sh|bash|sh)/ ascii
$nc3 = /nc\s+[\w.-]+\s+\d{2,5}\s+-c\s+(\/bin\/(ba)?sh|bash|sh)/ ascii
$nc4 = /netcat\s+[\w.-]+\s+\d{2,5}\s+-e/ ascii
$mkfifo = /mkfifo\s+\/tmp\/\w+;\s*(nc|ncat)\s+/ ascii
condition:
any of ($*)
}
rule C7_Linux_ReverseShell_Python {
meta:
risk_level = "high"
category = "C7"
false_positive_rate = "medium"
reference = "MITRE ATT&CK T1059.006 Python"
description = "Python 反弹 Shell:socket + exec/bin/sh + pty"
strings:
$socket1 = "import socket" ascii
$socket2 = "socket.socket" ascii
$pty = "import pty" ascii
$sub = "import subprocess" ascii
$sh = /\/bin\/(ba)?sh/ ascii
$osdup2 = "os.dup2" ascii
$execv = "os.execv" ascii
condition:
// socket + pty + /bin/bash = 完整 Python pty 反弹
($socket1 or $socket2) and $pty and $sh
or
// socket + subprocess + /bin/sh + dup2 = 经典模式
($socket1 or $socket2) and $sub and $sh and $osdup2
or
// socket + os.execv + /bin/bash
($socket1 or $socket2) and $execv and $sh
}
rule C7_Linux_ReverseShell_Perl {
meta:
risk_level = "high"
category = "C7"
false_positive_rate = "medium"
reference = "MITRE ATT&CK T1059.005 Perl"
description = "Perl 反弹 Shell:IO::Socket + exec + /bin/sh"
strings:
$iosocket = "IO::Socket::INET" ascii nocase
$socketvar = /\$s\s*=\s*IO::Socket/ ascii
$exec = /exec\s+['"]\/bin\/(ba)?sh['"]/ ascii
$open = /open\s*\(.*<&\$\{?s\}?/ ascii
$eval = /eval\s+reverse\s+['"]/ ascii
condition:
($iosocket or $socketvar) and ($exec or $open or $eval)
}
rule C7_Linux_ReverseShell_Socat {
meta:
risk_level = "high"
category = "C7"
false_positive_rate = "low"
reference = "MITRE ATT&CK T1059.004 Socat"
description = "socat 反弹 Shell:TCP-LISTEN + EXEC:/bin/bash"
strings:
$socat1 = /socat\s+(TCP-LISTEN:\d{2,5},?\s*(reuseaddr|fork)?|TCP4:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{2,5})/ ascii
$socat2 = /EXEC:\/bin\/(ba)?sh/ ascii
$socat3 = /EXEC:'\/bin\/(ba)?sh'/ ascii
condition:
any of ($socat1*) and any of ($socat2, $socat3)
}
rule C7_Linux_ReverseShell_Misc {
meta:
risk_level = "medium"
category = "C7"
false_positive_rate = "low"
reference = "多种语言反弹 Shell 通用特征"
description = "通用反弹 Shell 标记:/dev/udp 或 攻击工具名 + shell 参数"
strings:
$devudp = /\/dev\/udp\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{2,5}/ ascii
$bashc = /bash\s+-c\s+['"].*\/dev\/(tcp|udp)/ ascii
$dash_e = /\/bin\/bash\s+-e\s+['"]/ ascii
// 裸词 Hydra 会命中 "dehydrated"、crack 会命中 "cracklib",必须带参数或成组出现
$hydra = /\bhydra\s+(-l|-P|-p|-s|-m|-t)\b/ ascii nocase
$tool = /\b(crackmapexec|weevely|meterpreter|msfconsole|msfvenom)\b/ ascii nocase
$reverseshell = /reverse[_\s]?shell|shell[_\s]?shock/ ascii nocase
$netart = /(nc|ncat)\s+\S+\s+\d{2,5}\s+-[ec]\b|\/dev\/(tcp|udp)\/|socat\s+EXEC:|bash\s+-i\s*>&/ ascii
condition:
any of ($devudp, $bashc, $dash_e)
or $hydra
or ($tool and $netart)
or ($reverseshell and $netart)
}
// =============================================================================
// C7-2 持久化 —— crontab / authorized_keys / systemd
// =============================================================================
rule C7_Linux_Persistence_Crontab {
meta:
risk_level = "high"
category = "C7"
false_positive_rate = "medium"
reference = "MITRE ATT&CK T1053.003 Cron"
description = "crontab 持久化:下载执行 + .bashrc 注入 + /tmp/.hidden 目录"
strings:
$crontab1 = /\*\s+\*\s+\*\s+\*\s+\*\s+(curl|wget)\s+['"]?https?:/ ascii
$crontab2 = /\*\s+\*\s+\*\s+\*\s+\*\s+(bash|sh)\s+\S+\s+['"]\/dev\/tcp/ ascii
$crontab3 = /crontab\s+-[lre]?\s+\/tmp\/\w+/ ascii
$bashrc = /\.bashrc|\.bash_profile|\.profile/ ascii
$wget = /wget\s+https?:/ ascii
$curl = /curl\s+.*\|\s*(bash|sh)/ ascii
$hidden = /\/tmp\/\.?\w+\s+&&/ ascii
condition:
any of ($crontab1, $crontab2, $crontab3)
or
$bashrc and ($wget or $curl) and $hidden
}
rule C7_Linux_Persistence_AuthorizedKeys {
meta:
risk_level = "high"
category = "C7"
false_positive_rate = "low"
reference = "MITRE ATT&CK T1098 SSH Authorized Keys"
description = "authorized_keys 写入:下载公钥 + 追加到 .ssh/authorized_keys + chmod 600"
strings:
$authkeys = /\.ssh\/authorized_keys/ ascii
$wgetkey = /wget\s+-O\s+.*authorized_keys/ ascii
$curlkey = /curl\s+.*authorized_keys/ ascii
$echokey = /echo\s+['"]ssh-(rsa|ecdsa|ed25519)/ ascii
$chmod = /chmod\s+\d{3,4}\s+\$\{?SSH_DIR\}?authorized_keys/ ascii
condition:
any of ($wgetkey, $curlkey, $echokey) or ($authkeys and any of ($wgetkey, $curlkey, $chmod))
}
rule C7_Linux_Persistence_SystemD {
meta:
risk_level = "high"
category = "C7"
false_positive_rate = "low"
reference = "MITRE ATT&CK T1543.002 Systemd Service"
description = "恶意 systemd unit:ExecStart 指向临时目录隐藏文件 / 管道执行 / 反弹命令"
strings:
$unit = /\[Unit\]/ ascii
$service = /\[Service\]/ ascii
$install = /\[Install\]/ ascii
$execstart = /ExecStart=/ ascii
$multiuser = /multi-user\.target/ ascii
// 隐藏文件(点开头)落在可写临时目录——正常 unit 只会在 /usr/bin、/opt 等路径
$hiddenpath = /\/(tmp|var\/tmp|dev\/shm)\/\.[a-zA-Z0-9_-]{2,}/ ascii
$pipe = /(curl|wget)\s+\S+\s*\|\s*(ba)?sh/ ascii
$revshell = /((nc|ncat|socat)\s+.*(-e|--exec|EXEC:)\s*\/bin\/(ba)?sh|\/dev\/tcp\/\d{1,3}\.\d{1,3})/ ascii
condition:
($unit and $service and $execstart and any of ($hiddenpath, $pipe, $revshell))
or
($install and $multiuser and $execstart and any of ($hiddenpath, $pipe, $revshell))
}
rule C7_Linux_Persistence_LD_PRELOAD {
meta:
risk_level = "high"
category = "C7"
false_positive_rate = "low"
reference = "MITRE ATT&CK T1574.006 LD_PRELOAD"
description = "LD_PRELOAD 劫持:写 ld.so.preload 或预加载临时目录里的 .so"
strings:
$ldpreload = /LD_PRELOAD=/ ascii
$exportenv = /export\s+LD_PRELOAD/ ascii
$ldso = /ld\.so\.preload/ ascii
$tmpso = /\/(tmp|var\/tmp|dev\/shm|proc\/\d+\/root)\/[a-zA-Z0-9_.\/-]*\.so(\.[0-9]+)?/ ascii
condition:
// /etc/ld.so.preload 是内核级后门常用落点,单独出现即算证据
$ldso
or
// LD_PRELOAD 指向可写临时目录的 so;README 里 LD_PRELOAD=libasan.so 不算
(any of ($ldpreload, $exportenv) and $tmpso)
}
// =============================================================================
// C7-3 Rootkit + 挖矿通用特征
// =============================================================================
rule C7_Linux_Rootkit_KernelModule {
meta:
risk_level = "critical"
category = "C7"
false_positive_rate = "medium"
reference = "MITRE ATT&CK T1547.006 Kernel Modules and Extensions"
description = "内核模块加载:insmod/modprobe + .ko + /proc/kallsyms 隐藏"
strings:
$insmod = /insmod\s+.*\.ko/ ascii
$modprobe = /modprobe\s+.*\.ko/ ascii
$ko = /\.ko(\.xz|\.gz)?\b/ ascii
$hiddenproc = /hide_process_from_dcache|hide_module/ ascii
$proc = /\/proc\/kallsyms|\/proc\/modules/ ascii
$netstat = /\/proc\/net\/tcp|\/proc\/net\/udp/ ascii
condition:
any of ($insmod, $modprobe) and any of ($ko, $hiddenproc)
or
any of ($hiddenproc) and any of ($proc, $netstat)
}
rule C7_Linux_Miner_Generic {
meta:
risk_level = "medium"
category = "C7"
false_positive_rate = "medium"
reference = "MITRE ATT&CK T1496 Resource Hijacking"
description = "挖矿通用特征:stratum+tcp 协议 + 非标准端口(3333/5555/8080)"
strings:
$stratum = "stratum+tcp://" ascii
$stratums = "stratum+ssl://" ascii
$pool = /pool\.(xmr|mine|nanopool|coin|mining)/ ascii nocase
$port3333 = /:\s*3333\b/ ascii
$port5555 = /:\s*5555\b/ ascii
$highcpu = /nice\s+-n\s+[+-]?\d+|cpulimit\s+-l/ ascii
condition:
any of ($stratum, $stratums, $pool) and any of ($port3333, $port5555)
or
any of ($stratum, $stratums) and $highcpu
}
// =============================================================================
// C7-4 跨平台后门:Ruby + Lua + Node.js
// =============================================================================
rule C7_Misc_Ruby_Lua_ReverseShell {
meta:
risk_level = "medium"
category = "C7"
false_positive_rate = "low"
reference = "多语言反弹 Shell"
description = "Ruby/Lua 反弹 Shell:Socket 对象 + 紧邻的 shell 执行调用"
strings:
$ruby = "TCPSocket" ascii
$ruby2 = "Socket.tcp" ascii
$lua = "loadstring" ascii
$lua2 = "luasocket" ascii
$exec = /(\bexec|\bsystem|IO\.popen|\bpopen|os\.execute|os\.runtime)\s*\(?\s*['"]((\/bin\/)?(ba)?sh|nc\s+-e|\/dev\/tcp)[^'"]{0,48}/ ascii
condition:
// 只要出现 TCPSocket/loadstring 就命中 = 任何内嵌 Lua 的程序(Redis、nginx-lua、
// Wireshark 插件)必中。语言标记与 shell 执行必须挨在一起(256B 内)。
$exec and (
for any i in (1..#exec): (
any of ($ruby, $ruby2, $lua, $lua2) in (@exec[i] - 256..@exec[i] + 256)
)
)
}
// =============================================================================
// C7-5 网络投毒 / MITM 工具(内网横向移动)
// 工具名必须整词匹配,且与攻击参数成组出现
// =============================================================================
rule C7_Network_Tools_Malicious {
meta:
risk_level = "medium"
category = "C7"
false_positive_rate = "low"
reference = "内网攻击工具"
description = "内网攻击工具:ettercap/responder/nmap + 投毒参数成组出现"
strings:
$tool1 = /\bettercap\b/ ascii nocase
$tool2 = /\bresponder(\.py)?\b/ ascii nocase
$tool3 = /\bnmap\b/ ascii nocase
// 攻击参数 / 漏洞编号(这些才是意图证据)
$art1 = /--smb/ ascii
$art2 = /\bms17-010\b/ ascii nocase
$art3 = /\bSMBGhost\b/ ascii nocase
$art4 = /\bdns[-_]spoof\b|\bdns[-_]mitm\b/ ascii nocase
$art5 = /\barp[-_]poison\b|\barp[-_]spoof\b/ ascii nocase
$art6 = /--Mitm|-T\s+text|\bec_sleep\b|\bntlm_relay\b|\bRunFinger\.py\b/ ascii nocase
condition:
// 投毒手法名本身就是明确证据
any of ($art4, $art5)
or
// 工具名 + 攻击参数
($tool1 and any of ($art1, $art2, $art3, $art6))
or ($tool2 and any of ($art1, $art2, $art3, $art6))
or ($tool3 and any of ($art1, $art2, $art3))
}