Лучший способ обеспечить безопасность и избежать XSS с введенными пользователем URL-адресами

StackOverflow https://stackoverflow.com/questions/205923

Вопрос

У нас есть приложение с высоким уровнем безопасности, и мы хотим, чтобы пользователи могли вводить 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:

Прочтите следующее:

Например:

$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 — это две разные вещи.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top