# [CRIT] [GHSA / CRITICAL] CVE-2026-48030: Pheditor: OS Command Injection in terminal handler via unsanitized 'dir' parameter

**Source:** GitHub Security Advisories
**Published:** 2026-06-09
**Article:** https://github.com/advisories/GHSA-jvc5-6g7q-c843

## Threat Profile

Pheditor: OS Command Injection in terminal handler via unsanitized 'dir' parameter

### Summary

An OS Command Injection vulnerability in the terminal action handler allows any authenticated user to execute arbitrary OS commands by injecting shell metacharacters into the 'dir' POST parameter, completely bypassing the TERMINAL_COMMANDS whitelist and achieving full Remote Code Execution with web server privileges.

### Details

The terminal handler in pheditor.php accepts two POST parameters: `com…

## Indicators of Compromise (high-fidelity only)

- **CVE:** `CVE-2026-48030`

## MITRE ATT&CK Techniques

- **T1190** — Exploit Public-Facing Application
- **T1204.002** — User Execution: Malicious File
- **T1059.004** — Command and Scripting Interpreter: Unix Shell
- **T1505.003** — Server Software Component: Web Shell

## Kill chain phases observed

_(none detected from narrative keywords)_

## Recommended hunts

### Pheditor CVE-2026-48030 — web server spawning shell interpreter from terminal handler RCE

`UC_73_2` · phase: **install** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats `summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where Processes.parent_process_name IN ("php-fpm","php","php-cgi","apache2","httpd","nginx","php7.4","php8.0","php8.1","php8.2") AND Processes.process_name IN ("sh","bash","dash","ash","zsh") AND Processes.user IN ("www-data","apache","nginx","nobody","httpd","_www","wwwrun") by Processes.dest Processes.user Processes.parent_process_name Processes.parent_process Processes.process_name Processes.process | `drop_dm_object_name(Processes)` | where match(process,"(?i)(curl|wget|cd /tmp|cd /var/www|echo '<\?php|;\s*(curl|wget|nc|bash|sh)|\|\s*(sh|bash)|/dev/tcp/)") OR match(parent_process,"(?i)pheditor\.php") | convert ctime(firstTime) ctime(lastTime)
```

**Defender KQL:**
```kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ ("php-fpm","php","php-cgi","apache2","httpd","nginx","php7.4","php8.0","php8.1","php8.2")
| where FileName in~ ("sh","bash","dash","ash","zsh")
| where InitiatingProcessAccountName in~ ("www-data","apache","nginx","nobody","httpd","_www","wwwrun")
| where ProcessCommandLine has_any ("curl ","wget ","echo '<?php","/dev/tcp/","; curl","|sh","| sh","|bash","| bash","cd /var/www","cd /tmp","nc -e","bash -i")
   or InitiatingProcessCommandLine has "pheditor"
| project Timestamp, DeviceName, AccountName, InitiatingProcessAccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, FolderPath
| order by Timestamp desc
```

### Pheditor CVE-2026-48030 — shell metacharacters in 'dir' POST parameter to pheditor.php

`UC_73_3` · phase: **exploit** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats `summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Web where Web.url="*pheditor.php*" Web.http_method="POST" by Web.src Web.dest Web.user Web.url Web.http_user_agent Web.status | `drop_dm_object_name(Web)` | search (url="*action=terminal*" OR url="*action%3Dterminal*") | search (url="*%3B*" OR url="*%7C*" OR url="*%26%26*" OR url="*%24%28*" OR url="*%60*" OR url="*%0A*" OR url="*%3E%3E*") | convert ctime(firstTime) ctime(lastTime)
```

### Pheditor CVE-2026-48030 — webshell drop: PHP / web account writing .php to webroot

`UC_73_4` · phase: **install** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| tstats `summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Filesystem where Filesystem.process_name IN ("php-fpm","php","php-cgi","apache2","httpd","nginx","sh","bash","dash") AND Filesystem.user IN ("www-data","apache","nginx","nobody","httpd","_www") AND (Filesystem.file_path="/var/www/*" OR Filesystem.file_path="/srv/www/*" OR Filesystem.file_path="/usr/share/nginx/html/*" OR Filesystem.file_path="/srv/http/*") AND Filesystem.file_name="*.php" AND Filesystem.action IN ("created","modified") by Filesystem.dest Filesystem.user Filesystem.process_name Filesystem.file_path Filesystem.file_name Filesystem.file_hash | `drop_dm_object_name(Filesystem)` | convert ctime(firstTime) ctime(lastTime)
```

**Defender KQL:**
```kql
DeviceFileEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ ("php-fpm","php","php-cgi","apache2","httpd","nginx","sh","bash","dash")
| where InitiatingProcessAccountName in~ ("www-data","apache","nginx","nobody","httpd","_www","wwwrun")
| where FolderPath has_any ("/var/www/","/srv/www/","/usr/share/nginx/html/","/srv/http/")
| where FileName endswith ".php" or FileName endswith ".phtml" or FileName endswith ".phar"
| where ActionType in~ ("FileCreated","FileModified","FileRenamed")
| project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName, InitiatingProcessCommandLine, InitiatingProcessParentFileName, FolderPath, FileName, SHA256, ActionType
| order by Timestamp desc
```

### Pheditor CVE-2026-48030 — vulnerable Pheditor 2.0.1–2.0.3 asset inventory exposure

`UC_73_5` · phase: **recon** · confidence: **High** · AI-generated for this article

**Splunk SPL (CIM):**
```spl
| inputlookup vulnerability_scan_results.csv | search (cve_id="CVE-2026-48030" OR (software_name="*pheditor*" AND (software_version="2.0.1" OR software_version="2.0.2" OR software_version="2.0.3"))) | eval is_internet_facing=if(internet_facing="true",1,0) | stats values(software_version) as versions, values(cve_id) as cves, max(is_internet_facing) as exposed by host_name, ip_address | sort -exposed, host_name
```

**Defender KQL:**
```kql
let Vuln = DeviceTvmSoftwareVulnerabilities
  | where Timestamp > ago(7d)
  | where CveId =~ "CVE-2026-48030"
  | project Timestamp, DeviceId, DeviceName, OSPlatform, SoftwareVendor, SoftwareName, SoftwareVersion, VulnerabilitySeverityLevel, RecommendedSecurityUpdate, CveId;
let Inv = DeviceTvmSoftwareInventory
  | where Timestamp > ago(7d)
  | where SoftwareName has "pheditor" or SoftwareVendor has "pheditor"
  | where SoftwareVersion in~ ("2.0.1","2.0.2","2.0.3")
  | project Timestamp, DeviceId, DeviceName, OSPlatform, SoftwareVendor, SoftwareName, SoftwareVersion;
let Surface = DeviceInfo
  | where Timestamp > ago(7d)
  | summarize arg_max(Timestamp, IsInternetFacing, PublicIP, MachineGroup, OSPlatform) by DeviceId, DeviceName;
union Vuln, Inv
| summarize arg_max(Timestamp, *) by DeviceId
| join kind=leftouter Surface on DeviceId
| project Timestamp, DeviceName, OSPlatform, SoftwareVendor, SoftwareName, SoftwareVersion, CveId, IsInternetFacing, PublicIP, MachineGroup
| order by IsInternetFacing desc, DeviceName asc
```

### Article-specific behavioural hunt — [GHSA / CRITICAL] CVE-2026-48030: Pheditor: OS Command Injection in terminal han

`UC_73_1` · phase: **install** · confidence: **High**

**Splunk SPL (CIM):**
```spl
``` Article-specific bespoke detection — [GHSA / CRITICAL] CVE-2026-48030: Pheditor: OS Command Injection in terminal han ```
| tstats `summariesonly` count
    from datamodel=Endpoint.Filesystem
    where Filesystem.action IN ("created","modified")
      AND (Filesystem.file_path="*/dev/null*" OR Filesystem.file_path="*/var/www/html*" OR Filesystem.file_path="*/var/www/html/shell.php*")
    by Filesystem.dest, Filesystem.user, Filesystem.process_name,
       Filesystem.file_path, Filesystem.file_name
| `drop_dm_object_name(Filesystem)`
```

**Defender KQL:**
```kql
// Article-specific bespoke detection — [GHSA / CRITICAL] CVE-2026-48030: Pheditor: OS Command Injection in terminal han
// Hunts the actual binaries / paths / commandline fragments named
// in the article instead of a generic technique-class template.

// File-creation events for the named binaries / paths
DeviceFileEvents
| where Timestamp > ago(30d)
| where ActionType in ("FileCreated","FileModified")
| where (FolderPath has_any ("/dev/null", "/var/www/html", "/var/www/html/shell.php"))
| project Timestamp, DeviceName, AccountName, FolderPath,
          FileName, ActionType, InitiatingProcessFileName,
          InitiatingProcessCommandLine
| order by Timestamp desc
```

### IOC-driven hunts (use shared templates)

These are standard IOC-substitution hunts — the canonical SPL and KQL live once in [`_TEMPLATES.md`](../_TEMPLATES.md), so we don't repeat the same boilerplate on every CVE / hash / network-IOC briefing.

- **Asset exposure — vulnerability matches article CVE(s)** ([template](../_TEMPLATES.md#asset-exposure)) — phase: **recon**, confidence: **High**
  - CVE(s): `CVE-2026-48030`


## Why this matters

Severity classified as **CRIT** based on: CVE present, 6 use case(s) fired, 4 technique(s) inferred. Read the full article for actor attribution, tooling details, and any defanged IOCs in the body that aren't visible in the RSS summary.
