Лучший способ обеспечить безопасность и избежать XSS с введенными пользователем URL-адресами
-
03-07-2019 - |
Вопрос
У нас есть приложение с высоким уровнем безопасности, и мы хотим, чтобы пользователи могли вводить URL-адреса, которые увидят другие пользователи.
Это создает высокий риск взлома XSS — пользователь потенциально может ввести JavaScript, который в конечном итоге выполнит другой пользователь.Поскольку мы храним конфиденциальные данные, важно, чтобы этого никогда не произошло.
Каковы наилучшие методы борьбы с этим?Достаточно ли одного белого списка безопасности или шаблона побега?
Любые советы по работе с перенаправлениями (например, сообщение «эта ссылка выходит за пределы нашего сайта» на странице с предупреждением перед переходом по ссылке)
Есть ли аргумент в пользу того, чтобы вообще не поддерживать ссылки, вводимые пользователем?
Уточнение:
В основном наши пользователи хотят ввести:
stackoverflow.com
И выведите его другому пользователю:
<a href="http://stackoverflow.com">stackoverflow.com</a>
Что меня действительно беспокоит, так это то, что они используют это для взлома XSS.Т.е.они вводят:
alert('взломали!');
Таким образом, другие пользователи получают эту ссылку:
<a href="alert('hacked!');">stackoverflow.com</a>
Мой пример предназначен только для того, чтобы объяснить риск: я прекрасно понимаю, что javascript и URL-адреса — это разные вещи, но, позволив им ввести последнее, они смогут выполнить первое.
Вы будете удивлены, сколько сайтов можно взломать с помощью этого трюка — HTML еще хуже.Если они знают, что нужно делать со ссылками, умеют ли они также очищать <iframe>
, <img>
и умные ссылки на CSS?
Я работаю в среде с высоким уровнем безопасности — один взлом XSS может привести к очень большим потерям для нас.Я рад, что смог создать регулярное выражение (или использовать одно из прекрасных предложений на данный момент), которое могло бы исключить все, о чем я мог подумать, но будет ли этого достаточно?
Решение
Если вы считаете, что URL-адреса не могут содержать код, подумайте еще раз!
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
Прочтите это и заплачьте.
Вот как мы это делаем при переполнении стека:
/// <summary>
/// returns "safe" URL, stripping anything outside normal charsets for URL
/// </summary>
public static string SanitizeUrl(string url)
{
return Regex.Replace(url, @"[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]", "");
}
Другие советы
Процесс рендеринга ссылки «безопасной» должен проходить в три-четыре этапа:
- Отмените экранирование/перекодирование полученной строки (RSnake задокументировал ряд трюков на странице http://ha.ckers.org/xss.html которые используют экранирование и кодировки UTF).
- Очистите ссылку:Регулярные выражения — хорошее начало — обязательно обрежьте строку или выбросьте ее, если она содержит « (или что-то еще, что вы используете для закрытия атрибутов в выводе);Если вы делаете ссылки только как ссылки на другую информацию, вы также можете принудительно указать протокол в конце этого процесса — если часть перед первым двоеточием не «http» или «https», тогда добавьте «http://». к началу.Это позволяет вам создавать полезные ссылки из неполного ввода, который пользователь вводит в браузер, и дает вам последний шанс спровоцировать любое зло, которое кто-то пытался прокрасться.
- Убедитесь, что результатом является правильно сформированный URL-адрес (протокол://хост.домен[:порт][/путь][/[файл]][?queryField=queryValue][#anchor]).
- Возможно, проверьте результат по черному списку сайтов или попытайтесь получить его с помощью какой-либо программы проверки на наличие вредоносных программ.
Если безопасность является приоритетом, я надеюсь, что пользователи простят некоторую паранойю в этом процессе, даже если в конечном итоге некоторые безопасные ссылки будут потеряны.
Используйте библиотеку, например OWASP-ESAPI API:
- PHP- http://code.google.com/p/owasp-esapi-php/
- Джава - http://code.google.com/p/owasp-esapi-java/
- .СЕТЬ - http://code.google.com/p/owasp-esapi-dotnet/
- Питон - http://code.google.com/p/owasp-esapi-python/
Прочтите следующее:
- https://www.golemtechnologies.com/articles/prevent-xss#how-to-prevent-cross-site-scripting
- https://www.owasp.org/
- http://www.secbytes.com/blog/?p=253
Например:
$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
$esapi = new ESAPI( "/etc/php5/esapi/ESAPI.xml" ); // Modified copy of ESAPI.xml
$sanitizer = ESAPI::getSanitizer();
$sanitized_url = $sanitizer->getSanitizedURL( "user-homepage", $url );
Другой пример — использование встроенной функции.PHP filter_var функция является примером:
$url = "http://stackoverflow.com"; // e.g., $_GET["user-homepage"];
$sanitized_url = filter_var($url, FILTER_SANITIZE_URL);
С использованием filter_var
позволяет вызовы javascript и отфильтровывает схемы, которые не являются ни http
ни https
.Используя Дезинфицирующее средство OWASP ESAPI вероятно, это лучший вариант.
Еще одним примером является код из WordPress:
Кроме того, поскольку невозможно узнать, куда ведет URL-адрес (т. е. это может быть действительный URL-адрес, но содержимое URL-адреса может быть вредоносным), у Google есть безопасный просмотр API, который вы можете вызвать:
Создание собственного регулярного выражения для очистки проблематично по нескольким причинам:
- Если вы не Джон Скит, в коде будут ошибки.
- Существующие API требуют многих часов проверки и тестирования.
- Существующие API проверки URL учитывают интернационализацию.
- Существующие API будут обновляться в соответствии с новыми стандартами.
Другие вопросы, которые следует учитывать:
- Какие схемы вы разрешаете (являются ли
file:///
иtelnet://
приемлемый)? - Какие ограничения вы хотите наложить на содержимое URL-адреса (допустимы ли URL-адреса вредоносного ПО)?
Просто закодируйте ссылки в HTML-коде при их выводе.Убедитесь, что вы не позволяете javascript:
ссылки.(Лучше всего иметь белый список принимаемых протоколов, например http, https и mailto.)
Вы не указываете язык своего приложения, тогда я буду предполагать ASP.NET, и для этого вы можете использовать Библиотека Microsoft для защиты от межсайтовых сценариев
Он очень прост в использовании, все, что вам нужно, это включить и все :)
Раз уж вы по теме, почему бы не почитать Рекомендации по проектированию безопасных веб-приложений
Если какой-либо другой язык....если есть библиотека для ASP.NET, она должна быть доступна и для других языков (PHP, Python, ROR и т. д.)
Как насчет того, чтобы не отображать их в виде ссылки?Просто используйте текст.
В сочетании с предупреждением действовать на свой страх и риск может быть достаточно.
добавление - смотрите также Должен ли я очищать HTML-разметку для размещенной CMS? для обсуждения очистки пользовательского ввода
В моем проекте, написанном на JavaScript, я использую это регулярное выражение в качестве белого списка:
url.match(/^((https?|ftp):\/\/|\.{0,2}\/)/)
Единственное ограничение заключается в том, что вам нужно поставить ./ впереди для файлов в том же каталоге, но я думаю, что смогу с этим смириться.
Для питонистов попробуйте Scrapy's w3lib.
OWASP ESAPI предшествует Python 2.7. и хранится в архиве ныне несуществующий Google Code.
Вы можете использовать шестнадцатеричный код, чтобы преобразовать весь URL-адрес и отправить его на свой сервер.Таким образом, клиент не поймет содержание с первого взгляда.После прочтения содержимого вы можете расшифровать URL-адрес содержимого = ?и отправить его в браузер.
Разрешение URL-адреса и разрешение JavaScript — это две разные вещи.