// ============================================================================= // 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)) }