-
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 9 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
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,77 @@ | ||
| name: Local LLM Model DNS Queries | ||
| id: e0cda953-b926-4778-b7df-df61dab7bb78 | ||
| version: 1 | ||
| date: '2025-11-12' | ||
| author: Rod Soto | ||
| status: production | ||
| type: Hunting | ||
| description: Detects DNS queries related to local LLM models on endpoints by monitoring Sysmon DNS query events (Event ID 22) for known LLM model domains and services. | ||
| data_source: | ||
| - Sysmon EventID 22 | ||
| search: | | ||
| `sysmon` | spath | ||
| | search Event.System.EventID=22 | ||
| | eval host='Event.System.Computer' | ||
| | eval QueryName=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "^QueryName$")) | ||
| | eval Image=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "^Image$")) | ||
| | search QueryName="*huggingface*" OR | ||
| QueryName="*ollama*" OR | ||
| QueryName="*jan.ai*" OR | ||
| QueryName="*gpt4all*" OR | ||
| QueryName="*nomic*" OR | ||
| QueryName="*koboldai*" OR | ||
| QueryName="*lmstudio*" OR | ||
| QueryName="*modelscope*" OR | ||
| QueryName="*civitai*" OR | ||
| QueryName="*github.com*llama*" OR | ||
| QueryName="*github.com*oobabooga*" OR | ||
| QueryName="*github.com*koboldai*" OR | ||
| QueryName="*replicate*" OR | ||
| QueryName="*anthropic*" OR | ||
| QueryName="*openai*" OR | ||
| QueryName="*openrouter*" OR | ||
| QueryName="*api.openrouter*" OR | ||
| QueryName="*aliyun*" OR | ||
| QueryName="*alibabacloud*" OR | ||
| QueryName="*dashscope.aliyuncs*" | ||
| | search Image!="*MsMpEng.exe*" AND Image!="*Windows Defender*" AND Image!="*system32*" AND Image!="*ProgramData*" AND Image!="*syswow64*" | ||
| | stats count by _time, host, Image, QueryName | ||
| | sort -count | ||
| | `local_llm_model_dns_queries_filter` | ||
| how_to_implement: Ensure Sysmon is deployed across Windows endpoints and configured to capture DNS query events (Event ID 22). 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 `local_llm_model_dns_queries_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 model DNS queries and shadow AI activities. Correlate findings with endpoint asset inventory and user identity data to prioritize investigation. | ||
| known_false_positives: Legitimate DNS queries to LLM model hosting platforms by authorized developers, ML engineers, and researchers during model training, fine-tuning, or experimentation. Approved AI/ML sandboxes and lab environments where LLM model downloads are expected. Automated ML pipelines and workflows that interact with LLM model hosting services as part of their normal operation. Third-party applications and services that access LLM model platforms 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: | ||
| - T1590 | ||
| 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 | ||
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,92 @@ | ||
| name: Suspicious Local LLM Framework | ||
rosplk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| id: 657b022a-9c50-4910-8572-f036cc4a0248 | ||
| version: 1 | ||
| date: '2025-11-12' | ||
| author: Rod Soto | ||
| status: production | ||
| type: Hunting | ||
| description: This detection identifies suspicious execution of unauthorized local LLM frameworks (Ollama, LM Studio, GPT4All, Jan, Llama.cpp, KoboldCPP, NutStudio, Llama-Run) and related AI/ML libraries (HuggingFace, LangChain, Transformers) by monitoring Windows process creation events (Event ID 4688). The search correlates process names, command-line arguments, and parent processes to classify framework activity and flag potential shadow AI deployments or unauthorized model inference operations on endpoints. | ||
| data_source: | ||
| - Windows Event Log Security 4688 | ||
| search: | | ||
| `wineventlog_security` EventID=4688 | spath | ||
rosplk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| | rename "Event.System.Computer" as host, "Event.System.EventID" as EventID | ||
| | eval NewProcessName=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "NewProcessName")) | ||
| | eval ParentProcessName=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "ParentProcessName")) | ||
| | eval CommandLine=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "CommandLine")) | ||
| | eval SubjectUserName=mvindex('Event.EventData.Data', mvfind('Event.EventData.Data{@Name}', "SubjectUserName")) | ||
| | search ( | ||
| NewProcessName="*ollama*" OR | ||
| NewProcessName="*llama*" OR | ||
| NewProcessName="*llama-run*" OR | ||
| NewProcessName="*gpt4all*" OR | ||
| NewProcessName="*lmstudio*" OR | ||
| NewProcessName="*nutstudio*" OR | ||
| NewProcessName="*koboldcpp*" OR | ||
| NewProcessName="*jan*" OR | ||
| NewProcessName="*jan.exe*" OR | ||
| CommandLine="*transformers*" OR | ||
| CommandLine="*langchain*" OR | ||
| CommandLine="*huggingface*" OR | ||
| CommandLine="*llama-run*" OR | ||
| CommandLine="*nutstudio*" OR | ||
| ParentProcessName="*ollama*" OR | ||
| ParentProcessName="*lmstudio*" OR | ||
| ParentProcessName="*nutstudio*" OR | ||
| ParentProcessName="*gpt4all*" OR | ||
| ParentProcessName="*jan*" OR | ||
| ParentProcessName="*llama-run*" | ||
| ) | ||
| | eval Framework=case( | ||
| like(NewProcessName, "%ollama%") OR like(ParentProcessName, "%ollama%"), "Ollama", | ||
| like(NewProcessName, "%lmstudio%") OR like(NewProcessName, "%LM Studio%") OR like(ParentProcessName, "%lmstudio%"), "LM Studio", | ||
| like(NewProcessName, "%nutstudio%") OR like(ParentProcessName, "%nutstudio%") OR like(CommandLine, "%nutstudio%"), "NutStudio", | ||
| like(NewProcessName, "%gpt4all%") OR like(ParentProcessName, "%gpt4all%"), "GPT4All", | ||
| like(NewProcessName, "%jan%") OR like(ParentProcessName, "%jan%") OR like(NewProcessName, "%jan.exe%"), "Jan", | ||
| like(NewProcessName, "%koboldcpp%") OR like(CommandLine, "%koboldcpp%"), "KoboldCPP", | ||
| like(NewProcessName, "%llama-run%") OR like(ParentProcessName, "%llama-run%") OR like(CommandLine, "%llama-run%"), "Llama-Run", | ||
| like(CommandLine, "%transformers%") OR like(CommandLine, "%huggingface%"), "HuggingFace/Transformers", | ||
| like(CommandLine, "%langchain%"), "LangChain", | ||
| like(NewProcessName, "%llama%") OR like(NewProcessName, "%llama.cpp%") OR like(ParentProcessName, "%llama%"), "Llama.cpp", | ||
| 1=1, "Related Activity" | ||
| ) | ||
| | stats count by host, Framework, EventID, ParentProcessName | ||
| | sort host, Framework, -count | `suspicious_local_llm_framework_filter` | ||
| how_to_implement: This search can be implemented by configuring Splunk to ingest Windows Security Event logs, specifically monitoring Event ID 4688 (process creation). Ensure that process creation events include detailed command-line arguments. Deploy the search as a scheduled saved search or real-time alert within Splunk Enterprise Security or Splunk Cloud to continuously detect suspicious local LLM framework activity. Tune the search by updating the process name and command-line keywords as new frameworks emerge. Integrate with asset and identity data to enrich context and reduce false positives. | ||
| known_false_positives: Legitimate development and data science workflows where developers, ML engineers, and researchers install and run local LLM frameworks for experimentation, fine-tuning, or prototyping. Approved AI/ML sandboxes and lab environments, open-source and educational use cases, third-party software bundling HuggingFace/Transformers/LangChain libraries as dependencies, and system administrators deploying frameworks as part of containerized services. Parent process and command-line keyword overlap with unrelated tools (e.g., "llama-backup", tools using "--transformers" flags for non-LLM purposes). Recommended tuning — baseline approved frameworks and users, exclude sanctioned development/lab systems, require additional context (user role, peer group, model artifacts, network exfiltration signals) before escalating to incidents. | ||
| 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' | ||
rosplk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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 | ||
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 | ||
rosplk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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:Microsoft-Windows-Sysmon/Operational | ||
rosplk marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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.