Дмитрий Яковлев


Преобразование специальных символов в HTML-сущности для создания безопасного и корректного HTML в PowerShell

Часто, пользователи, работающие с PowerShell, пишущие свои сценарии для создания HTML-документов, в силу специфики работы, не учитывают правила безопасности, которые являются обязательными для веб-разработчиков.

Одно из таких правил – считать по умолчанию, что текстовые данные, включаемые в HTML-код, могут содержать управляющие символы, нарушающие структуру и отображение HTML-документа, а также вредоносный код, приводящий к XSS-атаке.

Если PHP-разработчикам для преобразования специальных символов доступна стандартная PHP-функция htmlspecialchars(), что могут использовать разработчики сценариев в PowerShell?

Для начала следует разобраться, какие именно символы и во что преобразовывать. Список этих символов такой:

  • & (амперсанд) => &;
  • < (меньше) => &lt;;
  • > (больше) => &gt;;
  • " (двойная кавычка) => &quot;;
  • ' (одинарная кавычка) => &#39;.

Следует иметь в виду, что замена одинарных кавычек требуется не всегда, но если текст выводится внутри атрибутов элементов HTML, будет безопаснее всегда прибегать к их замене.

Зная таблицу замены специальных символов, можно перейти к рассмотрению способов сделать вывод текста в HTML безопасным.

Ручная замена с оператором -Replace

Это первый способ, который сразу приходит на ум: если всё сводится к замене одних символов на другие, то используем -Replace.

$inputString = "<script>alert(`"You've been hacked, mister!`");</script>"
$safeHTML = $inputString -replace '&', '&amp;' -replace '<', '&lt;' -replace '>', '&gt;' -replace '"', '&quot;' -replace "'", '&#39;'
Write-Output "<code>$safeHTML</code>"

Применяя этот код, важно соблюсти последовательность замены: сначала заменяется символ & (амперсанд).

Преимущество использования оператора -Replace в том, что это решение не имеет зависимостей и будет работать всегда. Можно было бы остановиться, на этом, однако будет интересно рассмотреть и другие решения.

Использование метода [System.Net.WebUtility]::HtmlEncode()

Это кроссплатформенное решение, использующее метод .NET [System.Net.WebUtility]::HtmlEncode(), доступный в .NET Core 2.0 и новее.

$inputString = "<script>alert(`"You've been hacked, mister!`");</script>"
Write-Output "<code>$([System.Net.WebUtility]::HtmlEncode($inputString))</code>"

Класс System.Net.WebUtility предоставляет методы кодирования и декодирования URL-адресов при обработке веб-запросов. Доступные методы перечислены в официальной справке Microsoft, уверен, ознакомиться с ними будет полезно каждому разработчику сценариев PowerShell.

Оба рассмотренных решения гарантируют защиту от базовых XSS и корректное отображение данных в HTML-документе. Однако кроме перечисленных символов, метод [System.Net.WebUtility]::HtmlEncode() заменяет символы, выходящие за пределы ASCII 127.

На этом можно считать тему безопасного HTML в PowerShell закрытой, но я хочу рассмотреть ещё одно решение.

Использование метода [System.Web.HttpUtility]::HtmlEncode()

Использование этого метода приводится на сайте Microsoft в статье How to: Protect Against Script Exploits in a Web Application by Applying HTML Encoding to Strings, как рекомендованное решение для обеспечения безопасного вывода в веб-браузере при разработке ASP.NET веб-приложений.

Add-Type -AssemblyName System.Web
$inputString = "<script>alert(`"You've been hacked, mister Müller!`");</script>"
Write-Output "<code>$([System.Web.HttpUtility]::HtmlEncode($inputString))</code>"

Применение рассмотренных решений при разработке сценариев PowerShell, избавит от базовых проблем с безопасностью и с корректностью отображения данных в создаваемых HTML-документах.