Skip to content

Siemphony is in beta and still being built. How a rule earns its badge.

Siemphony’s repertoire

Shell startup or logout script modified on Linux

Matches the file-modification leg of AN0059: an auditd PATH record naming one of the configuration scripts a login or interactive shell sources on its own, which is where this technique plants the command it wants re-executed at every logon. The path list is MITRE's `FilePathRegex` knob, populated here with the bash, sh and zsh per-user dotfiles plus their system-wide counterparts under /etc, and it is anchored on the filename rather than on an absolute path because auditd records `name=` exactly as it was handed to the syscall, so an editor run from inside the home directory logs a bare `.bashrc`. Three limits are structural. auditd emits PATH and SYSCALL as separate records for one event, and the writing process's `exe`, `uid` and `auid` live only on the SYSCALL side, so MITRE's `TargetUser` knob cannot be applied inside this selection at all; the analytic's second half — an unexpected binary executing shortly after shell startup, within MITRE's `TimeWindow` knob — is a cross-event correlation lib/sigma has no way to express; and the macOS arm AN0060 is not attempted, because its unifiedlog and EndpointSecurity sources have no standardised Sigma field names and inventing them would produce a rule that parses everywhere and matches nothing. Prerequisite: auditd watches none of these paths by default, so this rule returns zero rows until watches such as `-w /etc/profile -p wa` and a per-home `-w /home/<user>/.bashrc -p wa` are loaded, and zero rows reads as quiet when it actually means blind. The `wa` permission also matters for noise: with it, only writes and attribute changes are recorded, whereas a watch including `r` makes every shell login match. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0020, not hand-written and not tested by its author. Any lab result is on this rule's own page.Full description

The detection

The 3 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

title: Shell startup or logout script modified on Linuxid: a01eef05-d4a9-4665-b1fb-7f7d1dcc10bdstatus: experimentaldescription: |  Matches the file-modification leg of AN0059: an auditd PATH record naming one  of the configuration scripts a login or interactive shell sources on its own,  which is where this technique plants the command it wants re-executed at every  logon. The path list is MITRE's `FilePathRegex` knob, populated here with the  bash, sh and zsh per-user dotfiles plus their system-wide counterparts under  /etc, and it is anchored on the filename rather than on an absolute path  because auditd records `name=` exactly as it was handed to the syscall, so an  editor run from inside the home directory logs a bare `.bashrc`. Three limits  are structural. auditd emits PATH and SYSCALL as separate records for one  event, and the writing process's `exe`, `uid` and `auid` live only on the  SYSCALL side, so MITRE's `TargetUser` knob cannot be applied inside this  selection at all; the analytic's second half — an unexpected binary executing  shortly after shell startup, within MITRE's `TimeWindow` knob — is a  cross-event correlation lib/sigma has no way to express; and the macOS arm  AN0060 is not attempted, because its unifiedlog and EndpointSecurity sources  have no standardised Sigma field names and inventing them would produce a rule  that parses everywhere and matches nothing. Prerequisite: auditd watches none  of these paths by default, so this rule returns zero rows until watches such  as `-w /etc/profile -p wa` and a per-home `-w /home/<user>/.bashrc -p wa` are  loaded, and zero rows reads as quiet when it actually means blind. The `wa`  permission also matters for noise: with it, only writes and attribute changes  are recorded, whereas a watch including `r` makes every shell login match.  UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0020, not hand-written and not tested by its author. Any lab result is on this rule's own page.references:  - https://attack.mitre.org/techniques/T1546/004  - https://attack.mitre.org/detectionstrategies/DET0020author: Siemphony pipeline (machine-derived from MITRE ATT&CK v19.2)date: 2026-08-16tags:  - attack.privilege-escalation  - attack.persistence  - attack.t1546.004logsource:  product: linux  service: auditddetection:  selection_dotfiles:    type: 'PATH'    name|endswith:      - '.bashrc'      - '.bash_profile'      - '.bash_login'      - '.bash_logout'      - '.bash_aliases'      - '.profile'      - '.zshrc'      - '.zshenv'      - '.zprofile'      - '.zlogin'      - '.zlogout'      - '/etc/profile'      - '/etc/bash.bashrc'      - '/etc/bashrc'      - '/etc/zsh/zshrc'      - '/etc/zsh/zshenv'      - '/etc/zsh/zprofile'      - '/etc/zsh/zlogin'      - '/etc/zsh/zlogout'      - '/etc/zshrc'      - '/etc/zshenv'      - '/etc/zprofile'      - '/etc/zlogin'      - '/etc/zlogout'  selection_profiled:    type: 'PATH'    name|contains: '/etc/profile.d/'  condition: 1 of selection*falsepositives:  - "Configuration management and dotfile tooling rewriting the same files on a schedule: Ansible, Chef, Puppet and Salt pushing a standard ~/.bashrc or /etc/profile.d/ fragment to every host, and chezmoi, GNU stow, oh-my-zsh or a chef-managed home directory doing the same per user. On a managed estate this is the loudest match by a wide margin and is why the level is low rather than medium."  - "Package installation and upgrade. Language runtimes and SDKs drop or replace files under /etc/profile.d/ from their postinst scripts, and the nvm, rvm, conda, pyenv and Rust installers all append their initialisation block to ~/.bashrc or ~/.zshrc as their documented final step."  - "Account creation. useradd and adduser copy the /etc/skel dotfiles into each new home directory, so every provisioned user, service account and CI build user produces a burst of matching CREATE records."  - "A user editing their own shell configuration in vim, nano or emacs to add an alias, a PATH entry or a prompt change. Editors write through a temporary file and rename it into place, so one interactive edit emits several PATH records for the same target."  - "Backup, restore and home-directory migration jobs that unpack an archive over a user's home directory, recreating every dotfile in it."level: low

Splunk · SPL

Run this as a search.

index=* ((type="PATH" AND (name="*.bashrc" OR name="*.bash_profile" OR name="*.bash_login" OR name="*.bash_logout" OR name="*.bash_aliases" OR name="*.profile" OR name="*.zshrc" OR name="*.zshenv" OR name="*.zprofile" OR name="*.zlogin" OR name="*.zlogout" OR name="*/etc/profile" OR name="*/etc/bash.bashrc" OR name="*/etc/bashrc" OR name="*/etc/zsh/zshrc" OR name="*/etc/zsh/zshenv" OR name="*/etc/zsh/zprofile" OR name="*/etc/zsh/zlogin" OR name="*/etc/zsh/zlogout" OR name="*/etc/zshrc" OR name="*/etc/zshenv" OR name="*/etc/zprofile" OR name="*/etc/zlogin" OR name="*/etc/zlogout")) OR (type="PATH" AND name="*/etc/profile.d/*"))

Elastic · ES|QL

Run this as a search.

FROM logs-*| WHERE ((TO_LOWER(type) == "path" AND (TO_LOWER(name) LIKE "*.bashrc" OR TO_LOWER(name) LIKE "*.bash_profile" OR TO_LOWER(name) LIKE "*.bash_login" OR TO_LOWER(name) LIKE "*.bash_logout" OR TO_LOWER(name) LIKE "*.bash_aliases" OR TO_LOWER(name) LIKE "*.profile" OR TO_LOWER(name) LIKE "*.zshrc" OR TO_LOWER(name) LIKE "*.zshenv" OR TO_LOWER(name) LIKE "*.zprofile" OR TO_LOWER(name) LIKE "*.zlogin" OR TO_LOWER(name) LIKE "*.zlogout" OR TO_LOWER(name) LIKE "*/etc/profile" OR TO_LOWER(name) LIKE "*/etc/bash.bashrc" OR TO_LOWER(name) LIKE "*/etc/bashrc" OR TO_LOWER(name) LIKE "*/etc/zsh/zshrc" OR TO_LOWER(name) LIKE "*/etc/zsh/zshenv" OR TO_LOWER(name) LIKE "*/etc/zsh/zprofile" OR TO_LOWER(name) LIKE "*/etc/zsh/zlogin" OR TO_LOWER(name) LIKE "*/etc/zsh/zlogout" OR TO_LOWER(name) LIKE "*/etc/zshrc" OR TO_LOWER(name) LIKE "*/etc/zshenv" OR TO_LOWER(name) LIKE "*/etc/zprofile" OR TO_LOWER(name) LIKE "*/etc/zlogin" OR TO_LOWER(name) LIKE "*/etc/zlogout")) OR (TO_LOWER(type) == "path" AND TO_LOWER(name) LIKE "*/etc/profile.d/*"))

Wazuh · XML rule

Deploy to your manager — this is a rule, not a search.

<group name="sigma,linux,">  <!-- 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="type" type="pcre2">(?i)^PATH$</field>    <field name="name" type="pcre2">(?i)(\.bashrc$|\.bash_profile$|\.bash_login$|\.bash_logout$|\.bash_aliases$|\.profile$|\.zshrc$|\.zshenv$|\.zprofile$|\.zlogin$|\.zlogout$|/etc/profile$|/etc/bash\.bashrc$|/etc/bashrc$|/etc/zsh/zshrc$|/etc/zsh/zshenv$|/etc/zsh/zprofile$|/etc/zsh/zlogin$|/etc/zsh/zlogout$|/etc/zshrc$|/etc/zshenv$|/etc/zprofile$|/etc/zlogin$|/etc/zlogout$)</field>    <description>Shell startup or logout script modified on Linux (1/2)</description>    <mitre>      <id>T1546.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="type" type="pcre2">(?i)^PATH$</field>    <field name="name" type="pcre2">(?i)/etc/profile\.d/</field>    <description>Shell startup or logout script modified on Linux (2/2)</description>    <mitre>      <id>T1546.004</id>    </mitre>  </rule></group>

Sentinel · KQL

Run this as a search.

Sentinel cannot express this construct. No Sentinel table is modelled for this logsource ({"product":"linux","service":"auditd"}), so there is nothing honest to query. Pick a logsource this translator maps, or write the KQL by hand. The Sigma source is on the first tab, unchanged.

Verdicts · reactions · comments

Community

Verdicts from engineers who actually deployed it, and the conversation around it.

Log in to react
Not yet reported on

Nobody has run this in a real environment and said what happened.

Verdicts from engineers who deployed it

0 cast

No 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.