Skip to content

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

Siemphony’s repertoire

Extended attribute syscall or setfattr/getfattr execution on Linux

Matches AN1135's Linux chain at the two points a single auditd record can carry it: a SYSCALL record naming one of the six xattr syscalls (setxattr, lsetxattr, fsetxattr and their get counterparts), or an EXECVE record whose argv0 is setfattr or getfattr. Both are real, single-event observables -- writing or reading an extended attribute always goes through one of the six syscalls, and the CLI tools always execve into a process named for themselves. AN1135's full three-part chain -- a namespace-scoped setfattr, a size or entropy anomaly in the value written, and a later process reading that value back -- collapses to the first two steps here: a raw auditd SYSCALL record carries no decoded attribute name or value, only numeric syscall arguments (register contents, not parsed strings), so MITRE's XattrNamespaces and PayloadSizeThreshold knobs cannot be applied to it, and "a later process reads the value back" is a cross-event correlation within MITRE's CorrelationWindow that lib/sigma has no join or timeframe construct to express. The EXECVE selection is similarly left unscoped to a namespace: setfattr's `-n user.foo` argument can land in any of several argv positions depending on what else is on the command line, and pinning one position would silently miss the others. AN1136, the macOS leg, is not attempted: its logsource, {product: macos, service: unifiedlog}, has no standardised Sigma field vocabulary anywhere in this corpus, the same blocker already recorded against it for T1036.004, T1552.003, T1564.001 and others. Prerequisite: raw auditd audits neither xattr syscalls nor process execution by default. This rule returns zero rows until both an xattr watch (`-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,getxattr,lgetxattr,fgetxattr -k xattr`) and an execve watch (`-a always,exit -F arch=b64 -S execve -k exec`) are loaded -- and zero rows here reads as quiet when it actually means blind. Second prerequisite specific to `selection_xattr_syscall`'s `syscall` field: raw, uninterpreted auditd output records `syscall=` as the architecture-dependent kernel syscall number, not the name string this selection matches against (`setxattr` is 188 on x86_64, for example, and the numbering differs on arm64). Name resolution is not universal -- Elastic's Auditbeat resolves it by default, but a plain-text `audit.log` tail, `ausearch` without `-i`, and Wazuh's default auditd field extraction all pass the number through unresolved, so on those collectors this half of the rule never fires until an interpreting layer (`ausearch -i`, `laurel`, or an equivalent enrichment pipeline) sits in front of it. `selection_xattr_cmd`'s `a0` is unaffected by this -- EXECVE always records argv as text, never as a number, regardless of collector. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0406, 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: Extended attribute syscall or setfattr/getfattr execution on Linuxid: 8dcc029a-0a2e-4ae4-9c8e-195081030fc2status: experimentaldescription: |  Matches AN1135's Linux chain at the two points a single auditd record can  carry it: a SYSCALL record naming one of the six xattr syscalls (setxattr,  lsetxattr, fsetxattr and their get counterparts), or an EXECVE record whose  argv0 is setfattr or getfattr. Both are real, single-event observables --  writing or reading an extended attribute always goes through one of the six  syscalls, and the CLI tools always execve into a process named for  themselves. AN1135's full three-part chain -- a namespace-scoped setfattr,  a size or entropy anomaly in the value written, and a later process reading  that value back -- collapses to the first two steps here: a raw auditd  SYSCALL record carries no decoded attribute name or value, only numeric  syscall arguments (register contents, not parsed strings), so MITRE's  XattrNamespaces and PayloadSizeThreshold knobs cannot be applied to it, and  "a later process reads the value back" is a cross-event correlation within  MITRE's CorrelationWindow that lib/sigma has no join or timeframe construct  to express. The EXECVE selection is similarly left unscoped to a namespace:  setfattr's `-n user.foo` argument can land in any of several argv  positions depending on what else is on the command line, and pinning one  position would silently miss the others. AN1136, the macOS leg, is not  attempted: its logsource, {product: macos, service: unifiedlog}, has no  standardised Sigma field vocabulary anywhere in this corpus, the same  blocker already recorded against it for T1036.004, T1552.003, T1564.001  and others.  Prerequisite: raw auditd audits neither xattr syscalls nor process  execution by default. This rule returns zero rows until both an xattr  watch (`-a always,exit -F arch=b64 -S  setxattr,lsetxattr,fsetxattr,getxattr,lgetxattr,fgetxattr -k xattr`) and an  execve watch (`-a always,exit -F arch=b64 -S execve -k exec`) are loaded --  and zero rows here reads as quiet when it actually means blind.  Second prerequisite specific to `selection_xattr_syscall`'s `syscall` field:  raw, uninterpreted auditd output records `syscall=` as the  architecture-dependent kernel syscall number, not the name string this  selection matches against (`setxattr` is 188 on x86_64, for example, and  the numbering differs on arm64). Name resolution is not universal --  Elastic's Auditbeat resolves it by default, but a plain-text `audit.log`  tail, `ausearch` without `-i`, and Wazuh's default auditd field extraction  all pass the number through unresolved, so on those collectors this half of  the rule never fires until an interpreting layer (`ausearch -i`, `laurel`,  or an equivalent enrichment pipeline) sits in front of it.  `selection_xattr_cmd`'s `a0` is unaffected by this -- EXECVE always records  argv as text, never as a number, regardless of collector.  UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0406, 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/T1564/014  - https://attack.mitre.org/detectionstrategies/DET0406author: Siemphony pipeline (machine-derived from MITRE ATT&CK v19.2)date: 2026-08-18tags:  - attack.defense-evasion  - attack.t1564.014logsource:  product: linux  service: auditddetection:  selection_xattr_syscall:    type: 'SYSCALL'    syscall:      - 'setxattr'      - 'lsetxattr'      - 'fsetxattr'      - 'getxattr'      - 'lgetxattr'      - 'fgetxattr'  selection_xattr_cmd:    type: 'EXECVE'    a0|endswith:      - 'setfattr'      - 'getfattr'  condition: 1 of selection*falsepositives:  - "SELinux relabeling and policy tooling -- restorecon, setfiles and semanage -- calling get/setxattr against security.selinux on every file touched during a full relabel, an fixfiles run, or routine file creation on any enforcing SELinux host; this is the highest-volume match by a wide margin and is why this rule is low rather than medium."  - "Backup, archive and sync tooling that preserves extended attributes -- tar with --xattrs, rsync -X, bsdtar and cp --preserve=xattr -- each of which calls get/setxattr once per file it copies or archives, producing one burst of matches per scheduled job."  - "Administrators and provisioning scripts running getfattr or setfattr directly to inspect or set POSIX ACLs (system.posix_acl_access) or an SELinux context as routine filesystem administration, which is the exact command this rule's selection_xattr_cmd is built to match."  - "Container and package-management tooling -- dockerd/containerd extracting image layers, and rpm/dpkg installing packages that carry Linux file capabilities -- calling setxattr on security.capability for every capability-bearing binary during a pull, build or install."level: low

Splunk · SPL

Run this as a search.

index=* ((type="SYSCALL" AND (syscall="setxattr" OR syscall="lsetxattr" OR syscall="fsetxattr" OR syscall="getxattr" OR syscall="lgetxattr" OR syscall="fgetxattr")) OR (type="EXECVE" AND (a0="*setfattr" OR a0="*getfattr")))

Elastic · ES|QL

Run this as a search.

FROM logs-*| WHERE ((TO_LOWER(type) == "syscall" AND (TO_LOWER(syscall) == "setxattr" OR TO_LOWER(syscall) == "lsetxattr" OR TO_LOWER(syscall) == "fsetxattr" OR TO_LOWER(syscall) == "getxattr" OR TO_LOWER(syscall) == "lgetxattr" OR TO_LOWER(syscall) == "fgetxattr")) OR (TO_LOWER(type) == "execve" AND (TO_LOWER(a0) LIKE "*setfattr" OR TO_LOWER(a0) LIKE "*getfattr")))

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)^SYSCALL$</field>    <field name="syscall" type="pcre2">(?i)(^setxattr$|^lsetxattr$|^fsetxattr$|^getxattr$|^lgetxattr$|^fgetxattr$)</field>    <description>Extended attribute syscall or setfattr/getfattr execution on Linux (1/2)</description>    <mitre>      <id>T1564.014</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)^EXECVE$</field>    <field name="a0" type="pcre2">(?i)(setfattr$|getfattr$)</field>    <description>Extended attribute syscall or setfattr/getfattr execution on Linux (2/2)</description>    <mitre>      <id>T1564.014</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.