Headline
CVE-2023-50252: Unsafe attributes merge when parsing `use` tag
php-svg-lib is an SVG file parsing / rendering library. Prior to version 0.5.1, when handling <use>
tag that references an <image>
tag, it merges the attributes from the <use>
tag to the <image>
tag. The problem pops up especially when the href
attribute from the <use>
tag has not been sanitized. This can lead to an unsafe file read that can cause PHAR Deserialization vulnerability in PHP prior to version 8. Version 0.5.1 contains a patch for this issue.
Summary
When handling <use> tag that references an <image> tag, it merges the attributes from the <use> tag to the <image> tag. The problem pops up especially when the href attribute from the <use> tag has not been sanitized. This can lead to an unsafe file read that can cause PHAR Deserialization vulnerability in PHP < 8.
Details
When parsing an <use> tag, it will try to find the referenced object refered by the href attribute. If it is found, it will save it on the $referenced property.
When UseTag::handle is called, the attributes of the <use> tag will be merged with the attributes of the referenced tag:
$mergedAttributes = $this->reference->attributes;
$attributesToNotMerge = ['x', 'y', 'width', 'height'];
foreach ($attributes as $attrKey => $attrVal) {
if (!in_array($attrKey, $attributesToNotMerge) && !isset($mergedAttributes[$attrKey])) {
$mergedAttributes[$attrKey] = $attrVal;
}
}
As shown by the above code, the href attribute is included in the merging process, overiding the href attributes of the referenced tag.
The problem comes if the referenced object is an <image> tag, because the href of the original <image> tag will be overiden, thus bypasing any validation that has occured before for the <image> tag (this is the case in dompdf, as dompdf will sanitize the href attribute in svg file).
Now, after the merging process has finished, the referenced object’s handle method is called:
$this->reference->handle($mergedAttributes);
When the <image> tag handle method is called, it will try to draw the image but with the href coming from the <use> tag:
// ImageTag::start
$this->document->getSurface()->drawImage($this->href, $this->x, $this->y, $this->width, $this->height);
Before drawing the image, it will use file_get_contents to load the image based on the href attribute
If this href is pointing to a phar file, it can lead to dangerous deserialization problem ini php <8.
PoC
This is the svg used in this research:
<svg width="200" height="200"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image id="phar:///poc.phar" xlink:href="file:///existing/safe/image.png" />
<use href="phar:///poc.phar" width="500" height="500"/>
</svg>
When the above code is parsed, the library will load the file via file_get_contents:
$data = file_get_contents("phar:///poc.phar");
Impact
In PHP < 8, the above vulnerability could lead to dangerous deserialization from the phar file. This could lead to file deletion (thus causing denial of service), and even RCE, depending on the classes available in the system.
Mitigation
Systems utilizing php-svg-lib can implement input validation using logic similar to the following:
$parser = xml_parser_create("utf-8");
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
xml_set_element_handler(
$parser,
function ($parser, $name, $attributes) {
if (strtolower($name) === "image" || strtolower($name) === "use") {
$attributes = array_change_key_case($attributes, CASE_LOWER);
$urls = [];
$urls[] = $attributes["xlink:href"] ?? "";
$urls[] = $attributes["href"] ?? "";
foreach ($urls as $url) {
if (!empty($url)) {
// perform validation here
}
}
}
// include other tag/attribute validation
},
false
);
if (($fp = fopen($url, "r")) !== false) {
while ($line = fread($fp, 8192)) {
xml_parse($parser, $line, false);
}
fclose($fp);
xml_parse($parser, "", true);
}
xml_parser_free($parser);
Related news
Debian Linux Security Advisory 5642-1 - Three security issues were discovered in php-svg-lib, a PHP library to read, parse and export to PDF SVG files, which could result in denial of service, restriction bypass or the execution of arbitrary code.