Shared object written into a non-standard directory Linux dynamic linker would trust
AN1209 offers three log sources and only one of them survives scrutiny. Its first, `auditd:SYSCALL::execve with LD_PRELOAD ... set`, is mapped in the brief to `process_creation`/linux — Image/CommandLine fields that mirror a process's own argv. `LD_PRELOAD` is an environment variable, not an argument: `export LD_PRELOAD=/tmp/x.so` followed by a plain command, or the value set persistently in a shell-init file, never appears in that child's argv at all, so a `CommandLine|contains: 'LD_PRELOAD'` selector would only ever catch the narrow case of the assignment typed inline in the same invocation (`env LD_PRELOAD=/tmp/x.so cmd`) and would silently miss the far more common shell-export and profile-persistence forms while looking like it covers the technique. Its third, `linux:osquery`, has no standardised Sigma field vocabulary anywhere in this corpus — the same blocker already recorded against that log source for T1011 and T1499.003. What remains, and what this rule is built on, is the second: an auditd `PATH` record naming a `.so` file — matched with a regex tolerant of the versioned suffixes real shared objects and LD_PRELOAD payloads that mimic them actually carry (`libfoo.so.1`, `libfoo.so.6.1`), since a plain `endswith('.so')` misses every one of those and this is exactly the version-suffix trap that defeats naive extension checks elsewhere in this corpus — written into a directory the dynamic linker has no special trust in but a user process can freely write to — `/tmp`, `/var/tmp`, `/dev/shm` and any path under `/home`. That is MITRE's own MonitoredDirectories knob, populated here with those four; a library staged in one of them is the physical artefact `LD_PRELOAD` (or a written `/etc/ld.so.preload` line) has to point at, regardless of which mechanism set the variable or whether this rule's own execve leg saw it. MITRE's CorrelationWindow knob — correlating this write with the later process that actually loads the library — is not attempted: lib/sigma has no aggregation or cross-event correlation, so this rule is a location-based content match on one write event, nothing more. The macOS leg AN1210 (`DYLD_INSERT_LIBRARIES`/`DYLD_LIBRARY_PATH`) is not attempted either: its log source is `macos:unifiedlog`, unstandardised in this corpus for the same reason as the third leg above. A PATH record like this one is only emitted for a syscall auditd is already watching, and a static `-w` watch cannot cover `/tmp`/`/dev/shm`/`/home` by inode the way it can a fixed file — this needs a broad `-S openat` (or `open`) audit rule with `-F success=1`, which is far higher-volume than a path watch and is not present in any mainstream default configuration; without it, this rule returns zero rows because nothing is being recorded, not because nothing was written. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0435, 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 2 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=* | where ((match(type, "(?i)^PATH$") AND match(name, "\\.so(\\.[0-9]+)*$")) AND (match(name, "(?i)/tmp/") OR match(name, "(?i)/var/tmp/") OR match(name, "(?i)/dev/shm/") OR match(name, "(?i)/home/")))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. --> <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)\.so(\.[0-9]+)*$</field> <field name="name" type="pcre2">(?i)(/tmp/|/var/tmp/|/dev/shm/|/home/)</field> <description>Shared object written into a non-standard directory Linux dynamic linker would trust</description> <mitre> <id>T1574.006</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.
Elastic · ES|QL
Run this as a search.
Elastic cannot express this construct. ES|QL RLIKE uses Lucene regexp syntax, which has no case-insensitive flag, and Sigma regexes are case-insensitive. Use |contains/|startswith/|endswith, or write the ES|QL 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.