整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

使用 SVG 制作加载动画

者:公子

出处:https://segmentfault.com/a/1190000024526176

pire.Office 7.7.6 已发布。本次更新带来了一些新功能,如:Spire.Doc 在使用新引擎转换 Word 到 PDF 时支持保留文本方向;Spire.PDF 支持创建标签 PDF 文件;Spire.XLS 支持在导出 DataTable 时,设置是否保持数据的数字格式;Spire.Presentation 支持裁切幻灯片图片。此外,该版本还成功修复了许多已知问题。详情请阅读以下内容。

该版本涵盖了最新版的Spire.Doc,Spire.PDF,Spire.XLS,Spire.Email,Spire.DocViewer, Spire.PDFViewer,Spire.Presentation,Spire.Spreadsheet, Spire.OfficeViewer, Spire.DocViewer, Spire.Barcode, Spire.DataExport。

版本信息如下:

  • Spire.Doc.dll v10.7.16
  • Spire.Pdf.dll v8.7.9
  • Spire.XLS.dll v12.7.0
  • Spire.Email.dll v5.6.0
  • Spire.DocViewer.Forms.dll v7.6.0
  • Spire.PdfViewer.Forms.dll v7.7.0
  • Spire.PdfViewer.Asp.dll v7.7.0
  • Spire.Presentation.dll v7.7.1
  • Spire.Spreadsheet.dll v6.6.1
  • Spire.OfficeViewer.Forms.dll v7.7.6
  • Spire.Barcode.dll v6.7.0
  • Spire.DataExport.dll v4.5.0
  • Spire.DataExport.ResourceMgr.dll v2.1.0

获取Spire.Office 7.7.6请点击:

Spire.Office for .NET | 下载


Spire.PDF

新功能:

  • 支持创建标签PDF 文件
//Note:At present, in order to ensure the validity of the output tagged PDF file, it is necessary to add the valid license of Spire.PDF for .net to remove the red warning watermark.

//Spire.License.LicenseProvider.SetLicenseKey("valid license key");

//Create a pdf document
PdfDocument doc = new PdfDocument();

//Add page
doc.Pages.Add();

//Set tab order
doc.Pages[0].SetTabOrder(TabOrder.Structure);

//Create PdfTaggedContent
PdfTaggedContent taggedContent = new PdfTaggedContent(doc);
taggedContent.SetLanguage("en-US");
taggedContent.SetTitle("test");

//Set font
PdfTrueTypeFont font = new PdfTrueTypeFont(new System.Drawing.Font("Times New Roman", 10), true);
PdfSolidBrush brush = new PdfSolidBrush(Color.Black);

//Append elements
PdfStructureElement article = taggedContent.StructureTreeRoot.AppendChildElement(PdfStandardStructTypes.Document);
PdfStructureElement paragraph1 = article.AppendChildElement(PdfStandardStructTypes.Paragraph);
PdfStructureElement span1 = paragraph1.AppendChildElement(PdfStandardStructTypes.Span);
span1.BeginMarkedContent(doc.Pages[0]);

PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Justify);
doc.Pages[0].Canvas.DrawString("Spire.PDF for .NET is a professional PDF API applied to creating, writing, editing, handling and reading PDF files.",
font, brush, new Rectangle(40, 0, 480, 80), format);
span1.EndMarkedContent(doc.Pages[0]);

PdfStructureElement paragraph2 = article.AppendChildElement(PdfStandardStructTypes.Paragraph);
paragraph2.BeginMarkedContent(doc.Pages[0]); doc.Pages[0].Canvas.DrawString("Spire.PDF for .NET can be applied to easily convert Text, Image, SVG, HTML to PDF and convert PDF to Excel with C#/VB.NET in high quality.",
font, brush, new Rectangle(40, 80, 480, 60), format);
paragraph2.EndMarkedContent(doc.Pages[0]);

PdfStructureElement figure1 = article.AppendChildElement(PdfStandardStructTypes.Figure);
//Set Alternate text 
figure1.Alt = "replacement text1";
figure1.BeginMarkedContent(doc.Pages[0], null);
PdfImage image = PdfImage.FromFile(@"E-logo.png");
doc.Pages[0].Canvas.DrawImage(image, new PointF(40, 200), new SizeF(100, 100));
figure1.EndMarkedContent(doc.Pages[0]);

PdfStructureElement figure2 = article.AppendChildElement(PdfStandardStructTypes.Figure);
//Set Alternate text
figure2.Alt = "replacement text2";
figure2.BeginMarkedContent(doc.Pages[0], null);
  doc.Pages[0].Canvas.DrawRectangle(PdfPens.Black, new Rectangle(300, 200, 100, 100));
figure2.EndMarkedContent(doc.Pages[0]);

//Save to file
String result = "CreateTaggedFile_result.pdf";
doc.SaveToFile(result);
doc.Close();
  • 支持创建 PDF/UA 文件
//Note:At present, in order to ensure the validity of the output PDF/UA file, it is necessary to add the valid license of Spire.PDF for .net to remove the red warning watermark.
//Spire.License.LicenseProvider.SetLicenseKey("valid license key");

//Create a pdf document
PdfDocument doc = new PdfDocument();

//Add page
doc.Pages.Add();

//Set tab order
doc.Pages[0].SetTabOrder(TabOrder.Structure);

//Create PdfTaggedContent
PdfTaggedContent taggedContent = new PdfTaggedContent(doc);
taggedContent.SetLanguage("en-US");
taggedContent.SetTitle("test");

//Set PDF/UA1 identification
taggedContent.SetPdfUA1Identification();

//Set font
PdfTrueTypeFont font = new PdfTrueTypeFont(new System.Drawing.Font("Times New Roman", 10), true);
PdfSolidBrush brush = new PdfSolidBrush(Color.Black);

//Append elements
PdfStructureElement article = taggedContent.StructureTreeRoot.AppendChildElement(PdfStandardStructTypes.Document);
PdfStructureElement paragraph1 = article.AppendChildElement(PdfStandardStructTypes.Paragraph);
PdfStructureElement span1 = paragraph1.AppendChildElement(PdfStandardStructTypes.Span);
span1.BeginMarkedContent(doc.Pages[0]);

PdfStringFormat format = new PdfStringFormat(PdfTextAlignment.Justify);
doc.Pages[0].Canvas.DrawString("Spire.PDF for .NET is a professional PDF API applied to creating, writing, editing, handling and reading PDF files.",
font, brush, new Rectangle(40, 0, 480, 80), format);
span1.EndMarkedContent(doc.Pages[0]);

PdfStructureElement paragraph2 = article.AppendChildElement(PdfStandardStructTypes.Paragraph);
paragraph2.BeginMarkedContent(doc.Pages[0]);
doc.Pages[0].Canvas.DrawString("Spire.PDF for .NET can be applied to easily convert Text, Image, SVG, HTML to PDF and convert PDF to Excel with C#/VB.NET in high quality.",
font, brush, new Rectangle(40, 80, 480, 60), format);
paragraph2.EndMarkedContent(doc.Pages[0]);

PdfStructureElement figure1 = article.AppendChildElement(PdfStandardStructTypes.Figure);
//Set Alternate text 
figure1.Alt = "replacement text1";
figure1.BeginMarkedContent(doc.Pages[0], null);
PdfImage image = PdfImage.FromFile(@"E-logo.png");
doc.Pages[0].Canvas.DrawImage(image, new PointF(40, 200), new SizeF(100, 100));
figure1.EndMarkedContent(doc.Pages[0]);

PdfStructureElement figure2 = article.AppendChildElement(PdfStandardStructTypes.Figure);
//Set Alternate text
figure2.Alt = "replacement text2";
figure2.BeginMarkedContent(doc.Pages[0], null);
  doc.Pages[0].Canvas.DrawRectangle(PdfPens.Black, new Rectangle(300, 200, 100, 100));
figure2.EndMarkedContent(doc.Pages[0]);

//Save to file
String result = "CreatePDFUAFile_result.pdf";
doc.SaveToFile(result);
doc.Close();

问题修复:

  • 修复了应用程序在使用时间戳服务器签署 PDF 文档时抛出“System.NotSupportedException”的问题。
  • 修复了PDF转excel文件后内容格式不正确的问题。
  • 修复了应用程序在将 PDF 转换为 SVG 时抛出“System.NullReferenceException”的问题。
  • 修复了打印PDF文件后,印章内容格式不正确的问题。
  • 优化了查找 PDF 文件文本时的耗时问题。
  • 修复了 ReplaceAllText() 函数不生效的问题。
  • 优化 了DrawString() 方法以绘制 Html 字符串。
  • 修复了合并 PDF 文件时应用程序抛出“System.IndexOutOfRangeException”的问题。
  • 修复了 RemoveCustomProperty() 函数效果不正确的问题。
  • 修复了应用程序在压缩 PDF 图像时抛出“System.OutOfMemoryException”的问题。
  • 修复了从 u3d 文件转换后,无法打开输出 PDF 的问题。
  • 修复了提取的图片大小不正确的问题。
  • 修复了PDF转图片后,PDF文件二维码不正确的问题。
  • 修复了从 PDF/A 文件中提取文本时,应用程序抛出“System.NullReferenceException”的问题。
  • 修复了无法从 PDF 文件中找到文本的问题。
  • 修复了应用程序在加载并直接保存 PDF 文件后抛出“Invalid year in date string”的问题。
  • 修复了打印 PDF 文件后内容丢失的问题。

Spire.Doc

新功能:

  • 在使用新引擎转换Word到PDF时支持保留文本方向。

功能调整:

  • 废弃了public IStyle FindById(int styleId)方法。
  • 废弃了public IStyle FindByIstd(int istd)方法。
  • 公开了public IStyle FindByIdentifier(int sIdentifier)方法。

问题修复:

  • 修复了转换Word到PDF,分页不正确的问题。
  • 修复了转换Word到PDF,内容格式不正确的问题。
  • 修复了转换Word到PDF,换行不正确的问题。
  • 修复了转换Word到PDF,表格文字显示不全的问题。
  • 修复了加载HTML,程序抛异常“InvalidOperationException”的问题。
  • 修复了替换图片,程序抛异常“InvalidCastException”的问题。
  • 修复了加载HTML, 程序抛异常“FileNotFoundException”的问题。
  • 修复了域值设置不正确的问题。
  • 修复了转换Word到PDF,数学公式错位的问题。
  • 修复了使用新引擎方式转换Word到PDF时,设置页眉页脚不连续上一章节不生效的问题。
  • 修复了转换Word到PDF,程序抛异常“InvalidOperationException”的问题。
  • 修复了Comment.CommentMarkEnd和Comment.CommentMarkStart的引用问题。
  • 修复了统计段落字符数目不正确的问题。
  • 修复了合并单元格多出列的问题。
  • 修复了加载HTML文件时程序抛出“NullReferenceException: 未将对象引用设置到对象的实例”异常的问题。
  • 修复了Word转PDF后表格多出边框线的问题。
  • 修复了HTML转Word后表格边框丢失的问题。
  • 修复了HTML转Word后表格位置发生变化的问题。
  • 修复了生成Doc格式文档时表格布局不正确的问题。
  • 修复了RTF转PDF后图片丢失的问题。
  • 修复了创建分栏页面后转PDF分栏不生效的问题。
  • 修复了向书签中添加文本后多出空格的问题。
  • 修复了Word转PDF程序挂起的问题。
  • 修复了Word转PDF后图片不正确的问题。
  • 修复了给文档设置自定义属性为空时程序抛出异常"属性值的类型不受支持"的问题。

Spire.XLS

新功能:

  • 支持在导出DataTable时,设置是否保持数据的数字格式。
ExportTableOptions options = new ExportTableOptions();
options.KeepDataFormat = false;
DataTable table = sheet.ExportDataTable(1, 1, sheet.LastDataRow, sheet.LastDataColumn, options);
  • 支持计算“UNICODE”公式

问题修复:

  • 修复了Excel转PDF后,透视表列名位置偏移的问题。
  • 修复了加载HTML文件时抛出“System. FormatException:Input string was not in a correct format”异常的问题。
  • 修复了插入公式后,公式未计算出结果的问题。
  • 修复了“CellRange.DisplayedText”属性获取值不正确的问题。
  • 修复了Excel转PDF时,抛出“System.FormatException:该字符串未被识别为有效的 DateTime”异常的问题。
  • 修复了获取非连续范围的名称管理器抛出空指针异常的问题。

Spire.PDFViewer

问题修复:

  • 优化了文档加载时间。
  • 修复了预览文档内容空白的问题。
  • 修复了旋转PDF程序抛异常“value can not be null”。
  • 修复了预览文档图章丢失的问题。

Spire.Presentation

新功能:

  • 支持裁切幻灯片图片。
SlidePicture slidePicture =    (SlidePicture)presentation.Slides[0].Shapes[0];
slidePicture.Crop(float x, float y, float   width, float height);
  • 提供InsertPicture(stream)方法支持从文件流插入图片到幻灯片中。
presentation.Slides[0].Shapes[0].InsertPicture(Stream stream)
  • 支持创建PowerPoint2016新增的图表类型(Waterfall,Treemap、Boxandwhisker,Histogram,Pareto,SunBurst)。

x00 前言

在过去几周中,FortiGuard Labs一直在研究带有SVG(Scalable Vector Graphics)图像的Web应用。根据研究结果,我们找到了Web应用中的一些常见问题。在本文中,我们简要介绍了SVG的特点以及针对SVG图像的常见攻击面。

根据之前的研究结果,我们梳理了一些常见的SVG攻击方式,如下所示:

  • 跨站脚本(Cross-Site Scripting)
  • HTML注入
  • XML实体:“Billion Laughs”攻击(针对XML文档解析器的一种DoS攻击)
  • DoS(拒绝服务):新型SVG “Billion Laughs”攻击。

0x01 SVG简介

SVG的全称为 Scalable Vector Graphics(可缩放矢量图),是一种基于XML的二维矢量图格式,支持交互性及动画展示。SVG图像及具体行为由XML文本文件定义,可以通过任何文本编辑器以及绘图软件来创建并编辑。目前所有主流web浏览器都支持渲染SVG图像。

来观察一个示例,更好理解SVG图像。如下图所示,我们编写了一些代码来渲染SVG图像:

图1. simple.svg代码片段

将该图像保存为simple.svg,然后直接打开,或者将其包含在img/image/object/embed HTML标签中,如下图所示:

图2. 通过代码渲染图像

图1代码渲染生成的图像如图2所示,这是rect元素,浏览器会在x, y (100, 100)(即宽度和高度)位置渲染一个红色矩形。

0x02 使用SVG的攻击场景

虽然SVG提供了较大的灵活性,可以方便创建更多的动态web内容,但同时也引入了一些安全风险。在下文中,我们将讨论一些常见的攻击向量,我们在互联网上的一些主流站点上都观察到过这些攻击方式。

跨站脚本

我们可以通过脚本方式来访问并修改SVG文档的任何内容,这与HTML操作方式类似。默认的脚本语言为ECMAScript(与JavaScript密切相关),每个SVG元素及属性都对应已定义的DOM(Document Object Model,文档对象模型)对象。相关脚本被封装在<script>元素中。

这意味着如果web服务器允许用户上传任意SVG图像,就存在XSS(跨站脚本)安全风险。如下所示,我们将脚本存放在图像中:

图3. xss.svg代码片段

将该图像保存为xss.svg,然后直接打开,如下图所示:

图4. 直接访问该文件触发XSS

如果将该文件链接到某个HTML页面,访问该页面也可以触发,如下图所示:

图5. 通过链接文件触发XSS

JavaScript代码会在浏览器上下文中执行,这意味着攻击者可以使用该文件执行恶意行为,比如窃取用户隐私信息等。

HTML注入

在某些情况下,XSS payload会被服务端过滤,然而我们依然能够通过SVG图像的特定功能来注入HTML代码。如前文所述,SVG是基于XML的一种矢量图,因此我们无法简单将HTML内容放入其中,不然会破坏XML的语法。

为了避免这种情况,SVG提供了一个foreignObject元素,可以用来包含来自其他XML命名空间的元素。在浏览器上下文中,这部分数据很可能采用(X)HTML形式。

来看一下html.svg图像:

图6. html.svg代码片段

当我们在foreignObject内添加一个body标签以及XHTML命名空间时,可以使用xmlns属性来声明命名空间。采用这种方式,浏览器会将body标签及其所有子标签解析为属于XHTML的元素。因此,我们可以将来自SVG的任意XHTML代码渲染到页面中:

图7. HTML注入漏洞

这种方式可以运行任意HTML代码,意味着我们可以简单从SVG图像中发起类似钓鱼、绕过同源策略、CSRF之类的攻击。

XML实体:Billion Laughs Attack

由于SVG是基于XML的矢量图,因此可以支持Entity(实体)功能。Entity可以用来定义特殊字符的快捷方式,也可以声明成内部或外部实体。

我们可以通过如下方式声明内部Entity:

<!ENTITY entity-name "entity-value">

通过如下方式声明外部Entity:

<!ENTITY entity-name SYSTEM "URI/URL">

如果解析文件的XML解析器存在脆弱性,那么我们就可以滥用外部Entity功能来泄露内部数据。由于现在大家主要使用的都是现代浏览器,因此我们假设可用的解析器都经过fuzzer的严格测试,因此没那么容易被攻击。在这个前提下,这里我们主要讨论如何滥用内部Entity。

entity.svg的内部实现如下所示:

图8. entity.svg代码片段

如上图所示,我们在第2行定义lab这个Entity,然后在SVG元素中调用该实体。结果如图9所示:

图9. lab实体被加载到页面

一切非常顺利,来尝试另一个例子:entity_2.svg,如下图所示:

图10. entity_2.svg代码片段

结果如下:

图11. lab2实体被加载到页面

如上图所示,这里的文本内容被重复渲染,这表明我们可以使用Entity标签发起“ Billion Laughs ”攻击。

“ Billion Laughs ”攻击是一种DoS(拒绝服务)攻击,目标是XML文档解析器。这种攻击也被称之为XML炸弹或者指数实体攻击。

图12. billion_laughs.svg代码片段

我们的浏览器在解析这个 billion_laughs.svg数据时,只花了4~5秒就能正常响应。这是因为大多数现代浏览器已经能够能应付这种攻击,可以在渲染过程中解决该问题,因此不会造成安全风险。

拒绝服务:新型SVG “Billion Laughs”攻击

在上一节中,我们发现“ Billion Laughs ”攻击可以延缓浏览器的处理速度,浏览器需要4~5秒才能应付该攻击。不幸的是,攻击者还可以通过SVG图像,发起另一种“ Billion Laughs ”攻击,绕过这些防御措施。

这一次我们使用xlink:href来代替XML Entity。来看一下 xlink_laughs.svg所使用的payload:

图13. xlink_laughs.svg代码片段

xlink:href属性以IRI(国际资源标识)方式定义了对某个资源的引用,该链接的具体含义需根据使用该链接的每个元素的上下文来决定。

<use>元素从SVG文档中获取节点,然后将其复制到其他位置。

我们现在a0中定义circle元素,然后在a1、a2、a3……中通过xlink:href属性调用<use>元素,通过这种方式反复克隆circle。结果如下图所示:

图14. 在解析恶意SVG时,通过xlink:href发起“ Billion Laugh”攻击

需要注意的是,在最坏的情况下,大多数现代浏览器在尝试解析网站上的这张SVG图像时可能会发生崩溃,或者至少会出现无响应情况。

有趣的是,我们在测试某些开源SVG/XML过滤器时,发现这些过滤器并不能正确捕捉到图13所示的SVG图像。因此,这种错误格式的SVG图像也可能造成DoS效果。

0x03 总结

SVG图像更像HTML,而不单单是一张简单的图像。因此,我们建议web开发者尽可能不要以对象或者iframe形式加载任何SVG。Web管理员同样应当限制可以上传到站点的文件类型。

此外,任何不可信的SVG图像在被上传到服务端前都必须经过过滤处理,可以采取如下操作:

  • 限制危险标签,比如script、foreignObject等。
  • 限制通过SVG图像的外部链接加载资源。
  • 限制SVG图像内的扩展逻辑。

我们使用一些浏览器来直接打开这些恶意SVG文件,对比结果如下图所示:

大家可以访问我们的Github仓库下载本文使用的SVG样本。

0x04 参考资料

[1] W3C, “Scalable Vector Graphics” https://www.w3.org/TR/SVG2/ (02 September, 2019)
[2] OWASP, “The Image that called me” https://www.owasp.org/images/0/03/Mario_Heiderich_OWASP_Sweden_The_image_that_called_me.pdf (02 September, 2019)
[3] Blackhat, “Exploiting Browsers without Image Parsing Bugs” https://www.blackhat.com/docs/us-14/materials/us-14-DeGraaf-SVG-Exploiting-Browsers-Without-Image-Parsing-Bugs.pdf (02 September, 2019)

原文链接:https://www.anquanke.com/post/id/190651