Нужно ли включать канонизацию при использовании OWASP ESAPI?

Мы добавляем ESAPI 2.x (библиотека безопасности owasp java) в приложение.

Изменение легко, хотя и довольно повторяющееся. Мы добавляем проверки ко всем входным параметрам, чтобы убедиться, что все символы, из которых они состоят, находятся в белом списке.

Это оно:

Validator instance = ESAPI.validator();
Assert.assertTrue(instance.isValidInput("test", "[email protected]", "Email", 100, false));

Затем шаблоны электронной почты устанавливаются в файле validation.properties, например:

Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$

Легкий!

Мы не кодируем вывод, учитывая, что после проверки ввода данные становятся доверенными.

Я вижу в ESAPI, что у него есть флаг для канонизации входной строки. Я понимаю, что канонизация - это "декодирование", поэтому любая закодированная строка преобразуется в обычный текст.

Вопрос в том. Зачем нам канонизировать?

Может ли кто-нибудь показать пример атаки, которую можно предотвратить с помощью канонизации?? (в джаве)

Спасибо!


person Diego Lopez    schedule 27.10.2014    source источник
comment
Мы не кодируем вывод, учитывая, что после проверки ввода данные становятся доверенными. неееет!!! Вы должны всегда избегать вывода. Источник может быть где-то кроме входа. Это касается как правильности, так и безопасности   -  person artbristol    schedule 27.10.2014
comment
-1: Данные НИКОГДА не становятся доверенными, если их источником является пользователь. см.: owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet   -  person avgvstvs    schedule 30.10.2014
comment
Я бы сказал, что вопрос не заслуживает негатива! По крайней мере, это вызвало некоторую дискуссию, так что, похоже, было о чем спросить. Данные BTW всегда всегда исходят от пользователя. Он стал доверенным, когда был должным образом проверен. Это, собственно, и говорит сам OWASP: используйте белый список.   -  person Diego Lopez    schedule 31.10.2014
comment
Ты прав. Более того, Adobe говорит об этом в своих рекомендациях по безопасности (библиотека XSSAPI): Разрешить все входные данные — кодировать все выходные данные. Преимущество этой стратегии в том, что разработчику очень легко ее запомнить и очень легко проверить.   -  person Diego Lopez    schedule 14.12.2014
comment
Отрицательным было отметить это для начинающих разработчиков, и, по-видимому, новые правила SO не позволяют мне изменить свой голос. Фильтрация XSS подходит, но только как еще один уровень защиты. Нет ничего плохого в том, чтобы заставить злоумышленника работать на обед!   -  person avgvstvs    schedule 14.12.2014
comment
Если вы отредактируете свой пост, я могу удалить свой минус.   -  person avgvstvs    schedule 04.05.2015


Ответы (2)


Вот один (из нескольких тысяч возможных примеров):

Возьмите этот простой ввод XSS:

<script>alert('XSS');</script>
//Now we URI encode it:
%3Cscript%3Ealert(%27XSS%27)%3B%3C%2Fscript%3E

//Now we URI encode it again:

%253Cscript%253Ealert(%2527XSS%2527)%253B%253C%252Fscript%253E

Канонизация ввода, который был закодирован один раз, приведет к исходному вводу, но в случае ESAPI третий ввод вызовет IntrusionException, потому что НИКОГДА не существует допустимого варианта использования, когда пользовательский ввод будет закодирован в URI более одного раза. В этом конкретном примере канонизация означает, что «все данные URI будут преобразованы в их фактическое символьное представление». Кстати, ESAPI делает больше, чем просто декодирует URI. Это важно, если вы хотите выполнять как проверку безопасности, так и/или бизнес-проверку, используя регулярные выражения — основное использование регулярных выражений в большинстве приложений.

Как минимум, канонизация дает вам уверенность в том, что скрытно ввести вредоносные данные в приложение непросто: цель состоит в том, чтобы ограничиться заведомо правильными значениями (белый список) и отклонить все остальное.

Что касается вашего опрометчивого комментария здесь:

We are not encoding output given that after the input validation, data becomes trusted.

Вот грязная правда: Javascript, XML, JSON и HTML не являются «обычными языками». Они недетерминированы. На практике это означает, что математически невозможно написать регулярное выражение для отклонения всех попыток вставки HTML или Javascript в ваше приложение. Посмотрите на шпаргалку по уклонению от XSS-фильтра, которую я разместил выше.

Ваше приложение использует jquery? Следующий ввод является вредоносным:

$=''|'',_=$+!"",__=_+_,___=__+_,($)[_$=($$=(_$=""+{})[__+__+_])+_$[_]+(""+_$[-__])[_]+(""+!_)[___]+($_=(_$=""+!$)[$])+_$[_]+_$[__]+$$+$_+(""+{})[_]+_$[_]][_$]((_$=""+!_)[_]+_$[__]+_$[__+__]+(_$=""+!$)[_]+_$[$]+"("+_+")")()

Таким образом, вы должны кодировать все данные при выводе пользователю, для надлежащего контекста это означает, что если часть данных будет сначала вводиться в функцию javascript, а затем отображается как HTML, вы кодируете для Javascript, а затем HTML. Если он выводится в поле данных HTML (например, поле ввода по умолчанию), вы кодируете его для атрибута HTML.

На самом деле БОЛЕЕ ВАЖНО выполнять кодирование вывода, чем фильтрацию ввода для защиты от XSS. (Если бы я ДОЛЖЕН просто выбрать один...)

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

person avgvstvs    schedule 30.10.2014
comment
Большое спасибо за ваш комментарий! Обратите внимание, что мы используем не черный список, который, как вы сказали, абсолютно невозможно получить, а очень строгий белый список, в котором в основном разрешены только буквы (A..Za..z) и цифры (0..9) и несколько символов, таких как _ и -. - person Diego Lopez; 31.10.2014
comment
Помните, что в регулярном выражении Java [A-Za-z0-9]+ пропускает символы Юникода. Если вы мне не верите, попробуйте String foo = "\uff12"; и посмотрите, ускользнет ли оно. Если вы хотите заблокировать весь диапазон того, что может обрабатывать Java, вам нужно регулярное выражение "[\\p{Alnum}]{0-some_limit}". Вы должны использовать ESAPI.validator, которое по умолчанию использует регулярное выражение SafeString, указанное в validation.properties, хотя я думаю, что ИТ использует регулярное выражение "[\\p{L}\\p{N}]+", что немного менее эффективным. - person avgvstvs; 31.10.2014
comment
Небольшая корректировка: "[\\p{Alnum}]{0-1024}" и "[\\p{L}\\p{N}]{0-1024}" - person avgvstvs; 31.10.2014
comment
Прочитайте это. - person avgvstvs; 31.10.2014
comment
Обратите внимание, что tString foo = 2 интерпретируется только компилятором java. Он не интерпретируется, когда является параметром. - person Diego Lopez; 14.12.2014
comment
Возьмите тестовый пример Junit из этого вопроса и измените его, чтобы запустить регулярное выражение для всех \uxxxx строк. Я думаю, вы обнаружите, что ваше заявление здесь нуждается в пересмотре. - person avgvstvs; 14.12.2014
comment
А начиная с Java 1.7 вы можете написать свое регулярное выражение следующим образом, и оно будет применяться к символам Юникода: "(?u)[A-Za-z0-9]{0-1024}" Хотя в большинстве случаев я по-прежнему предпочитаю использовать исходный синтаксис. - person avgvstvs; 14.12.2014

Канонизация данных также связана с приведением данных к их базовой форме. Поэтому, если мы возьмем другой сценарий, в котором задействован путь к файлу (относительная/символическая ссылка) и связанное с ним разрешение каталога, нам нужно сначала канонизировать путь, а затем проверить, иначе это позволит кому-то исследовать эти файлы без разрешения, просто передав цель приемлемо данные.

person Shubhradeep    schedule 27.10.2014