Pull to refresh

Изменения в валидации финальной версии ASP.NET MVC 2

Reading time5 min
Views1.1K
и несколько вопросов безопасности, на которые стоит обратить внимание

imageБрэд Уилсон (Brad Wilson), один из разработчиков в группе ASP.NET MVC, сообщил в своем блоге о грядущих концептуальных изменениях, которые будут произведены в финальной версии ASP.NET MVC 2.

Речь идет о смене одной концепции валидации, отталкивающейся от полей формы, на другую – концепцию, в основе которой лежит модель данных. В этой статье я хотел бы рассказать, почему были внесены эти изменения и что они означают для разработчика.

Для демонстрации я хотел бы определить простую модель данных. Ради примера я выбрал упрощенную модель одной записи digg-подобного сервиса. В таких сервисах каждая запись – это текст ссылки на полезный ресурс в сети, плюс описание этой ссылки.
В статье я использую изображения для демонстрации кода. Это связано с тем, что статью я планирую размещать на нескольких ресурсах и тратить время на раскрашивание синтаксиса в каждом из них мне не хочется. Взамен, в конце статьи я прилагаю исходные коды в виде готового проекта.
Итак, класс Story.cs:

image

Здесь, кроме полей Url и Description, объявлены поля Id (идентификатор), Approved (флаг указывающий на то, что запись прошла модерацию) и CreateDate (дата создания записи). Атрибут Bind в данном случае указывает на то, что при связывании данных с экземпляром модели не нужно связывать значения Id.

Для демонстрации нам понадобится форма для ввода и поле для вывода результатов. Создадим следующую разметку:

image

Попробуем что-нибудь ввести и посмотрим на результат:

image

На первый взгляд все в порядке, за исключением того, что в нашем коде нет никакой валидации. Модифицируем класс модели данных с помощью атрибутов DataAnnotations для поддержки валидации:

image

Теперь, если мы попытаемся отправить с нашей формы пустые поля, мы получим ошибки валидации:

image

Пока все выглядит хорошо и красиво. Однако представьте себе такой вариант: поле для ввода описания не было добавлено в одном из вариантов формы при создании другой страницы другим разработчиком. Или, что более трагично, злоумышленник формирует и отправляет данные вообще без указания поля “Описание”. Как в этом случае поведет себя наше приложение?

Для демонстрации такой попытки отправить плохие данные я сформировал простой запрос, который содержит значение Url, но не значение Description. Результат запроса вы можете посмотреть ниже:

image

Как вы видите, Description равен null, однако модель данных считается валидной. В случае, если нет дополнительных проверок, этот запрос привел бы записи невалидной (согласно наших представлений) модели в базу данных.

Проблема


В чем же подвох? Дело в том, что валидация, которая работает в ASP.NET MVC 2 всех публично существующих на данный момент версий (последняя версия — RC) в своей работе отталкивается от значений формы. Иными словами, валидации подлежат только те поля, которые были переданы на сервер, остальные поля валидацию не проходят.

Проблема данного момента стоит в следующем: является или нет серверная валидация механизмом защиты от несанкционированного доступа или нет? До недавнего момента ответом по сути было – нет. Валидация являлась средством проверки пользовательского ввода на определенные условия.

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

Решение


Что же предлагается в замен? Выход состоит в том, чтобы изменить поведение валидации с зависимости от формы к зависимости от модели. То есть привести поведение к тому, что ожидается большинством разработчиков. В финальной версии ASP.NET MVC 2 именно это и будет сделано: валидация перестанет зависеть от переданных значений, но будет полностью зависеть от модели данных.

Так, злоумышленник не сможет навредить нам отправив неверно сформированный запрос, в котором отсутствуют данные. Если в модели определено, что данные требуются, то при связывании значений формы и экземпляра модели возникнет ошибка валидации и модель не будет валидной.

Детали или “не все так просто”


Есть несколько моментов в предстоящих нововведениях на которые необходимо обратить внимание.

Комплексные типы


Правила валидации вложенных комплексных объектов внутри модели будут влиять на валидацию только в том случае, когда на форме есть хотя бы одно поле из этого комплексного типа. Например, если в классе Person объявлено свойство типа Address, то правила валидации для Address будут применяться только если в запросе на сервер будет участвовать хотя бы одно из свойств Address.

Изменения в обработке атрибута Bind


В связи с изменениями механизма валидации, обработка атрибута Bind, который установлен для модели изменена. В финальной версии MVC 2 валидация будет производится для всех свойств модели, независимо от того, помещены ли свойства в список Excluded атрибута Bind или нет.

Ранее, задав в списке Excluded определенные поля можно было добиться частичной валидации модели. Отныне, это невозможно – проверяться на правила валидации будут все свойства.

Required для non-nullable типов


В связи с тем, что валидация будет отталкиваться от модели, то использование Required для non-nullable типов бесполезно. Невозможно определить было или не было передано значение из формы, так как value-тип имеет значение по-умолчанию.

Параметры как часть модели


Другая возможная проблема состоит в том, что разработчик может использовать в качестве параметров действия не строгую модель представления, но часть ее:

image

Здесь, редактирование записи осуществляется первоначальным связыванием одного параметра id. Затем из репозитория загружается существующая запись и производится попытка ее обновления. Проблема возникает тогда, когда данные отправленные на сервер не содержат всех необходимых значений. Например, то же самое поле “Описание” не заполнено. В представленном примере, валидация для поля Description не сработает ни в одном из мест выполнения кода и модель будет неверно сохранена.

Решением проблемы будет использование строго типа модели, вместо части ее. Тогда валидация сработает на этапе связывания параметров действия.

Передача лишних параметров


Еще одна проблема, которая может возникнуть при использовании валидации – это возможность для злоумышленника отправить значения таких полей модели, которые не должны быть отправлены на сервер. Это может быть значение Approved для нашей модели Story. Значение Approved для записи означает, что запись прошла модерацию, то есть это значение определяет параметр безопасности системы и доступ к нему должен быть явно ограничен.

Я отправил с нашей формы зловредный запрос, посмотрите на результат:

image

Вы можете видеть, что модель уже имеет установленное значение Approved = true, то есть злоумышленник потенциально преодолел механизм премодерации.

Чтобы избежать подобной ситуации необходимо внимательно относиться к механизму валидации и правильно планировать ваши модели. Например, для того, чтобы избежать подобного взлома премодерации необходимо в модели для атрибута Binв добавить в список Excluded значение Approved:

image

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

Заключение


В этой статье я рассмотрел нововведения для механизма валидации, которые будут произведены в финальной версии ASP.NET MVC 2. Кроме того, были затронуты вопросы безопасности при использовании связывания данных, валидации и отправки данных с формы.

Автоматическая валидация и связывание данных – это крайне полезные механизмы, которые могут значительно облегчить вашу жизнь. Но их использование налагает обязанности по соблюдению определенных правил безопасности, про которые не нужно забывать. Надеюсь, эта статья поможет вам строить безопасные сайты на ASP.NET MVC. Приятной разработки, коллеги!
Приложение: исходные коды из статьи

Progg it
Tags:
Hubs:
Total votes 32: ↑20 and ↓12+8
Comments9

Articles