使用PHP消毒SVG [英] Sanitizing SVG using PHP

查看:94
本文介绍了使用PHP消毒SVG的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用d3.js作为SVG动态创建图表.这些图表是根据经过身份验证的用户的选择动态生成的.生成这些图表后,用户可以选择将生成的SVG下载为PNG或PDF.

I am creating charts on the fly as SVGs using d3.js. These charts are dynamically generated based on the selections of authenticated users. Once these charts are generated, the user has the option to download the generated SVG as a PNG or PDF.

当前工作流程如下:

// JAVASC
// get the element containing generated SVG
var svg = document.getElementById("chart-container");

// Extract the data as SVG text string
var svg_xml = (new XMLSerializer).serializeToString(svg);

// Submit the <FORM> to the server.
var form = document.getElementById("svgform");
form['output_format'].value = output_format;  // can be either "pdf" or "png"
form['data'].value = svg_xml ;
form.submit();

FORM元素是一个隐藏的表单,用于发布数据:

The FORM element is a hidden form, used to POST the data:

<form id="svgform" method="post" action="conversion.php">
  <input type="hidden" id="output_format" name="output_format" value="">
  <input type="hidden" id="data" name="data" value="">
</form>

PHP文件将提供的SVG数据另存为临时文件:

The PHP file saves the provided SVG data as a temporary file:

// check for valid session, etc - omitted for brevity 

$xmldat = $_POST['data'];  // serialized XML representing the SVG element
if(simplexml_load_string($xmldat)===FALSE) { die; } // reject invalid XML  

$fileformat = $_POST['output_format'];  // chosen format for output;  PNG or PDF
if ($fileformat != "pdf" && $fileformat != "png" ){ die; } // limited options for format
$fileformat = escapeshellarg($fileformat); // escape shell arguments that might have snuck in

// generate temporary file names with tempnam() - omitted for brevity

$handle = fopen($infile, "w");
fwrite($handle, $xmldat);
fclose($handle);

运行转换实用程序,该实用程序读取临时文件($ infile)并以指定的$ fileformat(PDF或PNG)创建新文件($ outfile).然后将生成的新文件返回到浏览器,并删除临时文件:

A conversion utility is run which reads the temporary file ($infile) and creates a new file ($outfile) in the specified $fileformat (PDF or PNG). The resulting new file is then returned to the browser, and the temporary files are deleted:

// headers etc generated - omitted for brevity
readfile($outfile);

unlink($infile);  // delete temporary infile  
unlink($outfile);  // delete temporary outfile  

我已经调查了使用JavaScript将SVG转换为PNG(canvg(),然后转换为DataURL,然后转换为document.write),并且可以将其用于生成PNG,但不允许将其转换为PDF.

I have investigated converting the SVG to a PNG using JavaScript (canvg(), then toDataURL, then document.write), and may use this for generating the PNGs, but it doesn't allow for conversion to PDF.

所以: 在将conversion.php提供的SVG数据写入文件之前,我该如何最好地对其进行清理或过滤? SVG消毒的当前状态是什么? PHP提供了哪些功能?我是否应该使用基于白名单的方法来清理SVG数据提供给conversion.php,还是有更好的方法?

So: How can I best sanitize or filter the SVG data which is provided to conversion.php, before it's written to a file? What's the current state of SVG sanitization? What's available within PHP? Should I go with a whitelist-based approach to sanitizing the SVG data provided to conversion.php, or is there a better way?

(我不了解XSLT,尽管我可以尝试学习它;我希望尽可能地在PHP中进行清理.使用Windows Server 2008,因此任何使用外部工具的解决方案都必须在该版本中可用.生态系统.)

(I do not know XSLT, though I could try to learn it; I hope to keep the sanitization within PHP as much as possible. Using Windows Server 2008, so any solutions that use external tools would need to be available within that ecosystem.)

推荐答案

您需要使用XML解析器+白名单对SVG进行清理.

You need to sanitize SVG using XML parser + whitelist.

由于SVG已经具有执行代码的多种方法,并且将来的扩展可能会添加其他方法,因此您根本无法将已知危险"的构造列入黑名单.只要正确处理所有XML极端情况(例如XSLT样式表,实体扩展,外部实体引用),就可以将安全元素和属性列入白名单.

Because SVG already has multiple ways to execute code and future extensions may add additional methods, you simply cannot blacklist "known dangerous" constructs. Whitelisting safe elements and attributes does work as long as you correctly handle all the XML corner cases (e.g. XSLT stylesheets, entity expansions, external entity references).

示例实现: https://github.com/alnorris/SVG-Sanitizer/blob/master/SvgSanitizer.php (MIT许可)或 https://github.com/darylldoyle/svg-sanitizer (GPL v2许可证)

Example implementations: https://github.com/alnorris/SVG-Sanitizer/blob/master/SvgSanitizer.php (MIT license) or https://github.com/darylldoyle/svg-sanitizer (GPL v2 license)

有关在选择要支持的功能时必须考虑的攻击媒介的更多信息:

More information about attack vectors that you have to consider while selecting which features you want to support:

  • https://phabricator.wikimedia.org/T85850 (base64 encoded parts)
  • https://www.slideshare.net/x00mario/the-image-that-called-me (different ways to execute code)
  • https://www.blackhat.com/docs/us-14/materials/us-14-DeGraaf-SVG-Exploiting-Browsers-Without-Image-Parsing-Bugs.pdf (embedding HTML inside SVG, SVG can do pretty much anything any XML file can do and any HTML file can do, using SVG inside <object> allows JS from inside the SVG to execute in parent document)
  • https://bjornjohansen.no/svg-in-wordpress (filtering SVG is hard enough that even WordPress still does not have a good solution for user submitted SVG files)
  • http://html5sec.org/?svg (list of some known SVG attacks by misusing different APIs)
  • https://security.stackexchange.com/questions/26264
  • https://blobfolio.com/2017/03/when-a-stranger-calls-sanitizing-svgs/ (different ways to encode stuff, clever use of whitespace to avoid detection, xml tricks)

这篇关于使用PHP消毒SVG的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆