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 descriptionShow less
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
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.
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.