diff --git a/README.md b/README.md index 85f9fcdd..fcc32efd 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,92 @@ The SAFE-MCP framework defines 14 tactics that align with the MITRE ATT&CK metho ## TTP Overview +| Tactic ID | Tactic Name | Technique ID | Technique Name | Description | +|-----------|-------------|--------------|----------------|-------------| +| **ATK-TA0043** | **Reconnaissance** | | | *No MCP-specific techniques currently documented* | +| **ATK-TA0042** | **Resource Development** | [SAFE-T2107](techniques/SAFE-T2107/README.md) | AI Model Poisoning via MCP Tool Training Data Contamination | Attackers contaminate training data used to develop AI models for MCP tools, implanting backdoors that activate during specific conditions | +| **ATK-TA0001** | **Initial Access** | [SAFE-T1001](techniques/SAFE-T1001/README.md) | Tool Poisoning Attack (TPA) | Attackers embed malicious instructions within MCP tool descriptions that are invisible to users but processed by LLMs | +| ATK-TA0001 | Initial Access | [SAFE-T1002](techniques/SAFE-T1002/README.md) | Supply Chain Compromise | Distribution of backdoored MCP server packages through unofficial repositories or compromised legitimate sources | +| ATK-TA0001 | Initial Access | [SAFE-T1003](techniques/SAFE-T1003/README.md) | Malicious MCP-Server Distribution | Adversary ships a trojanized server package or Docker image that users install, gaining foothold when the host registers its tools | +| ATK-TA0001 | Initial Access | SAFE-T1004 | Server Impersonation / Name-Collision | Attacker registers a server with the same name/URL as a trusted one, or hijacks discovery, so the client connects to them instead | +| ATK-TA0001 | Initial Access | [SAFE-T1008](techniques/SAFE-T1008/README.md) | Tool Shadowing Attack | Malicious MCP servers impersonate or interfere with legitimate tools to hijack execution within MCP-based workflows through cross-server tool interference | +| ATK-TA0001 | Initial Access | SAFE-T1005 | Exposed Endpoint Exploit | Misconfigured public MCP endpoints (no auth, debug on) let attackers connect, enumerate tools or trigger RCE | +| ATK-TA0001 | Initial Access | SAFE-T1006 | User-Social-Engineering Install | Phishing/social posts persuade developers to "try this cool tool"; the installer silently registers dangerous capabilities | +| ATK-TA0001 | Initial Access | [SAFE-T1007](techniques/SAFE-T1007/README.md) | OAuth Authorization Phishing | Malicious MCP servers exploit OAuth flows to steal access tokens from legitimate services by tricking users during authorization | +| ATK-TA0001 | Initial Access | SAFE-T1009 | Authorization Server Mix-up | Client follows redirect to look-alike AS domain (e.g., accounts-google.com vs accounts.google.com), causing authorization codes or tokens to be leaked to attacker-controlled server | +| **ATK-TA0002** | **Execution** | SAFE-T1101 | Command Injection | Exploitation of unsanitized input in MCP server implementations leading to remote code execution | +| ATK-TA0002 | Execution | [SAFE-T1102](techniques/SAFE-T1102/README.md) | Prompt Injection (Multiple Vectors) | Malicious instructions injected through various vectors to manipulate AI behavior via MCP | +| ATK-TA0002 | Execution | [SAFE-T1103](techniques/SAFE-T1103/README.md) | Fake Tool Invocation (Function Spoofing) | Adversary forges JSON that mimics an MCP function-call message, tricking the host into running a tool that was never offered | +| ATK-TA0002 | Execution | [SAFE-T1104](techniques/SAFE-T1104/README.md) | Over-Privileged Tool Abuse | Legit tool (e.g. "Shell") runs with broader OS rights than necessary; LLM can be induced to perform arbitrary commands | +| ATK-TA0002 | Execution | [SAFE-T1105](techniques/SAFE-T1105/README.md) | Path Traversal via File Tool | File-handling tool accepts relative paths like ../../secret.key; attacker leaks host secrets | +| ATK-TA0002 | Execution | [SAFE-T1106](techniques/SAFE-T1106/README.md) | Autonomous Loop Exploit | Craft prompts that push an agent into infinite "self-invoke" loop to exhaust CPU or hit rate limits (DoS) | +| ATK-TA0002 | Execution | [SAFE-T1109](techniques/SAFE-T1109/README.md) | Debugging Tool Exploitation | Browser-based remote code execution via vulnerable MCP Inspector (CVE-2025-49596) | +| ATK-TA0002 | Execution | [SAFE-T1110](techniques/SAFE-T1110/README.md) | Multimodal Prompt Injection via Images/Audio | Embedding malicious instructions within image or audio content to manipulate multimodal AI behavior | +| ATK-TA0002 | Execution | [SAFE-T1111](techniques/SAFE-T1111/README.md) | AI Agent CLI Weaponization | Malicious exploitation of AI coding assistant CLI tools with dangerous flags for reconnaissance and data exfiltration | +| **ATK-TA0003** | **Persistence** | [SAFE-T1201](techniques/SAFE-T1201/README.md) | MCP Rug Pull Attack | Time-delayed malicious tool definition changes after initial approval | +| ATK-TA0003 | Persistence | SAFE-T1202 | OAuth Token Persistence | Theft and reuse of OAuth access/refresh tokens for persistent access to MCP-connected services, including replay of refresh tokens after legitimate client sessions end | +| ATK-TA0003 | Persistence | SAFE-T1203 | Backdoored Server Binary | Inserts cron job or reverse shell on install; persists even if MCP service is uninstalled | +| ATK-TA0003 | Persistence | SAFE-T1204 | Context Memory Implant | Malicious agent writes itself into long-term vector store; re-loaded in every future session | +| ATK-TA0003 | Persistence | SAFE-T1205 | Persistent Tool Redefinition | Attacker modifies server's tool metadata to keep hidden commands across restarts | +| ATK-TA0003 | Persistence | [SAFE-T1206] (techniques/SAFE-T1206/README.md) | Credential Implant in Config | Adds attacker's API/SSH keys to server .env, giving re-entry | +| ATK-TA0003 | Persistence | SAFE-T1207 | Hijack Update Mechanism | Man-in-the-middle an auto-update channel to re-install malicious build later on | +| ATK-TA0003 | Persistence | [SAFE-T2106](techniques/SAFE-T2106/README.md) | Context Memory Poisoning via Vector Store Contamination | Attackers manipulate vector databases storing long-term memory for AI agents, creating persistent malicious content that contaminates knowledge across all future sessions | +| **ATK-TA0004** | **Privilege Escalation** | [SAFE-T1301](techniques/SAFE-T1301/README.md) | Cross-Server Tool Shadowing | Malicious MCP servers override legitimate tool calls to gain elevated privileges | +| ATK-TA0004 | Privilege Escalation | SAFE-T1302 | High-Privilege Tool Abuse | Invoke a VM-level or root tool from normal user context | +| ATK-TA0004 | Privilege Escalation | SAFE-T1303 | Sandbox Escape via Server Exec | Exploit vulnerable server to break container/seccomp isolation | +| ATK-TA0004 | Privilege Escalation | [SAFE-T1304](techniques/SAFE-T1304/README.md) | Credential Relay Chain | Use one tool to steal tokens, feed them to second tool with higher privileges | +| ATK-TA0004 | Privilege Escalation | SAFE-T1305 | Host OS Priv-Esc (RCE) | Achieve root via misconfigured service running as root, then alter host | +| ATK-TA0004 | Privilege Escalation | SAFE-T1306 | Rogue Authorization Server | Malicious MCP server redirects OAuth flows to attacker-controlled AS that ignores audience restrictions and Proof of Possession (PoP), minting overly-permissive "super-tokens" with expanded scopes | +| ATK-TA0004 | Privilege Escalation | SAFE-T1307 | Confused Deputy Attack | MCP server receives token for one user (Alice) and forwards it to another user's (Bob) MCP instance, allowing Bob to perform actions as Alice by exploiting the server's trusted position | +| ATK-TA0004 | Privilege Escalation | SAFE-T1308 | Token Scope Substitution | Attacker swaps a limited-scope token with one that has broader permissions but same audience, exploiting insufficient scope validation to gain elevated privileges | +| **ATK-TA0005** | **Defense Evasion** | SAFE-T1401 | Line Jumping | Bypassing security checkpoints through context injection before tool invocation | +| ATK-TA0005 | Defense Evasion | [SAFE-T1402](techniques/SAFE-T1402/README.md) | Instruction Steganography | Zero-width chars/HTML comments hide directives in tool metadata | +| ATK-TA0005 | Defense Evasion | SAFE-T1403 | Consent-Fatigue Exploit | Repeated benign prompts desensitize user; crucial request hidden mid-flow | +| ATK-TA0005 | Defense Evasion | SAFE-T1404 | Response Tampering | Model instructed not to mention risky action, keeping UI output "harmless" | +| ATK-TA0005 | Defense Evasion | SAFE-T1405 | Tool Obfuscation/Renaming | Malicious tool named "Utils-Helper" to blend in among 30 legit tools | +| ATK-TA0005 | Defense Evasion | SAFE-T1406 | Metadata Manipulation | Strip safety flags or lower risk scores in tool manifest before host logs it | +| ATK-TA0005 | Defense Evasion | SAFE-T1407 | Server Proxy Masquerade | Malicious server silently proxies legit API so traffic looks normal in network logs | +| ATK-TA0005 | Defense Evasion | SAFE-T1408 | OAuth Protocol Downgrade | Attacker forces use of less secure OAuth 2.0 implicit flow instead of authorization code flow, bypassing PKCE protections and enabling easier token theft | +| **ATK-TA0006** | **Credential Access** | [SAFE-T1501](techniques/SAFE-T1501/README.md) | Full-Schema Poisoning (FSP) | Exploitation of entire MCP tool schema beyond descriptions for credential theft | +| ATK-TA0006 | Credential Access | SAFE-T1502 | File-Based Credential Harvest | Use file tools to read SSH keys, cloud creds | +| ATK-TA0006 | Credential Access | SAFE-T1503 | Env-Var Scraping | Ask read_file for .env; exfil API secrets | +| ATK-TA0006 | Credential Access | SAFE-T1504 | Token Theft via API Response | Prompt LLM to call "session.token" tool, then leak result | +| ATK-TA0006 | Credential Access | SAFE-T1505 | In-Memory Secret Extraction | Query vector store for "api_key" embedding strings | +| ATK-TA0006 | Credential Access | SAFE-T1506 | Infrastructure Token Theft | Steal OAuth/session tokens from logs, TLS termination proxies, or other infrastructure components where tokens may be inadvertently stored or exposed, then replay at intended service | +| ATK-TA0006 | Credential Access | SAFE-T1507 | Authorization Code Interception | Man-in-the-browser attack steals OAuth authorization codes during the redirect flow and attempts to exchange them at the token endpoint before the legitimate client | +| **ATK-TA0007** | **Discovery** | SAFE-T1601 | MCP Server Enumeration | Unauthorized discovery and mapping of available MCP servers and tools | +| ATK-TA0007 | Discovery | SAFE-T1602 | Tool Enumeration | Call tools/list to see available functions | +| ATK-TA0007 | Discovery | SAFE-T1603 | System-Prompt Disclosure | Coax model into printing its system prompt/tool JSON | +| ATK-TA0007 | Discovery | SAFE-T1604 | Server Version Enumeration | GET /version or header analysis for vulnerable builds | +| ATK-TA0007 | Discovery | SAFE-T1605 | Capability Mapping | Ask "what can you do?"; model outlines high-value tools | +| ATK-TA0007 | Discovery | SAFE-T1606 | Directory Listing via File Tool | List root dir to find sensitive paths | +| **ATK-TA0008** | **Lateral Movement** | SAFE-T1701 | Cross-Tool Contamination | Using compromised MCP tools to access other connected services and systems | +| ATK-TA0008 | Lateral Movement | SAFE-T1702 | Shared-Memory Poisoning | Write false tasks to shared vector DB so peer agents execute them | +| ATK-TA0008 | Lateral Movement | SAFE-T1703 | Tool-Chaining Pivot | Compromise low-priv tool, then leverage it to call another privileged tool indirectly | +| ATK-TA0008 | Lateral Movement | SAFE-T1704 | Compromised-Server Pivot | Use hijacked server as beachhead to infect other hosts in same IDE/workspace | +| ATK-TA0008 | Lateral Movement | SAFE-T1705 | Cross-Agent Instruction Injection | Inject directives in multi-agent message bus to seize control of cooperating agents | +| ATK-TA0008 | Lateral Movement | SAFE-T1706 | OAuth Token Pivot Replay | Attacker reuses OAuth tokens across different services by exploiting either shared Authorization Server trust (e.g., GitHub token used at Slack) or Resource Servers that fail to validate audience claims, enabling unauthorized cross-service access | +| ATK-TA0008 | Lateral Movement | SAFE-T1707 | CSRF Token Relay | Leaked OAuth token is passed via Cross-Site Request Forgery to access different resources on the same Resource Server (e.g., pivoting between GCP projects under same Google AS) | +| **ATK-TA0009** | **Collection** | [SAFE-T1801](/techniques/SAFE-T1801/README.md) | Automated Data Harvesting | Systematic data collection through manipulated MCP tool calls | +| ATK-TA0009 | Collection | SAFE-T1802 | File Collection | Batch-read sensitive files for later exfil | +| ATK-TA0009 | Collection | SAFE-T1803 | Database Dump | Use SQL tool to SELECT * from prod DB | +| ATK-TA0009 | Collection | SAFE-T1804 | API Data Harvest | Loop over customer REST endpoints via HTTP tool | +| ATK-TA0009 | Collection | SAFE-T1805 | Context Snapshot Capture | Query vector store embeddings wholesale | +| **ATK-TA0011** | **Command and Control** | SAFE-T1901 | Outbound Webhook C2 | LLM calls "http.post" to attacker URL with commands/results | +| ATK-TA0011 | Command and Control | SAFE-T1902 | Covert Channel in Responses | Encode data in whitespace or markdown links returned to chat | +| ATK-TA0011 | Command and Control | SAFE-T1903 | Malicious Server Control Channel | Attacker operates rogue server; every tool call doubles as heartbeat | +| ATK-TA0011 | Command and Control | SAFE-T1904 | Chat-Based Backchannel | LLM embeds base64 blobs in normal answers that another bot decodes | +| **ATK-TA0010** | **Exfiltration** | SAFE-T1910 | Covert Channel Exfiltration | Data smuggling through tool parameters, error messages, or legitimate-appearing operations | +| ATK-TA0010 | Exfiltration | SAFE-T1911 | Parameter Exfiltration | Sneak secrets into unused JSON arg (note) | +| ATK-TA0010 | Exfiltration | SAFE-T1912 | Stego Response Exfil | Hide data in code blocks shown to user then copied elsewhere | +| ATK-TA0010 | Exfiltration | SAFE-T1913 | HTTP POST Exfil | Use outbound web tool to POST to attacker server | +| ATK-TA0010 | Exfiltration | SAFE-T1914 | Tool-to-Tool Exfil | Chain two tools so second one emails data out | +| ATK-TA0010 | Exfiltration | [SAFE-T1915](techniques/SAFE-T1915/README.md) | Cross-Chain Laundering via Bridges/DEXs | Multi-chain asset transfers using bridges and DEXs to obscure provenance and evade detection | +| **ATK-TA0040** | **Impact** | SAFE-T2101 | Data Destruction | delete_file or drop_table commands wipe assets | +| ATK-TA0040 | Impact | SAFE-T2102 | Service Disruption | Flood external API causing rate-limit or DoS | +| ATK-TA0040 | Impact | SAFE-T2103 | Code Sabotage | Agent commits malicious PR into repo | +| ATK-TA0040 | Impact | SAFE-T2104 | Fraudulent Transactions | Payment-tool instructed to move funds | +| ATK-TA0040 | Impact | SAFE-T2105 | Disinformation Output | Manipulate LLM to generate false or harmful content to downstream consumers | | Tactic ID | Tactic Name | Technique ID | Technique Name | Description | | -------------- | ------------------------ | ---------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **ATK-TA0043** | **Reconnaissance** | | | _No MCP-specific techniques currently documented_ | diff --git a/techniques/SAFE-T1206/README.md b/techniques/SAFE-T1206/README.md new file mode 100644 index 00000000..12e1a71f --- /dev/null +++ b/techniques/SAFE-T1206/README.md @@ -0,0 +1,108 @@ +# SAFE-T1206: Credential Implant in Config + +## Tactic + +Defense Evasion / Credential Access (ATK-TA0005 / ATK-TA0006) + +## Description + +Credential Implant in Config is a technique where an attacker inserts, replaces, or modifies authentication secrets inside configuration files, provider manifests, or runtime deployment artifacts. This allows unauthorized access to Model Context Protocol (MCP) providers or systems that rely on those configurations. It matters because MCP implementations often depend on trusted configuration files to validate provider endpoints, keys, and permissions. + +## How It Works + +1. **Access acquisition** – Attacker gains access to a system, CI pipeline, or workstation capable of modifying MCP config files. +2. **Malicious modification** – Sensitive keys, tokens, provider endpoints, or permissions are implanted into configuration or manifest files. +3. **Bypass of validation** – Attacker attempts to evade signature verification, code reviews, or CI policies. +4. **Execution** – Modified config is deployed or loaded by MCP runtime, granting the attacker unauthorized access or elevated capabilities. + +### Technical Details + +* Direct config edits to `mcp_config.json` or `providers.yml`. +* CI commits swapping legitimate endpoints with attacker-controlled hosts. +* Runtime secret injection without approval tickets. +* Manifest permission escalation enabling read-write or exfiltration capabilities. + +### Prerequisites + +* Access to configuration repository, build system, or runtime automation. +* Ability to modify files or bypass CI controls. +* In some cases, weak or missing signature validation. + +### Expected Outcome + +* Attacker gains access to privileged MCP providers. +* Unauthorized endpoints or credentials are trusted by the system. +* Potential data leakage or impersonation of legitimate MCP providers. + +## Examples + +"An attacker modifies `mcp_config.json` to implant a plaintext API key and swap a trusted provider endpoint with `https://proxy-evil.example.com`. During the next deployment, the MCP service loads the config without detecting the tampering, granting the attacker operational access to internal data sources." + +## Impact + +* **Confidentiality:** High – Stolen or implanted secrets can expose sensitive provider data. +* **Integrity:** High – Malicious configuration changes can compromise decision-making and service trust. +* **Availability:** Medium – Misconfigurations may break provider communication or cause denial of service. + +### Potential Consequences + +* Credential theft and impersonation +* Unauthorized access to internal knowledge sources +* Data exfiltration via manipulated endpoints +* Pipeline compromise and persistent backdoors + +## Detection + +Defenders can identify this attack by monitoring: + +* Unauthorized `file_write` events on `mcp_config.json` or `/etc/mcp/config.yml`. +* CI commits that bypass code review, signature validation, or branch protections. +* Runtime updates provisioning secrets without associated approval tickets. +* Manifest changes indicating permission escalation. +* Failed hash or signature checks during `config_load`. + +### Behavioral Indicators + +* Unverified commit authors modifying sensitive fields. +* Endpoint changes introducing non-whitelisted or suspicious domains. +* Secret-related fields added or modified unexpectedly. + +### Monitoring Strategies + +* Enable integrity-based monitoring on critical config files. +* Enforce commit signing and CI policy checks. +* Centralize logs for MCP runtime, Git events, and secret management. + +## Mitigation + +1. **Configuration Hardening** + + * Enforce signature validation for all MCP config loads. + * Use immutability controls for production configuration artifacts. + +2. **Access Controls** + + * Restrict write access to configuration repositories. + * Require strong authentication and role separation for CI pipelines. + +3. **Input Validation** + + * Validate provider endpoints against an allowlist. + * Reject configs containing unapproved secret fields. + +4. **Monitoring Requirements** + + * Implement anomaly detection for secret provisioning events. + * Audit all manifest updates and permission changes. + +## References + +* MITRE ATT&CK Technique: Credential Access (T1552 – Unsecured Credentials) +* Supply Chain Security Guidelines +* Configuration Security Best Practices +* MCP Provider and Runtime Documentation + +## MITRE ATT&CK Mapping + +**ATT&CK Technique:** T1552 – Unsecured Credentials +**ATT&CK Tactic:** Credential Access / Defense Evasion diff --git a/techniques/SAFE-T1206/detection-rule.yml b/techniques/SAFE-T1206/detection-rule.yml new file mode 100644 index 00000000..40ab74d0 --- /dev/null +++ b/techniques/SAFE-T1206/detection-rule.yml @@ -0,0 +1,169 @@ +title: Credential Implant in Config Detection +id: b4f2c3d1-9f6a-4e8b-9c2d-0a1b2c3d4e5f +status: experimental +description: | +Detects suspicious modifications, insertions, or provisioning of credentials +within +MCP configuration artifacts, provider manifests, and environment configuration +that +could indicate a credential-implant supply-chain attack. Focus areas include +unauthorized provider registrations, new or modified API keys in config, +endpoint +substitutions to non-whitelisted hosts, CI/CD commits that alter configuration +without proper review, and failures of configuration integrity checks +(signatures, +hashes). +Author: Victor Oluwatimileyin AJAO +date: 2025-11-20 +modified: 2025-11-20 +references: +- https://attack.mitre.org/techniques/T1195/ +- https://github.com/safe-mcp/techniques/SAFE-T1202 +- https://www.cisa.gov/news-events/alerts/2020/12/17 +- https://www.hashicorp.com/blog/securing-secrets-in-devops +management +- https://www.owasp.org/index.php/Top_10-2017_A3_2017-Sensitive_Data_Exposure +logsource: +product: config_management +service: mcp +category: configuration +# Detection selections focusing on events that indicate config credential +1 +implantation +detection: +# Direct modification of MCP configuration files in production or protected +paths +selection_config_write: +event_type: 'file_write' +file_path: +- '/etc/mcp/config.yml' +- '/opt/mcp/providers/*.yaml' +- 'mcp_config.json' +actor_type: 'user' +actor_trust_level: 'unapproved' +change_type: +- 'added' +- 'modified' +# New provider or tool registration in MCP manifests +selection_new_provider: +event_type: 'manifest_update' +update_type: 'provider_registration' +provider_status: 'new' +provider_origin: 'external' +provider_signed: false +# Inserted or modified credentials in configuration or environment +selection_credential_insertion: +event_type: +- 'env_update' +- 'config_change' +sensitive_key_patterns: +- 'api_key' +- 'secret' +- 'private_key' +- 'token' +value_source: 'plaintext' +actor_trust_level: 'unapproved' +# Config signature/hash verification failures at load time +selection_signature_failure: +event_type: 'config_load' +signature_validation: 'failed' +previous_signature: '!=current_signature' +# Provider endpoint changed to an unapproved/unwhitelisted domain +selection_endpoint_swap: +event_type: 'config_change' +field_changed: 'provider.endpoint' +2 +new_host_whitelisted: false +# Escalation of provider permissions in configuration (e.g., read -> write, +filesystem access added) +selection_permission_escalation: +event_type: 'config_change' +field_changed: 'provider.permissions' +permission_change: 'escalation' +# CI/CD: direct commit to protected branch or bypass of review/gating +selection_ci_bypass: +event_type: 'git_commit' +branch: 'main' +commit_author_verified: false +pr_review_count: 0 +pipeline_policy_passed: false +# Environment variable provisioning in runtime (e.g., container or k8s secret +mount) outside review window +selection_runtime_secret_mount: +event_type: 'runtime_update' +runtime_target: +- 'kubernetes' +- 'container' +secret_provisioned: true +provisioned_by: 'automation' +approval_ticket: null +condition: any of ( +selection_config_write, +selection_new_provider, +selection_credential_insertion, +selection_signature_failure, +selection_endpoint_swap, +selection_permission_escalation, +selection_ci_bypass, +selection_runtime_secret_mount +) +falsepositives: +- Legitimate emergency configuration changes by on-call operators +- Automated onboarding scripts that register approved providers +- Platform upgrades that rotate keys via approved CI/CD pipelines +- Secrets temporarily staged in ephemeral environments for deployment testing +- Configuration drift remediation performed by authorized configuration +management tools +level: high +3 +tags: +- attack.supply_chain +- attack.persistence +- attack.credential_access +- safe.t1202 +- mcp +- configuration_tamper +fields: +- event_type +- actor +- actor_type +- actor_trust_level +- file_path +- file_hash +- provider_name +- provider_endpoint +- change_type +- sensitive_key_patterns +- signature_validation +- branch +- commit_id +- approval_ticket +- timestamp +additional_rules: +# Detect sudden/configuration reloads with mismatching hashing +config_reload_with_mismatch: +event_type: 'config_reload' +loaded_from: 'production' +file_hash_match: false +# Detect provisioning of plaintext secrets into code repositories +plaintext_secret_in_repo: +event_type: 'git_commit' +file_diff_contains: +- 'api_key' +- 'secret' +- 'PRIVATE_KEY' +commit_author_verified: false +# Detect attempts to disable signature checks in config validation runtimes +disable_signature_check: +event_type: 'config_change' +field_changed: 'config_validation.signature_check' +new_value: false +4 +tests: +guidance: | +- Ensure configuration auditing is enabled and logs are ingested into your +detection platform. +- Correlate file-system events, Git/CI events, and runtime provisioning logs to +reduce false positives. +- Tune file paths and runtime targets to fit your MCP deployment +architecture. \ No newline at end of file diff --git a/techniques/SAFE-T1206/test-logs.json b/techniques/SAFE-T1206/test-logs.json new file mode 100644 index 00000000..2e3cd3ca --- /dev/null +++ b/techniques/SAFE-T1206/test-logs.json @@ -0,0 +1,142 @@ +{ + "test_scenarios": [ + { + "scenario_id": "unauthorized_config_write", + "description": "Unapproved user writes credentials directly into mcp_config.json in production", + "attack_type": "credential_implant", + "logs": [ + { + "timestamp": "2025-11-20T08:15:00Z", + "event_type": "file_write", + "file_path": "mcp_config.json", + "actor": "dev_laptop_01", + "actor_type": "user", + "actor_trust_level": "unapproved", + "change_type": "modified", + "diff": "+ \"providers\": [{\n+ \"name\": \"internalknowledge\",\n+ \"endpoint\": \"https://internal-db.corp\",\n+ \"api_key\": \"AKIA...EXFIL\"\n+ }]", + "file_hash": "sha256:abcdef123456", + "response_code": 200 + } + ], + "expected_detection": true, + "detection_reason": "Plaintext API key added by unapproved actor to production config" + }, + { + "scenario_id": "provider_endpoint_swap", + "description": "Provider endpoint swapped to attacker-controlled domain via CI commit that bypassed review", + "attack_type": "endpoint_swap", + "logs": [ + { + "timestamp": "2025-11-20T09:00:00Z", + "event_type": "git_commit", + "branch": "main", + "commit_id": "c0ffee123", + "commit_author": "automation_bot", + "commit_author_verified": false, + "pr_review_count": 0, + "pipeline_policy_passed": false, + "file_diff_contains": "- provider.endpoint: https://internalapi.corp\n+ provider.endpoint: https://proxy-evil.example.com" + }, + { + "timestamp": "2025-11-20T09:05:00Z", + "event_type": "config_reload", + "loaded_from": "production", + "file_hash_match": false, + "signature_validation": "failed" + } + ], + "expected_detection": true, + "detection_reason": "Endpoint changed to non-whitelisted host with signature failure and CI bypass" + }, + { + "scenario_id": "runtime_plaintext_secret_mount", + "description": "A runtime automation mounts plaintext secret into a container without approval", + "attack_type": "runtime_secret_provision", + "logs": [ + { + "timestamp": "2025-11-20T10:30:00Z", + "event_type": "runtime_update", + "runtime_target": "kubernetes", + "cluster": "prod-cluster-1", + "secret_provisioned": true, + "secret_name": "mcp-provider-api-key", + "provisioned_by": "automation", + "approval_ticket": null + } + ], + "expected_detection": true, + "detection_reason": "Plaintext secret provisioned into production runtime without approval" + }, + { + "scenario_id": "permission_escalation_in_manifest", + "description": "Provider permissions escalated from read-only to readwrite in providers.yaml", + "attack_type": "permission_escalation", + "logs": [ + { + "timestamp": "2025-11-20T11:20:00Z", + "event_type": "manifest_update", + "update_type": "provider_registration", + "provider_name": "fs-accessor", + "provider_origin": "internal", + "provider_status": "modified", + "field_changed": "provider.permissions", + "permission_change": "escalation", + "actor": "ci_pipeline", + "actor_type": "automation", + "actor_trust_level": "approved", + "approval_ticket": "TKT-1234" + } + ], + "expected_detection": true, + "detection_reason": "Provider permissions escalated which could enable exfiltration" + }, + { + "scenario_id": "plaintext_secret_in_repo_benign", + "description": "Staged secrets in ephemeral test repo by authorized automation (benign)", + "attack_type": "dev_onboarding", + "logs": [ + { + "timestamp": "2025-11-20T12:00:00Z", + "event_type": "git_commit", + "branch": "feature/onboard", + "commit_id": "deadbeef", + "commit_author": "onboard_bot", + "commit_author_verified": true, + "pr_review_count": 2, + "pipeline_policy_passed": true, + "file_diff_contains": "+ \"api_key\": \"staging-PLACEHOLDER\"" + } + ], + "expected_detection": false, + "detection_reason": "Authorized staging change with reviews and pipeline gating" + }, + { + "scenario_id": "signed_config_reload_ok_benign", + "description": "Config reload in production with valid signature after approved deployment", + "attack_type": "deployment", + "logs": [ + { + "timestamp": "2025-11-20T13:00:00Z", + "event_type": "config_load", + "loaded_from": "production", + "file_hash": "sha256:1234abcd", + "signature_validation": "passed", + "deployed_by": "release_manager", + "approval_ticket": "REL-2025-11" + } + ], + "expected_detection": false, + "detection_reason": "Valid signature and approved deployment" + } + ], + "metadata": { + "version": "1.0", + "created_date": "2025-11-20", + "author": "Smaran Dhungana ", + "description": "Test data for Credential Implant in Config detection rule (MCP)", + "total_scenarios": 6, + "malicious_scenarios": 4, + "benign_scenarios": 2 + } + } + \ No newline at end of file diff --git a/techniques/SAFE-T1206/test_detection_rule.py b/techniques/SAFE-T1206/test_detection_rule.py new file mode 100644 index 00000000..f486bf82 --- /dev/null +++ b/techniques/SAFE-T1206/test_detection_rule.py @@ -0,0 +1,159 @@ +""" +Test Suite for Credential Implant in Config Detection Rule (MCP) +This test suite validates the detection rule against representative scenarios +where credentials are implanted into MCP configuration artifacts, provider +manifests, or runtime environments. + +Author: Victor Oluwatimileyin AJAO +Date: 2025-11-20 +""" + +import json +import unittest +from datetime import datetime +from pathlib import Path + + +class TestCredentialImplantDetection(unittest.TestCase): + """Test cases for Credential Implant in Config detection""" + + def setUp(self): + test_data_path = Path(__file__).parent / "test-logs.json" + with open(test_data_path, 'r') as f: + self.test_data = json.load(f) + self.scenarios = self.test_data["test_scenarios"] + + def evaluate_detection_rule(self, logs): + """ + Simplified rule evaluation logic based on detection-rule.yml selections. + Returns True if any suspicious condition is met. + """ + for log in logs: + evt = log.get("event_type") + + # Unauthorized config writes with sensitive keys + if evt == 'file_write': + if log.get('file_path') in ['mcp_config.json', '/etc/mcp/config.yml']: + if log.get('actor_trust_level') == 'unapproved': + diff = log.get('diff', '') + if any(k in diff.lower() for k in ['api_key', 'secret', 'private_key', 'token']): + return True + + # CI bypass / endpoint swap / signature failure + if evt == 'git_commit': + if log.get('branch') == 'main' and not log.get('commit_author_verified'): + if log.get('pr_review_count', 0) == 0 or not log.get('pipeline_policy_passed'): + diff = log.get('file_diff_contains', '') + if 'provider.endpoint' in diff or 'proxy-' in diff: + return True + + fd = log.get('file_diff_contains', '') + if any(k in fd.lower() for k in ['api_key', 'secret', 'private_key']): + if not log.get('commit_author_verified'): + return True + + # Config load signature failure + if evt == 'config_load': + if log.get('signature_validation') == 'failed' or not log.get('file_hash'): + return True + + # Runtime secret mount without approval + if evt == 'runtime_update': + if log.get('secret_provisioned') and not log.get('approval_ticket'): + return True + + # Manifest or provider permission escalation + if evt == 'manifest_update': + if log.get('permission_change') == 'escalation': + return True + + return False + + def test_unauthorized_config_write(self): + scenario = next(s for s in self.scenarios if s['scenario_id'] == 'unauthorized_config_write') + result = self.evaluate_detection_rule(scenario['logs']) + self.assertTrue(result) + self.assertTrue(scenario['expected_detection']) + + def test_provider_endpoint_swap(self): + scenario = next(s for s in self.scenarios if s['scenario_id'] == 'provider_endpoint_swap') + result = self.evaluate_detection_rule(scenario['logs']) + self.assertTrue(result) + self.assertTrue(scenario['expected_detection']) + + def test_runtime_plaintext_secret_mount(self): + scenario = next(s for s in self.scenarios if s['scenario_id'] == 'runtime_plaintext_secret_mount') + result = self.evaluate_detection_rule(scenario['logs']) + self.assertTrue(result) + self.assertTrue(scenario['expected_detection']) + + def test_permission_escalation_manifest(self): + scenario = next(s for s in self.scenarios if s['scenario_id'] == 'permission_escalation_in_manifest') + result = self.evaluate_detection_rule(scenario['logs']) + self.assertTrue(result) + self.assertTrue(scenario['expected_detection']) + + def test_plaintext_secret_in_repo_benign(self): + scenario = next(s for s in self.scenarios if s['scenario_id'] == 'plaintext_secret_in_repo_benign') + result = self.evaluate_detection_rule(scenario['logs']) + self.assertFalse(result) + self.assertFalse(scenario['expected_detection']) + + def test_signed_config_reload_ok_benign(self): + scenario = next(s for s in self.scenarios if s['scenario_id'] == 'signed_config_reload_ok_benign') + result = self.evaluate_detection_rule(scenario['logs']) + self.assertFalse(result) + self.assertFalse(scenario['expected_detection']) + + def test_coverage_detection(self): + detected = 0 + total_malicious = sum(1 for s in self.scenarios if s['expected_detection']) + + for s in self.scenarios: + if s['expected_detection']: + if self.evaluate_detection_rule(s['logs']): + detected += 1 + else: + self.fail(f"Malicious scenario not detected: {s['scenario_id']}") + + self.assertEqual(detected, total_malicious) + + def test_log_format_consistency(self): + required_fields = ["timestamp", "event_type"] + + for scenario in self.scenarios: + for log in scenario['logs']: + for f in required_fields: + self.assertIn(f, log, f"Missing required field {f} in scenario {scenario['scenario_id']}") + + try: + datetime.fromisoformat(log['timestamp'].replace('Z', '+00:00')) + except Exception: + self.fail(f"Invalid timestamp format in scenario {scenario['scenario_id']}: {log['timestamp']}") + + +class TestDetectionPerformance(unittest.TestCase): + def test_detection_performance(self): + large_logs = [] + for _ in range(2000): + large_logs.append({ + 'timestamp': '2025-11-20T14:00:00Z', + 'event_type': 'file_write', + 'file_path': 'mcp_config.json', + 'actor_trust_level': 'approved' + }) + + start = datetime.now() + detected = False + + for l in large_logs: + if l.get('event_type') == 'file_write' and l.get('actor_trust_level') == 'unapproved': + detected = True + break + + duration = (datetime.now() - start).total_seconds() + self.assertLess(duration, 1.0, f"Performance too slow: {duration}s") + + +if __name__ == '__main__': + unittest.main(verbosity=2)