-
Notifications
You must be signed in to change notification settings - Fork 431
Rod- Suspicious Local LLM Frameworks #3780
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
Merged
+316
−0
Merged
Changes from 21 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
0bc6470
newstory
rosplk 66e5a8a
firstdet
rosplk ab083a1
fixeddatasets
rosplk ebe530b
4688locallmdiscovery
rosplk 11488f2
sys1
rosplk ebb4f1e
sysmon
rosplk 233c0a6
secsys
rosplk 7304cfc
llmdns
rosplk 7d2ceb6
suspdownfix
rosplk ea51447
Update detections/endpoint/suspicious_local_llm_framework_download_an…
rosplk a7f446d
localdnstosuspicious
rosplk f5b7a08
windowsexecutionoflocallllmdet
rosplk 32eaac6
fixeddetections
rosplk 94c5c8e
deletedold
rosplk a39017b
fixedsearch
rosplk d7e72b3
fixedsuspiciouslocalllmframeworkprocessexecnospath
rosplk 8637e9f
Merge branch 'develop' into rodshai
rosplk e238ef6
fixedhowtoimplement
rosplk 6ecbaaa
fixhowtoimp
rosplk 6fbb3ba
fixdescription
rosplk 7fd8190
moredetails
rosplk 099db85
update detections
nasbench b66a683
small fixes
nasbench 9c75fca
updates
nasbench 22ace95
small change
nasbench 4488158
Merge branch 'develop' into rodshai
patel-bhavin ce28534
various fixes
patel-bhavin 8d9cd1e
remove dd for hunting detections
patel-bhavin 6267944
Merge branch 'develop' into rodshai
patel-bhavin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
detections/endpoint/suspicious_local_llm_framework_download_and_execution_via_sysmon.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| name: Suspicious Local LLM Framework Download and Execution via Sysmon | ||
| id: e27da0be-838a-40f2-bd4c-2dac4e7f6031 | ||
| version: 1 | ||
| date: '2025-11-12' | ||
| author: Rod Soto | ||
| status: production | ||
| type: Hunting | ||
| description: Detects execution of local LLM frameworks on Windows endpoints by monitoring Sysmon process creation events (Event ID 1) for known LLM tools including Ollama, GPT4All, LM Studio, Jan, llama.cpp, KoboldCPP, and Oobabooga. This hunting detection identifies shadow AI deployments and unauthorized local model inference operations by analyzing process execution patterns of LLM frameworks. | ||
| data_source: | ||
| - Sysmon EventID 1 | ||
| search: | | ||
| `sysmon` | spath | ||
nasbench marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| | eval EventID='Event.System.EventID' | ||
| | eval host='Event.System.Computer' | ||
| | eval Image=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "^Image$")) | ||
| | eval TargetFilename=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "^TargetFilename$")) | ||
| | eval QueryName=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "^QueryName$")) | ||
| | search ( Image="*ollama*" OR Image="*gpt4all*" OR Image="*lmstudio*" OR Image="*kobold*" OR Image="*jan*" OR Image="*llama-run*" OR Image="*llama.cpp*" OR Image="*oobabooga*" OR Image="*text-generation-webui*" OR TargetFilename="*.gguf*" OR TargetFilename="*ollama*" OR TargetFilename="*jan*" OR QueryName="*huggingface.co*" OR QueryName="*ollama.com*" ) | ||
| | search Image!="*MsMpEng*" AND Image!="*defender*" AND Image!="*windows/system32*" AND Image!="*syswow64*" AND Image!="*winlogon*" AND Image!="*svchost*" | ||
| | eval Framework=case( | ||
| match(Image, "(?i)ollama") OR match(TargetFilename, "(?i)ollama") OR match(QueryName, "(?i)ollama"), "Ollama", | ||
| match(Image, "(?i)lmstudio") OR match(Image, "(?i)lm-studio") OR match(TargetFilename, "(?i)lmstudio"), "LMStudio", | ||
| match(Image, "(?i)gpt4all") OR match(TargetFilename, "(?i)gpt4all"), "GPT4All", | ||
| match(Image, "(?i)kobold"), "KoboldCPP", | ||
| match(Image, "(?i)jan") OR match(TargetFilename, "(?i)jan"), "Jan AI", | ||
| match(Image, "(?i)llama-run") OR match(Image, "(?i)llama-b") OR match(Image, "(?i)llama.cpp"), "llama.cpp", | ||
| match(Image, "(?i)oobabooga") OR match(Image, "(?i)text-generation-webui"), "Oobabooga", | ||
| 1=1, "Other" | ||
| ) | ||
| | search Framework!="Other" | stats count by Framework, host, Image | sort -count | `suspicious_local_llm_framework_download_and_execution_via_sysmon_filter` | ||
| how_to_implement: Ensure Sysmon is deployed across Windows endpoints and configured to capture process creation events (Event ID 1). Configure Sysmon's XML configuration file to log detailed command-line arguments, parent process information, and full process image paths. Ingest Sysmon event logs into Splunk via the Splunk Universal Forwarder or Windows Event Log Input, ensuring they are tagged with `sourcetype=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational`. Verify the `sysmon` macro exists in your Splunk environment and correctly references the Sysmon event logs. Create or update the `suspicious_local_llm_framework_download_and_execution_via_sysmon_filter` macro in your detections/filters folder to exclude approved systems, authorized developers, sanctioned ML/AI workstations, or known development/lab environments as needed. Deploy this hunting search to your Splunk Enterprise Security or Splunk Enterprise instance and schedule it to run on a regular cadence to detect unauthorized LLM framework execution and shadow AI deployments. Correlate findings with endpoint asset inventory and user identity data to prioritize investigation. | ||
rosplk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| known_false_positives: Legitimate creation of LLM model files by authorized developers, ML engineers, and researchers during model training, fine-tuning, or experimentation. Approved AI/ML sandboxes and lab environments where model file creation is expected. Automated ML pipelines and workflows that generate or update model files as part of their normal operation. Third-party applications and services that manage or cache LLM model files for legitimate purposes. | ||
| references: | ||
| - https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon | ||
| - https://www.splunk.com/en_us/blog/artificial-intelligence/splunk-technology-add-on-for-ollama.html | ||
| - https://blogs.cisco.com/security/detecting-exposed-llm-servers-shodan-case-study-on-ollama | ||
| tags: | ||
| analytic_story: | ||
| - Suspicious Local Llm Frameworks | ||
| asset_type: Endpoint | ||
| mitre_attack_id: | ||
| - T1543 | ||
| product: | ||
| - Splunk Enterprise | ||
| - Splunk Enterprise Security | ||
| - Splunk Cloud | ||
| security_domain: endpoint | ||
| drilldown_searches: | ||
| - name: View the detection results for - "$host$" | ||
| search: '%original_detection_search% | search host="$host$"' | ||
| earliest_offset: $info_min_time$ | ||
| latest_offset: $info_max_time$ | ||
| - name: View risk events for the last 7 days for - "$host$" | ||
| search: | | ||
| | from datamodel Risk.All_Risk | ||
| | search normalized_risk_object="$host$" starthoursago=168 | ||
| | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | ||
| | `security_content_ctime(firstTime)` | ||
| | `security_content_ctime(lastTime)` | ||
| earliest_offset: $info_min_time$ | ||
| latest_offset: $info_max_time$ | ||
| tests: | ||
| - name: True Positive Test | ||
| attack_data: | ||
| - data: https://raw.githubusercontent.com/splunk/attack_data/master/datasets/suspicious_behaviour/local_llms/sysmon_local_llms.txt | ||
| sourcetype: XmlWinEventLog | ||
| source: XmlWinEventLog:Microsoft-Windows-Sysmon/Operational | ||
82 changes: 82 additions & 0 deletions
82
detections/endpoint/suspicious_local_llm_framework_process_execution.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| name: Suspicious Local LLM Framework Process Execution | ||
| id: 0ba9df5a-017c-4651-bb47-3764b06ddf28 | ||
| version: 1 | ||
| date: '2025-11-12' | ||
| author: Rod Soto | ||
| status: production | ||
| type: Hunting | ||
| description: Detects execution of unauthorized local LLM frameworks (Ollama, LM Studio, NutStudio, GPT4All, Jan, Llama-Run) on Windows endpoints by monitoring Event ID 4688 process creation events. Correlates process names and parent processes to identify shadow AI deployments, classifies integrity levels and elevation types, and surfaces process chains for investigation of potential unauthorized model inference or data exfiltration. | ||
| data_source: | ||
| - Windows Event Log Security 4688 | ||
| search: | | ||
| `wineventlog_security` EventCode=4688 | ||
| (NewProcessName="*ollama*" OR NewProcessName="*lmstudio*" OR | ||
| NewProcessName="*nutstudio*" OR NewProcessName="*gpt4all*" OR | ||
| NewProcessName="*jan*" OR NewProcessName="*llama-run*" OR | ||
| ParentProcessName="*ollama*" OR ParentProcessName="*lmstudio*" OR | ||
| ParentProcessName="*nutstudio*" OR ParentProcessName="*gpt4all*" OR | ||
| ParentProcessName="*jan*" OR ParentProcessName="*llama-run*") | ||
| | eval host=Computer | ||
| | eval Framework=case( | ||
| like(NewProcessName, "%ollama%") OR like(ParentProcessName, "%ollama%"), "Ollama", | ||
| like(NewProcessName, "%lmstudio%") OR like(ParentProcessName, "%lmstudio%"), "LM Studio", | ||
| like(NewProcessName, "%nutstudio%") OR like(ParentProcessName, "%nutstudio%"), "NutStudio", | ||
| like(NewProcessName, "%gpt4all%") OR like(ParentProcessName, "%gpt4all%"), "GPT4All", | ||
| like(NewProcessName, "%jan%") OR like(ParentProcessName, "%jan%"), "Jan", | ||
| like(NewProcessName, "%llama-run%") OR like(ParentProcessName, "%llama-run%"), "Llama-Run", | ||
| 1=1, "Other") | ||
| | eval IntegrityLevel=case( | ||
| MandatoryLabel="S-1-16-16384", "System", | ||
| MandatoryLabel="S-1-16-12288", "High", | ||
| MandatoryLabel="S-1-16-8192", "Medium", | ||
| MandatoryLabel="S-1-16-4096", "Low", | ||
| MandatoryLabel="S-1-16-0", "Untrusted", | ||
| 1=1, "Unknown") | ||
| | eval Elevation=case( | ||
| TokenElevationType="%%1936", "Full Token (Admin)", | ||
| TokenElevationType="%%1937", "Elevated", | ||
| TokenElevationType="%%1938", "Limited", | ||
| 1=1, "Unknown") | ||
| | eval ProcessChain=ParentProcessName + " -> " + NewProcessName | ||
| | table _time host Framework SubjectUserName SubjectDomainName SubjectLogonId IntegrityLevel Elevation ProcessChain CommandLine NewProcessId ProcessId | ||
| | sort -_time | ||
| | dedup ProcessChain | ||
| | `suspicious_local_llm_framework_process_execution_filter` | ||
| how_to_implement: Ensure Windows Security Event Log collection (Event ID 4688 - Process Creation) is enabled and ingested into Splunk. Configure your Windows systems to audit process creation via Group Policy (Computer Configuration > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Detailed Tracking > Audit Process Creation). Verify the `wineventlog_security` macro exists in your Splunk environment and points to the correct index. Ensure your Splunk forwarder or Windows Event Log Input app correctly normalizes these fields. Create or update the `suspicious_local_llm_framework_process_execution_filter` macro in your detections/filters folder to exclude approved systems, users, or frameworks as needed. Deploy this hunting search to your Splunk Enterprise Security or Splunk Enterprise instance and schedule it to run on a regular cadence to detect unauthorized LLM framework execution. Alert on deviations from baseline process chains and integrity/elevation levels for your environment. | ||
| known_false_positives: Legitimate development, data science, and AI/ML workflows where authorized developers, researchers, or engineers intentionally execute local LLM frameworks (Ollama, LM Studio, GPT4All, Jan) for model experimentation, fine-tuning, or prototyping. Approved sandbox and lab environments where framework testing is authorized. Open-source contributors and hobbyists running frameworks for educational purposes or community projects. Third-party applications that bundle or invoke LLM frameworks as dependencies (e.g., IDE plugins, analytics tools, chatbot integrations). System administrators deploying frameworks as part of containerized services or orchestrated ML workloads. Process name keyword overlap with unrelated utilities (e.g., "llama-backup", "janimation", "gpt4-config"). Recommended tuning — baseline approved frameworks and users by role/department, exclude sanctioned dev/lab systems, correlate with user identity and peer group anomalies before escalating to incident response. | ||
| references: | ||
| - https://splunkbase.splunk.com/app/8024 | ||
| - https://www.ibm.com/think/topics/shadow-ai | ||
| - https://www.splunk.com/en_us/blog/artificial-intelligence/splunk-technology-add-on-for-ollama.html | ||
| - https://blogs.cisco.com/security/detecting-exposed-llm-servers-shodan-case-study-on-ollama | ||
| drilldown_searches: | ||
| - name: View the detection results for - "$host$" | ||
| search: '%original_detection_search% | search host="$host$"' | ||
| earliest_offset: $info_min_time$ | ||
| latest_offset: $info_max_time$ | ||
| - name: View risk events for the last 7 days for - "$host$" | ||
| search: | | ||
| | from datamodel Risk.All_Risk | ||
| | search normalized_risk_object="$host$" starthoursago=168 | ||
| | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | ||
| | `security_content_ctime(firstTime)` | ||
| | `security_content_ctime(lastTime)` | ||
| earliest_offset: $info_min_time$ | ||
| latest_offset: $info_max_time$ | ||
| tags: | ||
| analytic_story: | ||
| - Suspicious Local Llm Frameworks | ||
| asset_type: Endpoint | ||
| mitre_attack_id: | ||
| - T1543 | ||
| product: | ||
| - Splunk Enterprise | ||
| - Splunk Enterprise Security | ||
| - Splunk Cloud | ||
| security_domain: endpoint | ||
| tests: | ||
| - name: True Positive Test | ||
| attack_data: | ||
| - data: https://raw.githubusercontent.com/splunk/attack_data/master/datasets/suspicious_behaviour/local_llms/4688_local_llms.txt | ||
| sourcetype: XmlWinEventLog | ||
| source: XmlWinEventLog:Security |
56 changes: 56 additions & 0 deletions
56
detections/endpoint/unauthorized_llm_model_file_creation_on_endpoint.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| name: Unauthorized LLM Model File Creation on Endpoint | ||
| id: 23e5b797-378d-45d6-ab3e-d034ca12a99b | ||
| version: 1 | ||
| date: '2025-11-12' | ||
| author: Rod Soto | ||
| status: production | ||
| type: Hunting | ||
| description: Detects unauthorized creation of Large Language Model (LLM) files on Windows endpoints by monitoring Sysmon Event ID 11 (File Creation) for specific model file formats and extensions commonly used by local AI frameworks. This detection identifies shadow AI deployments, unauthorized model downloads, and rogue LLM infrastructure by detecting file creation patterns associated with quantized models (.gguf, .ggml), safetensors model format files, and Ollama Modelfiles. These file types are characteristic of local inference frameworks such as Ollama, llama.cpp, GPT4All, LM Studio, and similar tools that enable running LLMs locally without cloud dependencies. Organizations can use this detection to identify potential data exfiltration risks, policy violations related to unapproved AI usage, and security blind spots created by decentralized AI deployments that bypass enterprise governance and monitoring. | ||
| data_source: | ||
| - Sysmon EventID 11 | ||
| search: | | ||
| `sysmon`| spath | ||
nasbench marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| | search Event.System.EventID=11 | ||
| | eval host='Event.System.Computer' | eval TargetFilename=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "^TargetFilename$")) | ||
| | eval Image=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "^Image$")) | ||
| | search TargetFilename="*.gguf*" OR TargetFilename="*ggml*" OR TargetFilename="*safetensors*" OR TargetFilename="*Modelfile*" | ||
| | table _time, host, Image, TargetFilename | ||
| | `unauthorized_llm_model_file_creation_on_endpoint_filter` | ||
| how_to_implement: Ensure Sysmon is deployed across Windows endpoints and configured to capture process creation events (Event ID 11). Configure Sysmon's XML configuration file to log detailed command-line arguments, parent process information, and full process image paths. Ingest Sysmon event logs into Splunk via the Splunk Universal Forwarder or Windows Event Log Input, ensuring they are tagged with `sourcetype=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational`. Verify the `sysmon` macro exists in your Splunk environment and correctly references the Sysmon event logs. Create or update the `suspicious_local_llm_framework_download_and_execution_via_sysmon_filter` macro in your detections/filters folder to exclude approved systems, authorized developers, sanctioned ML/AI workstations, or known development/lab environments as needed. Deploy this hunting search to your Splunk Enterprise Security or Splunk Enterprise instance and schedule it to run on a regular cadence to detect unauthorized LLM framework execution and shadow AI deployments. Correlate findings with endpoint asset inventory and user identity data to prioritize investigation. | ||
| known_false_positives: Legitimate creation of LLM model files by authorized developers, ML engineers, and researchers during model training, fine-tuning, or experimentation. Approved AI/ML sandboxes and lab environments where model file creation is expected. Automated ML pipelines and workflows that generate or update model files as part of their normal operation. Third-party applications and services that manage or cache LLM model files for legitimate purposes. | ||
| references: | ||
| - https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon | ||
| - https://www.ibm.com/think/topics/shadow-ai | ||
| - https://www.splunk.com/en_us/blog/artificial-intelligence/splunk-technology-add-on-for-ollama.html | ||
| - https://blogs.cisco.com/security/detecting-exposed-llm-servers-shodan-case-study-on-ollama | ||
| tags: | ||
| analytic_story: | ||
| - Suspicious Local Llm Frameworks | ||
| asset_type: Endpoint | ||
| mitre_attack_id: | ||
| - T1543 | ||
| product: | ||
| - Splunk Enterprise | ||
| - Splunk Enterprise Security | ||
| - Splunk Cloud | ||
| security_domain: endpoint | ||
| drilldown_searches: | ||
| - name: View the detection results for - "$host$" | ||
| search: '%original_detection_search% | search host="$host$"' | ||
| earliest_offset: $info_min_time$ | ||
| latest_offset: $info_max_time$ | ||
| - name: View risk events for the last 7 days for - "$host$" | ||
| search: | | ||
| | from datamodel Risk.All_Risk | ||
| | search normalized_risk_object="$host$" starthoursago=168 | ||
| | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | ||
| | `security_content_ctime(firstTime)` | ||
| | `security_content_ctime(lastTime)` | ||
| earliest_offset: $info_min_time$ | ||
| latest_offset: $info_max_time$ | ||
| tests: | ||
| - name: True Positive Test | ||
| attack_data: | ||
| - data: https://raw.githubusercontent.com/splunk/attack_data/master/datasets/suspicious_behaviour/local_llms/sysmon_local_llms.txt | ||
| sourcetype: XmlWinEventLog:Microsoft-Windows-Sysmon/Operational | ||
| source: XmlWinEventLog:Microsoft-Windows-Sysmon/Operational | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.