
PoC for CVE-2025-22131
PoC for CVE-2025-22131
PhpSpreadsheet is a library written in pure PHP and offers a set of classes that allow you to read and write various spreadsheet file formats such as Excel and LibreOffice Calc.
phpspreadsheet version <1.29.8>=2.2.0, <2.3.6>=2.0.0, <2.1.7>=3.0.0, <3.8.0 is affected by a vulnerability where the sheet names are not properly sanitized which leads to XSS.
create a simple xlsx file with more than 1 sheet and save it.
unzip the file, update the sheet name manually to the xss payload
zip the file once again
upload the xlsx file to the vulnerable server
exfiltrate the victim's cookie on the given url
Note: I have used the payload to exfiltrate victim's cookie, if something else is desired, update the xl/workbook.xml file accordingly.
/**
* Generate sheet tabs.
*/
public function generateNavigation(): string
{
// Fetch sheets
$sheets = [];
if ($this->sheetIndex === null) {
$sheets = $this->spreadsheet->getAllSheets();
} else {
$sheets[] = $this->spreadsheet->getSheet($this->sheetIndex);
}
// Construct HTML
$html = '';
// Only if there are more than 1 sheets
if (count($sheets) > 1) {
// Loop all sheets
$sheetId = 0;
$html .= '<ul class="navigation">' . PHP_EOL;
foreach ($sheets as $sheet) {
$html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL;
++$sheetId;
}
$html .= '</ul>' . PHP_EOL;
}
return $html;
}
Here the $sheet->getTitle() is not properly escaped using htmlspecialchars() which is why an attacker can inject HTML.
Note that this piece of code only runs when there are more than 1 sheets, so it is necessary to have an xlsx file with more than 1 sheet.
In the PoC, an image tag is used to then exfiltrate the cookies of the victim to the attacker's url.