{
  "hunt": {
    "meta": {
      "tlp": "clear",
      "hunt": {
        "handoff": "keep-as-periodic-hunt",
        "trigger": "intel-report",
        "methodology": "model-assisted",
        "applicability": "campaign-specific",
        "justification": "PHP core vulnerabilities are critical (9.2) and unauthenticated. Proactively hunting for post-exploitation behavior ensures that even if initial RCE occurred, the attacker did not gain persistent control or harvest sensitive credentials."
      },
      "name": "Post-RCE Persistence and Credential Theft",
      "type": "investigation",
      "labels": [
        "hunt",
        "attack.t1190",
        "attack.t1552.001",
        "attack.t1552.005",
        "attack.t1071.001",
        "attack.t1505.003",
        "attack.t1053.003",
        "command and control",
        "credential access",
        "discovery",
        "execution",
        "initial access",
        "persistence"
      ],
      "series": {
        "slug": "php2shell-assessing-elastic-detection-coverage-relevant-to-cve-2026-109618-and-cve-2026-109619",
        "index": 2,
        "title": "php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619",
        "total": 2
      },
      "related": [
        {
          "hunt": "initial-access-php-rce",
          "reason": "This hunt focuses on post-exploitation outcomes; initial HTTP-level exploitation is a separate analysis of web logs.",
          "relation": "out-of-scope-alternative"
        },
        {
          "hunt": "php2shell-web-to-shell-staging",
          "relation": "follows"
        }
      ],
      "targets": {
        "hunter": {
          "name": "Hunt agent",
          "agent": true
        },
        "analyst": {
          "name": "Tier-2 analyst",
          "role": "analyst"
        },
        "endpoint": {
          "name": "Endpoint telemetry (hb_ surfaces)",
          "category": "endpoint",
          "telemetry": [
            "endpoint"
          ]
        }
      },
      "analysis": "A single rule for 'bash from apache' exists but is often disabled for noise; this hunt uses prevalence and multi-surface correlation (process + file) to identify rare credential access that a standing rule cannot baseline effectively.",
      "coverage": [
        {
          "stage": "c2-reverse-shell-primitives",
          "steps": [
            "web-worker-reverse-shells"
          ],
          "status": "covered"
        },
        {
          "stage": "credential-access-harvesting",
          "steps": [
            "web-worker-credential-access"
          ],
          "status": "covered"
        },
        {
          "stage": "persistence-webshell-and-system",
          "steps": [
            "web-worker-credential-access"
          ],
          "status": "covered"
        },
        {
          "stage": "initial-access-php-rce",
          "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "execution-web-worker-shell",
          "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "discovery-system-enumeration",
          "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
          "status": "out_of_scope"
        },
        {
          "stage": "execution-payload-staging",
          "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
          "status": "out_of_scope"
        }
      ],
      "scenario": {
        "stages": [
          {
            "name": "PHP core RCE exploitation",
            "slug": "initial-access-php-rce",
            "tactic": "initial-access",
            "techniques": [
              "T1190"
            ],
            "observables": [
              "CVE-2026-109618",
              "CVE-2026-109619",
              "unauthenticated HTTP request targeting PHP worker (php-fpm, mod_php, php-cgi)"
            ]
          },
          {
            "name": "Web worker spawning shell",
            "slug": "execution-web-worker-shell",
            "tactic": "execution",
            "techniques": [
              "T1059"
            ],
            "observables": [
              "parent_process_name in ('apache2', 'httpd', 'nginx', 'php-cgi', 'php-fpm', 'lsphp')",
              "process_name in ('bash', 'dash', 'sh', 'zsh', 'ksh')",
              "process_args in ('-c', '-cl', '-lc')"
            ]
          },
          {
            "name": "System and identity enumeration",
            "slug": "discovery-system-enumeration",
            "tactic": "discovery",
            "techniques": [
              "T1087",
              "T1082"
            ],
            "observables": [
              "id",
              "whoami",
              "uname -a",
              "hostname",
              "cat /etc/os-release",
              "sudo -l",
              "find / -perm -u=s -type f",
              "getcap -r /",
              "reading /etc/passwd",
              "reading /etc/shadow"
            ]
          },
          {
            "name": "Payload staging and interpreter pivot",
            "slug": "execution-payload-staging",
            "tactic": "execution",
            "techniques": [
              "T1059",
              "T1105"
            ],
            "observables": [
              "python3 -c",
              "perl -e",
              "ruby -e",
              "node -e",
              "php -r",
              "curl -O",
              "wget -O",
              "echo <b64> | base64 -d | sh",
              "openssl enc -d",
              "xxd -r"
            ]
          },
          {
            "name": "Reverse shell communication",
            "slug": "c2-reverse-shell-primitives",
            "tactic": "command-and-control",
            "techniques": [
              "T1071.001"
            ],
            "observables": [
              "/dev/tcp/",
              "mkfifo",
              "nc",
              "socat",
              "pty.spawn",
              "fsockopen"
            ]
          },
          {
            "name": "Credential and identity harvesting",
            "slug": "credential-access-harvesting",
            "tactic": "credential-access",
            "techniques": [
              "T1552.001",
              "T1552.005"
            ],
            "observables": [
              "reading .env files",
              "reading ~/.aws/credentials",
              "accessing /var/run/secrets/kubernetes.io/",
              "HTTP request to 169.254.169.254 (IMDS)"
            ]
          },
          {
            "name": "Webshell and system persistence",
            "slug": "persistence-webshell-and-system",
            "tactic": "persistence",
            "techniques": [
              "T1505.003",
              "T1133",
              "T1053.003"
            ],
            "observables": [
              "writing .php or .phtml to web root",
              "avatar.php.jpg (polyglot/double extension)",
              "adding cron entries",
              "creating systemd units",
              "modifying ~/.ssh/authorized_keys"
            ]
          }
        ],
        "summary": "Unauthenticated remote code execution vulnerabilities in PHP core (CVE-2026-109618 and CVE-2026-109619) allow attackers to gain code execution in the context of web worker processes. Post-exploitation involves web servers spawning shells for system discovery, staging second-stage payloads via interpreters, and establishing persistence through webshells or system configuration."
      },
      "severity": "high",
      "rationale": "Prioritize Linux servers running external-facing PHP applications. If the software inventory is outdated, run the hunt unscoped to capture all web workers.",
      "guardrails": {
        "claims": "no_unsupported",
        "evidence": "citation_required",
        "telemetry": "untrusted",
        "missing_data": "not_benign"
      },
      "hypothesis": "An attacker has exploited a PHP core vulnerability (CVE-2026-109618/109619) and is using the web worker context to harvest credentials or establish persistence via reverse shells and web shells.",
      "parameters": {
        "scope_hosts": {
          "from": {
            "ref": "analyst-scoping",
            "kind": "manual",
            "observed": "2024-10-21"
          },
          "type": "list[host]",
          "default": [],
          "description": "Optional list of hostnames to focus on."
        },
        "lookback_days": {
          "from": {
            "ref": "standard-retention",
            "kind": "manual",
            "observed": "2024-10-21"
          },
          "type": "number",
          "default": "14",
          "description": "Days of history to examine."
        },
        "credential_paths": {
          "from": {
            "ref": "php2shell",
            "kind": "article",
            "observed": "2024-10-21"
          },
          "type": "list[path]",
          "default": [
            "/.env",
            "/.aws/credentials",
            "/var/run/secrets/kubernetes.io/serviceaccount/token",
            "/etc/shadow"
          ],
          "description": "Sensitive file paths commonly targeted for harvesting."
        },
        "web_worker_names": {
          "from": {
            "ref": "php2shell",
            "kind": "article",
            "observed": "2024-10-21"
          },
          "type": "list[string]",
          "default": [
            "php-fpm",
            "apache2",
            "httpd",
            "nginx",
            "lsphp",
            "php-cgi"
          ],
          "description": "Process names of common web workers and PHP runtimes."
        },
        "reverse_shell_tools": {
          "from": {
            "ref": "php2shell",
            "kind": "article",
            "observed": "2024-10-21"
          },
          "type": "list[string]",
          "default": [
            "nc",
            "socat",
            "ncat",
            "netcat",
            "mkfifo"
          ],
          "description": "Binary names often used to establish interactive shells."
        }
      },
      "provenance": {
        "authors": [
          {
            "org": "huntbase.io",
            "name": "Huntbase hunt generation"
          }
        ],
        "generated": {
          "by": "huntbase-hunt-generation",
          "from": "https://www.elastic.co/security-labs/threat-command/php2shell-php-rce-detection",
          "gates": [
            "dry-run",
            "lint"
          ],
          "model": "hb_google/gemini-3-flash-preview"
        }
      },
      "references": [
        {
          "url": "https://www.elastic.co/security-labs/threat-command/php2shell-php-rce-detection",
          "name": "php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619"
        }
      ],
      "blind_spots": [
        {
          "id": "no-linux-endpoint-telemetry",
          "risk": "A host without an agent provides no telemetry for process spawns or file reads, making RCE outcome invisible.",
          "stage": "c2-reverse-shell-primitives",
          "question": "Are all web server nodes enrolled in process and file monitoring?",
          "requires": "Endpoint agent on all Linux web nodes"
        },
        {
          "id": "fileless-php-execution",
          "risk": "In-memory only execution bypasses process and file surfaces; detection relies on networking or script-block logging which may be incomplete.",
          "stage": "c2-reverse-shell-primitives",
          "question": "Can we see PHP execution that uses eval() without spawning a shell?",
          "requires": "PHP interpreter-level auditing"
        }
      ]
    },
    "name": "Post-RCE Persistence and Credential Theft",
    "description": "This hunt targets the post-exploitation objectives of the php2shell vulnerabilities. It specifically examines web worker processes (php-fpm, apache2, nginx) for convergent malicious behavior: accessing cloud credentials, environment files, or instance metadata, and spawning interactive shell primitives like netcat or socat. The hunt uses a parallel fan-out to analyze file activity and process execution across multiple surfaces, identifying rare or unauthorized actions originating from the web stack."
  },
  "nodes": [
    {
      "id": "hypothesis",
      "type": "hypothesis",
      "label": "Hypothesis",
      "config": {
        "tags": [],
        "series": {
          "slug": "php2shell-assessing-elastic-detection-coverage-relevant-to-cve-2026-109618-and-cve-2026-109619",
          "index": 2,
          "title": "php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619",
          "total": 2
        },
        "coverage": [
          {
            "stage": "c2-reverse-shell-primitives",
            "steps": [
              "web-worker-reverse-shells"
            ],
            "status": "covered"
          },
          {
            "stage": "credential-access-harvesting",
            "steps": [
              "web-worker-credential-access"
            ],
            "status": "covered"
          },
          {
            "stage": "persistence-webshell-and-system",
            "steps": [
              "web-worker-credential-access"
            ],
            "status": "covered"
          },
          {
            "stage": "initial-access-php-rce",
            "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "execution-web-worker-shell",
            "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "discovery-system-enumeration",
            "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
            "status": "out_of_scope"
          },
          {
            "stage": "execution-payload-staging",
            "reason": "Belongs to another part of the 'php2shell: Assessing Elastic detection coverage relevant to CVE-2026-109618 and CVE-2026-109619' series.",
            "status": "out_of_scope"
          }
        ],
        "rationale": "An attacker has exploited a PHP core vulnerability (CVE-2026-109618/109619) and is using the web worker context to harvest credentials or establish persistence via reverse shells and web shells.",
        "blind_spots": [
          {
            "id": "no-linux-endpoint-telemetry",
            "risk": "A host without an agent provides no telemetry for process spawns or file reads, making RCE outcome invisible.",
            "stage": "c2-reverse-shell-primitives",
            "question": "Are all web server nodes enrolled in process and file monitoring?",
            "requires": "Endpoint agent on all Linux web nodes"
          },
          {
            "id": "fileless-php-execution",
            "risk": "In-memory only execution bypasses process and file surfaces; detection relies on networking or script-block logging which may be incomplete.",
            "stage": "c2-reverse-shell-primitives",
            "question": "Can we see PHP execution that uses eval() without spawning a shell?",
            "requires": "PHP interpreter-level auditing"
          }
        ],
        "scoping_notes": "Prioritize Linux servers running external-facing PHP applications. If the software inventory is outdated, run the hunt unscoped to capture all web workers.",
        "beyond_detection": "A single rule for 'bash from apache' exists but is often disabled for noise; this hunt uses prevalence and multi-surface correlation (process + file) to identify rare credential access that a standing rule cannot baseline effectively."
      }
    },
    {
      "id": "identify-php-assets",
      "type": "query",
      "label": "Identify PHP-capable assets",
      "config": {
        "dsl": "sqlite",
        "role": "scoping",
        "source": "endpoint",
        "content": "SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE (LOWER(package_name) LIKE '%php%' OR LOWER(package_name) LIKE '%apache%' OR LOWER(package_name) LIKE '%nginx%') AND asset_scope = 'endpoint'",
        "surface": "hb_software_inventory",
        "description": "Scope the hunt to hosts running PHP or major web server packages.",
        "expected_signal": "A list of hosts that likely have a web stack capable of being exploited by PHP RCE. Silence suggests the estate has no indexed PHP/web software."
      },
      "parents": [
        {
          "id": "hypothesis"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "scoping",
        "label": "Identify PHP-capable assets",
        "reads": [
          "package_name",
          "device_hostname",
          "asset_scope"
        ],
        "source": "hb_software_inventory",
        "target": "endpoint",
        "content": "SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE (LOWER(package_name) LIKE '%php%' OR LOWER(package_name) LIKE '%apache%' OR LOWER(package_name) LIKE '%nginx%') AND asset_scope = 'endpoint'",
        "silence": "not_evidence_of_absence",
        "expected": "A list of hosts that likely have a web stack capable of being exploited by PHP RCE. Silence suggests the estate has no indexed PHP/web software.",
        "verified": "dry-run",
        "verified_at": "2026-10-22"
      }
    },
    {
      "id": "web-worker-credential-access",
      "type": "query",
      "label": "Web worker access to credentials and persistence",
      "config": {
        "dsl": "sqlite",
        "role": "baseline",
        "source": "endpoint",
        "content": "SELECT device_hostname, process_name, file_path, activity_name, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_file_activity WHERE (instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(parent_process_name) || ',') > 0) AND (instr(',' || '{{credential_paths}}' || ',', ',' || LOWER(file_path) || ',') > 0 OR (activity_id = 1 AND (LOWER(file_path) LIKE '%.php' OR LOWER(file_path) LIKE '%.phtml' OR LOWER(file_path) LIKE '%avatar.php.jpg'))) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name, file_path, activity_name HAVING host_count <= 5",
        "surface": "hb_file_activity",
        "description": "Identify web workers reading credential files or writing new PHP/phtml files.",
        "expected_signal": "A web worker process accessing sensitive files or creating new PHP scripts on a small subset of hosts. Normal application behavior should be widespread and excluded by the prevalence check."
      },
      "parents": [
        {
          "id": "identify-php-assets"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "baseline",
        "label": "Web worker access to credentials and persistence",
        "reads": [
          "device_hostname",
          "process_name",
          "file_path",
          "activity_name",
          "time"
        ],
        "source": "hb_file_activity",
        "target": "endpoint",
        "content": "SELECT device_hostname, process_name, file_path, activity_name, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_file_activity WHERE (instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(parent_process_name) || ',') > 0) AND (instr(',' || '{{credential_paths}}' || ',', ',' || LOWER(file_path) || ',') > 0 OR (activity_id = 1 AND (LOWER(file_path) LIKE '%.php' OR LOWER(file_path) LIKE '%.phtml' OR LOWER(file_path) LIKE '%avatar.php.jpg'))) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name, file_path, activity_name HAVING host_count <= 5",
        "silence": "not_evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "first_seen"
        },
        "expected": "A web worker process accessing sensitive files or creating new PHP scripts on a small subset of hosts. Normal application behavior should be widespread and excluded by the prevalence check.",
        "verified": "dry-run",
        "prevalence": {
          "by": "device_hostname",
          "key": [
            "process_name",
            "file_path"
          ],
          "rare_below": 5
        },
        "verified_at": "2026-10-22"
      }
    },
    {
      "id": "web-worker-reverse-shells",
      "type": "query",
      "label": "Web worker spawning shells and network tools",
      "config": {
        "dsl": "sqlite",
        "role": "triage",
        "source": "endpoint",
        "content": "SELECT device_hostname, process_name, process_cmd_line, parent_process_name, time FROM hb_process_activity WHERE (instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(parent_process_name) || ',') > 0 OR instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(actor_process_name) || ',') > 0) AND (instr(',' || '{{reverse_shell_tools}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR process_cmd_line LIKE '%/dev/tcp/%' OR process_cmd_line LIKE '%pty.spawn%' OR process_cmd_line LIKE '%fsockopen%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')",
        "surface": "hb_process_activity",
        "description": "Identify web workers spawning shell primitives or redirection tools used for interactive access.",
        "expected_signal": "A web worker spawning netcat, socat, or shell primitives. This is a high-confidence signal of post-exploitation command-and-control."
      },
      "parents": [
        {
          "id": "identify-php-assets"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "triage",
        "label": "Web worker spawning shells and network tools",
        "reads": [
          "device_hostname",
          "process_name",
          "process_cmd_line",
          "parent_process_name",
          "time"
        ],
        "source": "hb_process_activity",
        "target": "endpoint",
        "content": "SELECT device_hostname, process_name, process_cmd_line, parent_process_name, time FROM hb_process_activity WHERE (instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(parent_process_name) || ',') > 0 OR instr(',' || '{{web_worker_names}}' || ',', ',' || LOWER(actor_process_name) || ',') > 0) AND (instr(',' || '{{reverse_shell_tools}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR process_cmd_line LIKE '%/dev/tcp/%' OR process_cmd_line LIKE '%pty.spawn%' OR process_cmd_line LIKE '%fsockopen%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')",
        "silence": "not_evidence_of_absence",
        "expected": "A web worker spawning netcat, socat, or shell primitives. This is a high-confidence signal of post-exploitation command-and-control.",
        "verified": "dry-run",
        "verified_at": "2026-10-22"
      }
    },
    {
      "id": "triage-worker-behavior",
      "type": "analytic",
      "label": "Triage worker behavior",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint"
        ],
        "context": [
          "web-worker-credential-access",
          "web-worker-reverse-shells"
        ],
        "objective": "Determine if the rare file access and process execution patterns indicate a compromised web node.",
        "description": "Correlate findings to determine if the web worker actions indicate a successful RCE intrusion.",
        "max_iterations": 4,
        "expected_signal": "A per-host verdict of malicious, suspicious, or benign.",
        "success_criteria": "A detailed verdict per host citing rows that show unauthorized transitions from web requests to system-level access."
      },
      "parents": [
        {
          "id": "web-worker-credential-access",
          "kind": "merge"
        },
        {
          "id": "web-worker-reverse-shells",
          "kind": "merge"
        }
      ]
    },
    {
      "id": "route-on-triage",
      "type": "checkpoint",
      "label": "Route on triage verdict",
      "config": {
        "fuzzy": true,
        "judge": "hunter",
        "question": "the triage verdict is malicious for at least one host involving credential theft or reverse shells",
        "condition": "the triage verdict is malicious for at least one host involving credential theft or reverse shells",
        "blind_spot": "no-linux-endpoint-telemetry",
        "confidence": "high",
        "description": "Direct the response based on the agent's confidence and findings.",
        "checkpoint_type": "mandatory"
      },
      "parents": [
        {
          "id": "triage-worker-behavior"
        }
      ]
    },
    {
      "id": "isolate-affected-host",
      "type": "action",
      "label": "Isolate affected host",
      "config": {
        "target": "endpoint",
        "description": "Contain the breach by isolating the host from the network.",
        "instructions": "Isolate the host, revoke any cloud credentials found in the agent context, and collect memory/web-root artifacts.",
        "action_approval": "required"
      },
      "parents": [
        {
          "id": "route-on-triage",
          "branch": "on_supports"
        }
      ]
    },
    {
      "id": "manual-forensic-review",
      "type": "task",
      "label": "Manual forensic review",
      "config": {
        "assignee": "analyst",
        "description": "Final analyst verification of the agent's findings.",
        "instructions": "Review the cited rows. Verify if the web worker access to .env or AWS credentials is part of a standard application deployment. Check the timing of file writes against known RCE disclosure windows."
      },
      "parents": [
        {
          "id": "route-on-triage",
          "branch": "default"
        },
        {
          "id": "route-on-triage",
          "branch": "on_unavailable"
        },
        {
          "id": "isolate-affected-host"
        }
      ]
    },
    {
      "id": "close-out-php-hunt",
      "type": "task",
      "label": "Close out PHP hunt",
      "config": {
        "assignee": "analyst",
        "description": "Finalize the hunt and record coverage gaps.",
        "instructions": "Document the hosts examined. If no malicious activity was found, record this as evidence of absence for the php2shell scenario."
      },
      "parents": [
        {
          "id": "route-on-triage",
          "branch": "on_refutes"
        },
        {
          "id": "manual-forensic-review"
        }
      ]
    }
  ]
}