Часто, пользователи, работающие с PowerShell, пишущие свои сценарии для создания HTML-документов, в силу специфики работы, не учитывают правила безопасности, которые являются обязательными для веб-разработчиков.
Одно из таких правил – считать по умолчанию, что текстовые данные, включаемые в HTML-код, могут содержать управляющие символы, нарушающие структуру и отображение HTML-документа, а также вредоносный код, приводящий к XSS-атаке.
Если PHP-разработчикам для преобразования специальных символов доступна стандартная PHP-функция htmlspecialchars(), что могут использовать разработчики сценариев в PowerShell?
Для начала следует разобраться, какие именно символы и во что преобразовывать. Список этих символов такой:
& (амперсанд) => &;< (меньше) => <;> (больше) => >;" (двойная кавычка) => ";' (одинарная кавычка) => '.
Следует иметь в виду, что замена одинарных кавычек требуется не всегда, но если текст выводится внутри атрибутов элементов HTML, будет безопаснее всегда прибегать к их замене.
Зная таблицу замены специальных символов, можно перейти к рассмотрению способов сделать вывод текста в HTML безопасным.
Ручная замена с оператором -Replace
Это первый способ, который сразу приходит на ум: если всё сводится к замене одних символов на другие, то используем -Replace.
$inputString = "<script>alert(`"You've been hacked, mister!`");</script>"
$safeHTML = $inputString -replace '&', '&' -replace '<', '<' -replace '>', '>' -replace '"', '"' -replace "'", '''
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-документах.