-
Notifications
You must be signed in to change notification settings - Fork 523
[Osquery_manager] Services artifacts saved queries #15892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: temporary-osquery-artifacts-branch
Are you sure you want to change the base?
[Osquery_manager] Services artifacts saved queries #15892
Conversation
…es-artifact # Conflicts: # packages/osquery_manager/artifacts_matrix.md
…es-artifact # Conflicts: # packages/osquery_manager/artifacts_matrix.md
ferullo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you see results for all the Windows columns? I ran the Windows query and the failure_*, service_dll, servicedll_* fields were always empty for me.
| "key": "process.executable", | ||
| "value": { | ||
| "field": "path" | ||
| } | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ferullo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to keep leaving disjoint comments...
Windows registry and file paths are case insensitive. Should that be accounted for in the query?
|
Thanks @ferullo - I totally forgot about your comments, I'll review them on Monday :) |
|
QQ - In terms of the query itself, why the failure commands are considered for persistence? |
…r PR feedback - Renamed 'path' to 'cmd' and mapped to process.command_line (per @ferullo review) - Added executable_path extraction (handles quoted paths and paths with args) - Updated hash/authenticode JOINs to use extracted executable path - Removed failure_actions_raw (binary blob not useful in ECS) - Updated ECS mappings accordingly
…ry-builder guidelines - Added LEFT JOIN to hash table for MD5/SHA256 of program executable - Added LEFT JOIN to signature table for code signing validation - Added ECS mappings for file.hash.* and file.code_signature.* - Added MITRE ATT&CK references in comments - Added 'code_signing' tag
…ry-builder guidelines - Added LEFT JOIN to hash table for MD5/SHA256 of unit file (fragment_path) - Enables integrity monitoring to detect tampered service definitions - Added ECS mappings for file.hash.md5 and file.hash.sha256 - Added MITRE ATT&CK reference in comments (T1543.002) - Added 'integrity_monitoring' tag
- Added LOWER() to hash/authenticode JOINs for case-insensitive matching - Windows paths are case-insensitive but SQLite comparisons are case-sensitive - Added inline comment explaining FailureCommand as persistence vector - Added note about LOWER() usage in query header
…noise - Use regex_match() to exclude Apple paths (/System/, /Library/Apple/) - Exclude Apple-signed services regardless of path - Add service_type classification column - Add ECS mapping for service.type - Reduce results from ~600 to ~10-20
…focus - Update description to reflect threat hunting use case - Add process.command_line ECS mapping - Rename path field to exe_path for clarity - Add process.pid mapping - Focus on suspicious indicators (unsigned, unusual paths, persistence)
…tection - Rename from services_systemd_linux_elastic to services_suspicious_linux - Focus on suspicious locations (user dirs, /tmp, ~/.config/systemd) - Add file modification time and hash enrichment - Add threat_hunting and suspicious tags - Add 120s timeout for complex query
- Rename query IDs to services_suspicious_* pattern - Update descriptions to reflect threat hunting focus - Add MITRE ATT&CK references - Update last modified date
…osquery-services-artifact # Conflicts: # packages/osquery_manager/kibana/osquery_saved_query/osquery_manager-5823a22e-5add-416d-a142-de323400edb0.json # packages/osquery_manager/kibana/osquery_saved_query/osquery_manager-892ee425-60e7-4eb6-ba25-6e97dc3e2ea0.json # packages/osquery_manager/kibana/osquery_saved_query/osquery_manager-f8b0894b-772d-4242-8e19-dbc5d7ae2e06.json
I adjusted the query a bit, and also reproduced failure attack and some dlls on my machine. The data is there - now available on the screenshots. |
| "interval": "3600", | ||
| "timeout": 120, | ||
| "platform": "darwin", | ||
| "query": "-- macOS Suspicious LaunchD Services Detection (Optimized)\n-- Source: Native osquery tables (launchd, signature, hash)\n-- Focus: Third-party persistence only - excludes all Apple services\n-- MITRE ATT&CK: T1543.001 (Launch Agent), T1543.004 (Launch Daemon)\n\nWITH services_enriched AS (\n SELECT\n l.label,\n l.name,\n l.path,\n l.program,\n l.program_arguments,\n l.run_at_load,\n l.keep_alive,\n COALESCE(l.username, 'root') AS username,\n COALESCE(s.signed, 0) AS is_signed,\n s.authority AS signer,\n CASE WHEN s.signed = 1 THEN 'signed' ELSE 'unsigned' END AS signature_status,\n (SELECT sha256 FROM hash WHERE path = l.program LIMIT 1) AS sha256,\n -- Classify service type for analysis\n CASE\n WHEN l.path LIKE '/Library/LaunchDaemons/%' THEN 'System-Daemon'\n WHEN l.path LIKE '/Library/LaunchAgents/%' THEN 'System-Agent'\n WHEN l.path LIKE '%/Library/LaunchAgents/%' THEN 'User-Agent'\n ELSE 'Other'\n END AS service_type\n FROM launchd l\n LEFT JOIN signature s ON s.path = l.program\n WHERE l.path IS NOT NULL AND l.path != ''\n)\n\nSELECT *\nFROM services_enriched\n-- EXCLUDE all Apple/system services using consolidated regex\nWHERE regex_match(\n path,\n '^(/System/|/Library/Apple/|/usr/libexec/)',\n 0\n) IS NULL\n AND regex_match(\n COALESCE(signer, ''),\n '(Apple|Software Signing)',\n 0\n) IS NULL\n-- Focus on suspicious indicators\nAND (\n -- Unsigned is always suspicious\n is_signed = 0\n -- Or in suspicious locations\n OR program LIKE '/Users/%'\n OR program LIKE '/tmp/%'\n OR program LIKE '/var/tmp/%'\n OR program LIKE '/private/tmp/%'\n OR program LIKE '%/.%'\n -- Or third-party with persistence enabled\n OR (is_signed = 1 AND run_at_load = '1')\n)\nORDER BY\n is_signed ASC,\n service_type,\n label;", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to offer an SQL update diff but I kept hitting a wall putting my thoughts into code so I'll just leave this comment for now.
- Can we modify this to return all (1) non-Apple services and (2) all services, even if signed by Apple, run from suspicious locations (for both, regardless of whether they run at load)? That seems a small superset of what this query currently returns.
- Lots of services seem to have a NULL
programbecause the program is actually found inprogram_arguments. Those services appear unsigned because signatures are only checked againstprogramin theWITHclause.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ferullo, thanks - these are great tips 👍
I think I understood your suggestions, but please tell me if you think there's still something that needs adjustments.
Changes:
- Broader scope: Query now returns ALL non-Apple-signed services regardless of
run_at_load, plus Apple-signed services (Software Signing) running from suspicious locations (/tmp/, /Users/, /var/tmp/, hidden /.directories) - Fixed NULL
program: Addedexecutable_pathderivation that extracts fromprogramfirst, falls back to first element ofprogram_argumentswhen program is NULL. Signature and hash lookups now use this derived path.
Changes: - Broaden scope to return ALL non-Apple-signed services (not just those with run_at_load enabled) for comprehensive threat hunting - Add detection of Apple-signed services in suspicious locations (/tmp, /Users, /var/tmp, hidden directories) - Fix NULL program issue by deriving executable_path from program field or first element of program_arguments - Use subqueries for signature lookups to avoid duplicate rows - Fix is_signed logic to check authority presence instead of signed boolean (which indicates notarization, not signing) - Fix username handling for empty strings with NULLIF - Add process.args ECS mapping for program_arguments - Update artifacts_matrix.md description
ferullo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. This is obviously a lot of work.
| } | ||
| }, | ||
| { | ||
| "key": "process.args", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be process.command_line
process.args is an array, process.command_line is the joined string.
| "key": "file.hash.sha256", | ||
| "value": { | ||
| "field": "sha256" | ||
| } | ||
| }, | ||
| { | ||
| "key": "file.code_signature.subject_name", | ||
| "value": { | ||
| "field": "signer" | ||
| } | ||
| }, | ||
| { | ||
| "key": "file.code_signature.status", | ||
| "value": { | ||
| "field": "signature_status" | ||
| } | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be under process.* not file.*. file.path is the path to the service configuration file but these hashes are for the process executable.
| "interval": "3600", | ||
| "timeout": 120, | ||
| "platform": "linux", | ||
| "query": "-- Linux Suspicious Systemd Services Detection\n-- Source: Native osquery tables (systemd_units, file, hash)\n-- Focus: Detect suspicious/malicious systemd services - NOT a full inventory\n-- MITRE ATT&CK: T1543.002 (Systemd Service)\n\nWITH services_enriched AS (\n SELECT\n su.id,\n su.load_state,\n su.active_state,\n su.sub_state,\n su.description,\n su.unit_file_state,\n su.fragment_path,\n f.mtime AS file_mtime,\n CAST((strftime('%s', 'now') - f.mtime) / 86400 AS INTEGER) AS days_since_modified,\n (SELECT sha256 FROM hash WHERE path = su.fragment_path LIMIT 1) AS sha256\n FROM systemd_units su\n LEFT JOIN file f ON f.path = su.fragment_path\n WHERE su.id LIKE '%.service'\n AND su.fragment_path IS NOT NULL\n AND su.fragment_path != ''\n)\n\nSELECT *\nFROM services_enriched\nWHERE (\n -- HIGH RISK: Service unit in user home directories\n fragment_path LIKE '/home/%'\n OR fragment_path LIKE '/root/%'\n -- HIGH RISK: Service unit in temp directories\n OR fragment_path LIKE '/tmp/%'\n OR fragment_path LIKE '/var/tmp/%'\n -- HIGH RISK: User systemd units (persistence location)\n OR fragment_path LIKE '%/.config/systemd/%'\n OR fragment_path LIKE '%/.local/share/systemd/%'\n -- MEDIUM RISK: Unusual unit_file_state (not standard enabled/disabled/static)\n OR unit_file_state IN ('linked', 'linked-runtime', 'transient')\n -- MEDIUM RISK: Service in /etc/systemd but not standard package install\n OR (fragment_path LIKE '/etc/systemd/system/%' AND days_since_modified < 30)\n -- MEDIUM RISK: Service in /run (runtime generated)\n OR fragment_path LIKE '/run/systemd/%'\n)\nORDER BY\n CASE WHEN fragment_path LIKE '/home/%' OR fragment_path LIKE '/tmp/%' THEN 0 ELSE 1 END,\n CASE WHEN fragment_path LIKE '%/.config/systemd/%' THEN 0 ELSE 1 END,\n days_since_modified ASC;", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the below snippet the actual criteria doesn't match the comment. If we just want to return new services I guess update the comment and we can just remove the fragment path check?
-- MEDIUM RISK: Service in /etc/systemd but not standard package install
OR (fragment_path LIKE '/etc/systemd/system/%' AND days_since_modified < 30)
Also, the hashes are for the service file itself not the executable that's run unlike on macOS (I haven't checked which Windows does). Since the executable path isn't included I assume you just can't retrieve it to join against? In that case can we just drop the hash in this table?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, removed the comment, and the hash 👍
| { | ||
| "key": "file.code_signature.subject_name", | ||
| "value": { | ||
| "field": "cert_subject" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider renaming cert_subject to signature_subject for consistency within this query or signer for consistency with macOS.
| { | ||
| "key": "service.type", | ||
| "value": { | ||
| "field": "start_type" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This column doesn't seem to be what ECS says service.type should be and it feels different from the type of data being put in this column on macOS. Maybe just drop mapping this column?
| "key": "file.hash.sha256", | ||
| "value": { | ||
| "field": "sha256" | ||
| } | ||
| }, | ||
| { | ||
| "key": "file.code_signature.subject_name", | ||
| "value": { | ||
| "field": "cert_subject" | ||
| } | ||
| }, | ||
| { | ||
| "key": "file.code_signature.status", | ||
| "value": { | ||
| "field": "signature_status" | ||
| } | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these should move from file.* to process.* since they correspond to the process.executable binary and on macOS file.path is being used for the service configuration file.
| "interval": "3600", | ||
| "timeout": 180, | ||
| "platform": "windows", | ||
| "query": "-- Windows Suspicious Services Detection\n-- Source: Native osquery tables (services, registry, hash, authenticode)\n-- Focus: Detect suspicious/malicious services - NOT a full inventory\n-- Filters: Unsigned binaries, unusual paths, persistence mechanisms, recent changes\n-- MITRE ATT&CK: T1543.003 (Windows Service), T1574.011 (ServiceDLL Hijacking), T1112 (Modify Registry)\n\nWITH services_registry AS (\n SELECT\n s.name,\n s.display_name,\n s.path AS cmd,\n CASE\n WHEN s.path LIKE '\"%' THEN\n SUBSTR(s.path, 2, INSTR(SUBSTR(s.path, 2), '\"') - 1)\n WHEN INSTR(LOWER(s.path), '.exe ') > 0 THEN\n SUBSTR(s.path, 1, INSTR(LOWER(s.path), '.exe') + 3)\n WHEN INSTR(LOWER(s.path), '.sys ') > 0 THEN\n SUBSTR(s.path, 1, INSTR(LOWER(s.path), '.sys') + 3)\n ELSE s.path\n END AS exe_path,\n s.status,\n s.start_type,\n s.user_account,\n s.service_type,\n s.pid,\n 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\' || s.name AS registry_path,\n r_key.mtime AS service_registry_mtime,\n r_dll.data AS service_dll,\n r_failcmd.data AS failure_command\n FROM services s\n LEFT JOIN registry r_key ON r_key.key = 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\' || s.name AND r_key.name = 'Start'\n LEFT JOIN registry r_dll ON r_dll.key = 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\' || s.name || '\\Parameters' AND r_dll.name = 'ServiceDll'\n LEFT JOIN registry r_failcmd ON r_failcmd.key = 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\' || s.name AND r_failcmd.name = 'FailureCommand'\n WHERE s.service_type NOT LIKE '%DRIVER%'\n AND s.path IS NOT NULL\n AND s.path != ''\n),\nservices_enriched AS (\n SELECT\n sr.*,\n CAST((strftime('%s', 'now') - sr.service_registry_mtime) / 86400 AS INTEGER) AS days_since_modified,\n (SELECT sha256 FROM hash WHERE path = sr.exe_path LIMIT 1) AS sha256,\n (SELECT subject_name FROM authenticode WHERE path = sr.exe_path LIMIT 1) AS cert_subject,\n (SELECT result FROM authenticode WHERE path = sr.exe_path LIMIT 1) AS signature_status,\n CASE WHEN sr.service_dll IS NOT NULL AND sr.service_dll != '' THEN\n (SELECT sha256 FROM hash WHERE path = sr.service_dll LIMIT 1)\n END AS servicedll_sha256,\n CASE WHEN sr.service_dll IS NOT NULL AND sr.service_dll != '' THEN\n (SELECT result FROM authenticode WHERE path = sr.service_dll LIMIT 1)\n END AS servicedll_signature_status\n FROM services_registry sr\n)\n\nSELECT *\nFROM services_enriched\nWHERE (\n -- HIGH RISK: Unsigned or untrusted binary (not in trusted paths)\n ((signature_status IS NULL OR signature_status != 'trusted')\n AND exe_path NOT LIKE 'C:\\\\Windows\\\\System32\\\\%'\n AND exe_path NOT LIKE 'C:\\\\Windows\\\\SysWOW64\\\\%')\n -- HIGH RISK: Running from user-writable directories\n OR exe_path LIKE 'C:\\\\Users\\\\%'\n OR exe_path LIKE '%\\\\AppData\\\\%'\n OR exe_path LIKE '%\\\\Temp\\\\%'\n OR exe_path LIKE 'C:\\\\Temp\\\\%'\n OR exe_path LIKE 'C:\\\\ProgramData\\\\%'\n -- HIGH RISK: Has persistence via FailureCommand\n OR failure_command IS NOT NULL\n -- HIGH RISK: ServiceDLL with untrusted signature (DLL hijacking)\n OR (service_dll IS NOT NULL AND (servicedll_signature_status IS NULL OR servicedll_signature_status != 'trusted'))\n)\nORDER BY\n CASE WHEN signature_status IS NULL OR signature_status != 'trusted' THEN 0 ELSE 1 END,\n CASE WHEN failure_command IS NOT NULL THEN 0 ELSE 1 END,\n CASE WHEN exe_path LIKE 'C:\\\\Users\\\\%' OR exe_path LIKE '%\\\\Temp\\\\%' THEN 0 ELSE 1 END;", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about changing this snippet to drop the exe_path checks. There's nothing special about c:\windows, malware could place itself in that directory.
-- HIGH RISK: Unsigned or untrusted binary (not in trusted paths)
((signature_status IS NULL OR signature_status != 'trusted')
AND exe_path NOT LIKE 'C:\\Windows\\System32\\%'
AND exe_path NOT LIKE 'C:\\Windows\\SysWOW64\\%')
- Add _elastic suffix to query ID for consistency - Add structured ECS fields: event.category, event.type, event.kind, event.module, event.dataset, host.os.type - Add MITRE ATT&CK threat framework mappings - Change hash/signature fields from file.* to process.* namespace - Rename column aliases for clarity (cert_subject → signature_signer) - Add human-readable mtime_utc timestamp - Simplify query comments and description
- Add _elastic suffix to query ID for consistency - Add structured ECS fields: event.category, event.type, event.kind, event.module, event.dataset, host.os.type - Add MITRE ATT&CK threat framework mappings - Change hash/signature fields from file.* to process.* namespace - Rename column aliases (signer → signature_signer, service_type → launchd_type) - Simplify query structure with renamed CTEs
- Add _elastic suffix to query ID for consistency - Add structured ECS fields: event.category, event.type, event.kind, event.module, event.dataset, host.os.type - Add MITRE ATT&CK threat framework mappings - Add file.mtime ECS mapping for modification time - Rename column (id → unit_id) for clarity - Add human-readable mtime_utc timestamp
Align query ID references with renamed queries across all platforms.
- Rename Windows registry_mtime_utc to modified_time for ECS consistency - Rename Linux mtime_utc to modified_time for ECS consistency - Add file.mtime ECS mapping to Windows services query - Align both queries with file.mtime ECS field standard
| { | ||
| "key": "file.mtime", | ||
| "value": { | ||
| "field": "modified_time" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comes back as seconds since epoch. IMO it would be cool if in the query results the type was a date string. Especially since for Windows it seems the time is a data string and it seems friendlier for the times to always be the same format across OSes and queries.
…ents - Address review feedback: Change process.* to file.* for hash/signature fields (hash and signature apply to the executable file, not the running process) - Windows: Fix ECS mappings for sha256, code_signature.subject_name, code_signature.status - macOS: Fix ECS mappings for md5, sha256, code_signature.subject_name, code_signature.status - Linux: Remove raw mtime column, only expose datetime-formatted modified_time - Add COALESCE null safety for days_since_modified calculations - Clean up column selection in Windows query CTE
- Replace event.kind/module/dataset/host.os.type with event.action - Add "osquery" tag, remove verbose MITRE ATT&CK tags - Remove threat.framework and threat.tactic/technique context fields - Clean up MITRE references from SQL query comments
- Fix ECS mappings: file.hash.* → process.hash.* for service executable enrichment - Fix ECS mappings: file.code_signature.* → process.code_signature.* - Add VirusTotal link (vt_link) for quick hash lookup - Clean up inline comment formatting
- Fix ECS mappings: file.hash.sha256 → process.hash.sha256 - Fix ECS mappings: file.code_signature.* → process.code_signature.* - Add VirusTotal link (vt_link) for quick hash lookup
- Remove sha256 hash computation (hash table unreliable for unit files) - Remove file.hash.sha256 ECS mapping (column no longer exists)
💚 Build Succeeded
History
cc @tomsonpl |

Services Artifact - Suspicious Service Persistence Detection
The Services artifact provides comprehensive visibility into system service configurations across Windows, macOS, and Linux platforms. These queries identify suspicious services that may indicate persistence mechanisms, privilege escalation, or lateral movement by analyzing service executables, code signatures, file locations, and configuration anomalies.
Core Forensic Artifacts Coverage
Queries by Platform
🪟 Windows - Suspicious Service Persistence Detection
Description
Identifies suspicious Windows services using multiple risk indicators: unsigned/untrusted binaries, executables in user-writable directories (Users, AppData, Temp, ProgramData), FailureCommand persistence mechanisms, and ServiceDLL hijacking with untrusted DLLs. Results prioritized by risk level. Covers MITRE ATT&CK T1543.003 (Windows Service), T1574.011 (Services Registry Permissions Weakness), T1112 (Modify Registry).
Detection Focus:
Result
[Query results will show suspicious services with their executable paths, code signature status, ServiceDLL information, and failure command configurations prioritized by risk level]
Platform
windowsInterval
3600seconds (1 hour)Query ID
services_suspicious_windows_elasticECS Field Mappings
event.category→["configuration"]event.type→["info"]event.kind→stateevent.module→osqueryevent.dataset→osquery.windows_serviceshost.os.type→windowsservice.name→nameservice.state→statusprocess.command_line→cmdlineprocess.executable→exe_pathprocess.pid→piduser.name→user_accountprocess.hash.sha256→sha256process.code_signature.subject_name→signature_signerprocess.code_signature.status→signature_statusregistry.path→registry_pathfile.mtime→modified_timedll.path→service_dlldll.hash.sha256→dll_sha256dll.code_signature.status→dll_signature_statustags→["persistence", "threat_hunting", "services", "windows", "mitre_t1543_003", "mitre_t1574_011"]threat.framework→MITRE ATT&CKthreat.tactic.id→["TA0003", "TA0004"]threat.tactic.name→["Persistence", "Privilege Escalation"]threat.technique.id→["T1543.003", "T1574.011"]threat.technique.name→["Create or Modify System Process: Windows Service", "Hijack Execution Flow: Services Registry Permissions Weakness"]SQL Query
🍎 macOS - LaunchD Persistence Detection
Description
Identifies third-party macOS launchd persistence mechanisms and Apple-signed services in suspicious locations. Enumerates non-Apple-signed services for threat hunting, flags Apple-signed binaries executing from user-writable paths (/Users/, /tmp/, hidden directories). Derives executable from program or program_arguments fields, enriches with code signature validation and file hashes. Excludes trusted system paths (/System/, /Library/Apple/). Covers MITRE ATT&CK T1543.001 (Launch Agent) and T1543.004 (Launch Daemon).
Detection Focus:
Result
[Query results will show suspicious launchd services with their labels, executable paths, code signatures, and file hashes sorted by signature status and launchd type]
Platform
darwinInterval
3600seconds (1 hour)Query ID
services_suspicious_darwin_elasticECS Field Mappings
event.category→["configuration"]event.type→["info"]event.kind→stateevent.module→osqueryevent.dataset→osquery.launchd_serviceshost.os.type→macosservice.name→labelfile.path→pathprocess.executable→executable_pathprocess.command_line→program_argumentsuser.name→usernameprocess.hash.md5→md5process.hash.sha256→sha256process.code_signature.subject_name→signature_signerprocess.code_signature.status→signature_statustags→["persistence", "threat_hunting", "launchd", "macos", "mitre_t1543_001", "mitre_t1543_004"]threat.framework→MITRE ATT&CKthreat.tactic.id→["TA0003"]threat.tactic.name→["Persistence"]threat.technique.id→["T1543.001", "T1543.004"]threat.technique.name→["Create or Modify System Process: Launch Agent", "Create or Modify System Process: Launch Daemon"]SQL Query
🐧 Linux - Systemd Service Persistence Detection
Description
Identifies suspicious Linux systemd service units in non-standard locations. Targets user-writable paths (/home, /tmp, /var/tmp), user systemd directories (~/.config/systemd, ~/.local/share/systemd), unusual unit states (linked, transient), recently modified units in /etc/systemd/system, and runtime-generated units in /run. Prioritizes results by risk level. Covers MITRE ATT&CK T1543.002 (Systemd Service).
Detection Focus:
Result
[Query results will show suspicious systemd service units with their paths, states, modification times, and file hashes prioritized by risk level (user-writable paths first)]
Platform
linuxInterval
3600seconds (1 hour)Query ID
services_suspicious_linux_elasticECS Field Mappings
event.category→["configuration"]event.type→["info"]event.kind→stateevent.module→osqueryevent.dataset→osquery.systemd_serviceshost.os.type→linuxservice.name→unit_idservice.state→active_statefile.path→fragment_pathfile.mtime→modified_timefile.hash.sha256→sha256tags→["persistence", "threat_hunting", "systemd", "linux", "mitre_t1543_002"]threat.framework→MITRE ATT&CKthreat.tactic.id→["TA0003"]threat.tactic.name→["Persistence"]threat.technique.id→["T1543.002"]threat.technique.name→["Create or Modify System Process: Systemd Service"]SQL Query
MITRE ATT&CK Coverage Summary
This PR was AI assisted with Claude Code