Startup RC or init script edited by a file-writing tool
AN0658 pairs modification of /etc/rc.local or an /etc/init.d script with the suspicious execution that follows at the next boot. Only the modification half is a single event: the boot half needs MITRE's `time_window` knob to link a write to a reboot minutes or days later, and lib/sigma has no timeframe and no cross-event join. So this rule matches the edit itself — a process whose command line names one of the RC script locations, launched either as a file-writing or editing utility (tee, sed, cp, install, chmod, an editor) or with a shell redirect aimed at one of those paths. The two forms are ORed because they are the same act reached two ways: `vi /etc/rc.local` and `sh -c 'echo /tmp/x >> /etc/rc.local'` both plant the persistence, but in the second the executable is a shell and only the redirect distinguishes it. The redirect arm matches the operator immediately followed by an RC path (`> /etc/init.d/` and `>/etc/init.d/`, which also cover the `>>` append form) rather than the operator anywhere on the line — an unanchored `>>` would fire on `/etc/init.d/foo start >> /var/log/foo.log` and on `cat /etc/rc.local >> /tmp/out`, neither of which writes the script. Shells are deliberately absent from the tool list: systemd's rc-local.service runs the script at every boot as `/bin/sh /etc/rc.local`, which would otherwise match once per boot on every host and match nothing an adversary did. The editor entries carry the Debian alternatives targets (vim.basic, vim.tiny, vim.nox) alongside `/vi` and `/vim`, because the exec record names the resolved binary and `vi` on a Debian-family host resolves to one of those. MITRE's `script_path` knob is what the path list implements, populated here with the Debian, RHEL, BSD-style and ESXi locations rather than taken from MITRE; dropping `/etc/init.d/` from it removes this rule's loudest false positive and would justify a higher level. Its `user_context` and `file_permission` knobs are not applied — root is the expected context for every legitimate match here as well as every malicious one. Vocabulary and limits. The brief maps `auditd:SYSCALL::execve` onto the Sigma `process_creation` category, which is Sysmon-for-Linux-shaped (`Image`, `CommandLine`); raw auditd splits the same execution across a SYSCALL record carrying `exe` and an EXECVE record carrying `a0`, `a1`, … , so that feed needs a field mapping before this rule can match on it. Nothing that writes the file without exec'ing a helper is visible: a Python or Perl implant that opens /etc/rc.local directly, or an interactive shell where the redirect is performed by the already-running shell and creates no new process, leaves no matching event. The brief's second source, `linux:syslog` boot logs, is not used — it has no standardised Sigma field vocabulary and boot messages name no script path. AN0659 (macOS) offers only `macos:unifiedlog`, which likewise has no standardised field names, so /etc/rc.common and the StartupItems trees are out of reach here even though the path list includes rc.common. ESXi's /etc/rc.local.d/local.sh is listed for completeness, but ESXi ships neither auditd nor Sysmon for Linux, so that entry only fires on a Linux host that uses the path. Prerequisite: neither feed exists by default. Sysmon for Linux is a separate agent no distribution installs, and stock auditd records no execve until a rule such as `-a always,exit -F arch=b64 -S execve -k exec` is loaded — until then this rule returns zero rows, and zero rows here means blind, not quiet. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0237, not hand-written and not tested by its author. Any lab result is on this rule's own page.Full descriptionShow less
The detection
The 4 SIEM queries below are previews produced by Siemphony’s own translator, not pySigma, and none has been executed against a real backend — review before you deploy.
detection.yml
Sentinel · KQL
Run this as a search.
DeviceProcessEvents| where ((ProcessCommandLine contains "/etc/rc.local" or ProcessCommandLine contains "/etc/rc.common" or ProcessCommandLine contains "/etc/rc.d/rc.local" or ProcessCommandLine contains "/etc/rc.local.d/" or ProcessCommandLine contains "/etc/init.d/" or ProcessCommandLine contains "/etc/rc.d/init.d/") and ((FolderPath endswith "/tee" or FolderPath endswith "/sed" or FolderPath endswith "/cp" or FolderPath endswith "/mv" or FolderPath endswith "/ln" or FolderPath endswith "/install" or FolderPath endswith "/chmod" or FolderPath endswith "/chown" or FolderPath endswith "/dd" or FolderPath endswith "/patch" or FolderPath endswith "/truncate" or FolderPath endswith "/ed" or FolderPath endswith "/vi" or FolderPath endswith "/vim" or FolderPath endswith "/vim.basic" or FolderPath endswith "/vim.tiny" or FolderPath endswith "/vim.nox" or FolderPath endswith "/nvim" or FolderPath endswith "/nano" or FolderPath endswith "/pico" or FolderPath endswith "/emacs" or FolderPath endswith "/gedit") or (ProcessCommandLine contains "> /etc/rc.local" or ProcessCommandLine contains ">/etc/rc.local" or ProcessCommandLine contains "> /etc/rc.common" or ProcessCommandLine contains ">/etc/rc.common" or ProcessCommandLine contains "> /etc/rc.d/rc.local" or ProcessCommandLine contains ">/etc/rc.d/rc.local" or ProcessCommandLine contains "> /etc/rc.local.d/" or ProcessCommandLine contains ">/etc/rc.local.d/" or ProcessCommandLine contains "> /etc/init.d/" or ProcessCommandLine contains ">/etc/init.d/" or ProcessCommandLine contains "> /etc/rc.d/init.d/" or ProcessCommandLine contains ">/etc/rc.d/init.d/")))
Splunk · SPL
Run this as a search.
index=* ((CommandLine="*/etc/rc.local*" OR CommandLine="*/etc/rc.common*" OR CommandLine="*/etc/rc.d/rc.local*" OR CommandLine="*/etc/rc.local.d/*" OR CommandLine="*/etc/init.d/*" OR CommandLine="*/etc/rc.d/init.d/*") AND ((Image="*/tee" OR Image="*/sed" OR Image="*/cp" OR Image="*/mv" OR Image="*/ln" OR Image="*/install" OR Image="*/chmod" OR Image="*/chown" OR Image="*/dd" OR Image="*/patch" OR Image="*/truncate" OR Image="*/ed" OR Image="*/vi" OR Image="*/vim" OR Image="*/vim.basic" OR Image="*/vim.tiny" OR Image="*/vim.nox" OR Image="*/nvim" OR Image="*/nano" OR Image="*/pico" OR Image="*/emacs" OR Image="*/gedit") OR (CommandLine="*> /etc/rc.local*" OR CommandLine="*>/etc/rc.local*" OR CommandLine="*> /etc/rc.common*" OR CommandLine="*>/etc/rc.common*" OR CommandLine="*> /etc/rc.d/rc.local*" OR CommandLine="*>/etc/rc.d/rc.local*" OR CommandLine="*> /etc/rc.local.d/*" OR CommandLine="*>/etc/rc.local.d/*" OR CommandLine="*> /etc/init.d/*" OR CommandLine="*>/etc/init.d/*" OR CommandLine="*> /etc/rc.d/init.d/*" OR CommandLine="*>/etc/rc.d/init.d/*")))Elastic · ES|QL
Run this as a search.
FROM logs-*| WHERE ((TO_LOWER(process.command_line) LIKE "*/etc/rc.local*" OR TO_LOWER(process.command_line) LIKE "*/etc/rc.common*" OR TO_LOWER(process.command_line) LIKE "*/etc/rc.d/rc.local*" OR TO_LOWER(process.command_line) LIKE "*/etc/rc.local.d/*" OR TO_LOWER(process.command_line) LIKE "*/etc/init.d/*" OR TO_LOWER(process.command_line) LIKE "*/etc/rc.d/init.d/*") AND ((TO_LOWER(process.executable) LIKE "*/tee" OR TO_LOWER(process.executable) LIKE "*/sed" OR TO_LOWER(process.executable) LIKE "*/cp" OR TO_LOWER(process.executable) LIKE "*/mv" OR TO_LOWER(process.executable) LIKE "*/ln" OR TO_LOWER(process.executable) LIKE "*/install" OR TO_LOWER(process.executable) LIKE "*/chmod" OR TO_LOWER(process.executable) LIKE "*/chown" OR TO_LOWER(process.executable) LIKE "*/dd" OR TO_LOWER(process.executable) LIKE "*/patch" OR TO_LOWER(process.executable) LIKE "*/truncate" OR TO_LOWER(process.executable) LIKE "*/ed" OR TO_LOWER(process.executable) LIKE "*/vi" OR TO_LOWER(process.executable) LIKE "*/vim" OR TO_LOWER(process.executable) LIKE "*/vim.basic" OR TO_LOWER(process.executable) LIKE "*/vim.tiny" OR TO_LOWER(process.executable) LIKE "*/vim.nox" OR TO_LOWER(process.executable) LIKE "*/nvim" OR TO_LOWER(process.executable) LIKE "*/nano" OR TO_LOWER(process.executable) LIKE "*/pico" OR TO_LOWER(process.executable) LIKE "*/emacs" OR TO_LOWER(process.executable) LIKE "*/gedit") OR (TO_LOWER(process.command_line) LIKE "*> /etc/rc.local*" OR TO_LOWER(process.command_line) LIKE "*>/etc/rc.local*" OR TO_LOWER(process.command_line) LIKE "*> /etc/rc.common*" OR TO_LOWER(process.command_line) LIKE "*>/etc/rc.common*" OR TO_LOWER(process.command_line) LIKE "*> /etc/rc.d/rc.local*" OR TO_LOWER(process.command_line) LIKE "*>/etc/rc.d/rc.local*" OR TO_LOWER(process.command_line) LIKE "*> /etc/rc.local.d/*" OR TO_LOWER(process.command_line) LIKE "*>/etc/rc.local.d/*" OR TO_LOWER(process.command_line) LIKE "*> /etc/init.d/*" OR TO_LOWER(process.command_line) LIKE "*>/etc/init.d/*" OR TO_LOWER(process.command_line) LIKE "*> /etc/rc.d/init.d/*" OR TO_LOWER(process.command_line) LIKE "*>/etc/rc.d/init.d/*")))
Wazuh · XML rule
Deploy to your manager — this is a rule, not a search.
<group name="sigma,linux,process_creation,"> <!-- Rule ids must be unique on your manager; 100000+ is the user range. --> <!-- 2 rules: the Sigma condition ORs across different fields, which one rule cannot express. Any one matching is a hit. --> <rule id="100000" level="5"> <!-- Set <if_sid> to the decoder/base rule for linux so this only evaluates relevant events. --> <field name="CommandLine" type="pcre2">(?i)(/etc/rc\.local|/etc/rc\.common|/etc/rc\.d/rc\.local|/etc/rc\.local\.d/|/etc/init\.d/|/etc/rc\.d/init\.d/)</field> <field name="Image" type="pcre2">(?i)(/tee$|/sed$|/cp$|/mv$|/ln$|/install$|/chmod$|/chown$|/dd$|/patch$|/truncate$|/ed$|/vi$|/vim$|/vim\.basic$|/vim\.tiny$|/vim\.nox$|/nvim$|/nano$|/pico$|/emacs$|/gedit$)</field> <description>Startup RC or init script edited by a file-writing tool (1/2)</description> <mitre> <id>T1037.004</id> </mitre> </rule> <rule id="100001" level="5"> <!-- Set <if_sid> to the decoder/base rule for linux so this only evaluates relevant events. --> <field name="CommandLine" type="pcre2">(?i)(/etc/rc\.local|/etc/rc\.common|/etc/rc\.d/rc\.local|/etc/rc\.local\.d/|/etc/init\.d/|/etc/rc\.d/init\.d/)</field> <field name="CommandLine" type="pcre2">(?i)(> /etc/rc\.local|>/etc/rc\.local|> /etc/rc\.common|>/etc/rc\.common|> /etc/rc\.d/rc\.local|>/etc/rc\.d/rc\.local|> /etc/rc\.local\.d/|>/etc/rc\.local\.d/|> /etc/init\.d/|>/etc/init\.d/|> /etc/rc\.d/init\.d/|>/etc/rc\.d/init\.d/)</field> <description>Startup RC or init script edited by a file-writing tool (2/2)</description> <mitre> <id>T1037.004</id> </mitre> </rule></group>
Verdicts · reactions · comments
Community
Verdicts from engineers who actually deployed it, and the conversation around it.
Nobody has run this in a real environment and said what happened.
Verdicts from engineers who deployed it
0 castNo verdicts reported yet. The first one is worth more than the tenth — say what you ran it against.
Log in to report a verdict.
Log in to join the discussion.
No comments yet. Someone who deploys this will have something to say about it.