1. Главная страница » Компьютеры

Asp net core redirect

Автор: | 16.12.2019

I’m making a Action method in a controller like following.

In Model

In Controller

And I access ActionMethod2 with /Controller/ActionMethod2 in browser. I expected /Controller/ActionMethod1 will be called and its model value has value which is sent by ActionMethod2 .

But if I debug it, 1) debuger do not stop at debug point (2) and at debug point (1) the value has no value, i.e value.modelStr == null .

How do value at debug point (1) get a value from ActionMethod2 ?

2 Answers 2

The parameter value of ActionMethod1 is type of Model class, this is a complex type, mvc will try to bind it’s value from http body, the http request should be a POST request.

But ActionMethod2 returns a RedirectToAction result, the browser redirect to ActionMethod1 with GET , and can not handle by ActionMethod1 .

The answer is add FromQueryAttribute to the parameter value of ActionMethod1 , tells mvc that value is bind from query string, like this:

Now ActionMethod1 will handle GET request, and ActionMethod2 can redirect to it.

Если веб-приложение перенаправляет пользователя на URL-адрес, указанный по запросу, например в строке запроса или через данные формы, этот URL-адрес может быть подделан и вести на внешний вредоносный сайт. A web app that redirects to a URL that’s specified via the request such as the querystring or form data can potentially be tampered with to redirect users to an external, malicious URL. Такое изменение данных называется атакой открытого перенаправления. This tampering is called an open redirection attack.

Каждый раз, когда логика вашего приложения выполняет перенаправление на определенный URL-адрес, нужно убедиться, что этот адрес не был изменен. Whenever your application logic redirects to a specified URL, you must verify that the redirection URL hasn’t been tampered with. ASP.NET Core содержит встроенные функциональные возможности, помогающие защитить приложения от атак методом открытого перенаправления/переадресации. ASP.NET Core has built-in functionality to help protect apps from open redirect (also known as open redirection) attacks.

Что такое атака открытого перенаправления What is an open redirect attack?

Веб-приложения часто перенаправляют пользователей на страницу входа при доступе к ресурсам, требующим проверки подлинности. Web applications frequently redirect users to a login page when they access resources that require authentication. Перенаправление обычно включает параметр строки запроса returnUrl , чтобы после успешной проверки подлинности пользователь был перенаправлен на первоначально запрошенный URL-адрес. The redirection typically includes a returnUrl querystring parameter so that the user can be returned to the originally requested URL after they have successfully logged in. После проверки подлинности пользователя, он будет перенаправлен на URL-адрес, который запрошен изначально. After the user authenticates, they’re redirected to the URL they had originally requested.

Поскольку конечный URL-адрес указан в строке запроса, злоумышленник может незаконно изменить ее. Because the destination URL is specified in the querystring of the request, a malicious user could tamper with the querystring. Измененный запрос позволит сайту перенаправить пользователя на внешний вредоносный сайт. A tampered querystring could allow the site to redirect the user to an external, malicious site. Этот прием называется атакой открытого перенаправления. This technique is called an open redirect (or redirection) attack.

Пример атаки An example attack

Злоумышленник может разработать атаку, которая позволит ему получить доступ к учетным или конфиденциальным данным пользователя. A malicious user can develop an attack intended to allow the malicious user access to a user’s credentials or sensitive information. Чтобы начать атаку, злоумышленник убеждает пользователя щелкнуть ссылку на страницу авторизации вашего сайта, добавляя в URL-адрес значение строки запроса returnUrl . To begin the attack, the malicious user convinces the user to click a link to your site’s login page with a returnUrl querystring value added to the URL. Например, рассмотрим приложение на сайте contoso.com со страницей входа http://contoso.com/Account/LogOn?returnUrl=/Home/About . For example, consider an app at contoso.com that includes a login page at http://contoso.com/Account/LogOn?returnUrl=/Home/About . Атака включает следующие шаги: The attack follows these steps:

  1. Пользователь нажмет на http://contoso.com/Account/LogOn?returnUrl=http://contoso1.com/Account/LogOn (второй URL-адрес является «contoso1.com», не «contoso.com»). The user clicks a malicious link to http://contoso.com/Account/LogOn?returnUrl=http://contoso1.com/Account/LogOn (the second URL is "contoso1.com", not "contoso.com").
  2. Пользователь успешно вошел. The user logs in successfully.
  3. Сайт перенаправляет пользователя на http://contoso1.com/Account/LogOn (вредоносный сайт, который выглядит как настоящий). The user is redirected (by the site) to http://contoso1.com/Account/LogOn (a malicious site that looks exactly like real site).
  4. Пользователь пытается войти еще раз (предоставляя вредоносному сайту свои учетные данные) и перенаправляется на настоящий сайт. The user logs in again (giving malicious site their credentials) and is redirected back to the real site.

Пользователь скорее всего думает, что ему просто не удалось войти с первой попытки, и не подозревает, The user likely believes that their first attempt to log in failed and that their second attempt is successful. что его учетные данные скомпрометированы. The user most likely remains unaware that their credentials are compromised.

Помимо страниц для входа, некоторые сайты предоставляют страницы перенаправления или конечные точки. In addition to login pages, some sites provide redirect pages or endpoints. Предположим, у вашего приложения есть страница с открытым перенаправлением /Home/Redirect . Imagine your app has a page with an open redirect, /Home/Redirect . Злоумышленник может создать, например, ссылку в электронном письме, которая ведет на [yoursite]/Home/Redirect?url=http://phishingsite.com/Home/Login . An attacker could create, for example, a link in an email that goes to [yoursite]/Home/Redirect?url=http://phishingsite.com/Home/Login . Обычного пользователя будет проверять URL-адрес и увидеть, что он начинается с имени веб-сайта. A typical user will look at the URL and see it begins with your site name. Увидев, что этот URL-адрес начинается с названия вашего веб-сайта, обычный пользователь, ни о чем не подозревая, щелкнет ссылку. Trusting that, they will click the link. Открытое перенаправление затем переведет его на фишинговый сайт, который выглядит в точности как ваш, и пользователь, скорее всего, введет на нем свои учетные данные. The open redirect would then send the user to the phishing site, which looks identical to yours, and the user would likely login to what they believe is your site.

Защита от открытого перенаправления Protecting against open redirect attacks

При разработке веб-приложений следует считать все предоставляемые пользователями данные не заслуживающими доверия. When developing web applications, treat all user-provided data as untrustworthy. Если приложение содержит функции, перенаправляющие пользователя на основе содержимого URL-адреса, перенаправление должно осуществляться только локально внутри приложения (или строго на известный URL, а не на любой адрес в строке запроса). If your application has functionality that redirects the user based on the contents of the URL, ensure that such redirects are only done locally within your app (or to a known URL, not any URL that may be supplied in the querystring).

LocalRedirect LocalRedirect

Используйте LocalRedirect вспомогательный метод из базового Controller класса: Use the LocalRedirect helper method from the base Controller class:

LocalRedirect вызовет исключение, если указан URL-адрес, не являющейся локальным. LocalRedirect will throw an exception if a non-local URL is specified. В противном случае он ведет себя так же, как метод Redirect . Otherwise, it behaves just like the Redirect method.

IsLocalUrl IsLocalUrl

Используйте IsLocalUrl метод для проверки перед перенаправлением URL-адреса: Use the IsLocalUrl method to test URLs before redirecting:

В следующем примере показано, как проверить, является ли URL-адрес локальным, перед перенаправлением. The following example shows how to check whether a URL is local before redirecting.

Метод IsLocalUrl защищает пользователей от случайного перенаправления на вредоносный сайт. The IsLocalUrl method protects users from being inadvertently redirected to a malicious site. Рекомендуем фиксировать сведения об URL-адресе в ситуациях, когда вместо ожидаемого локального URL предоставляется нелокальный. You can log the details of the URL that was provided when a non-local URL is supplied in a situation where you expected a local URL. Это поможет в диагностике использующих перенаправление атак. Logging redirect URLs may help in diagnosing redirection attacks.

По встроенным механизмам безопасности ASP .NET Core написано мало статей. Даже официальная документация имеет пробелы. В этой статье мы пройдём по всем основным компонентам, имеющим отношение к безопасности, и разберём, как это работает внутри.

Если вы используете старый добрый ASP .NET, то для вас будет полезна информация по внутреннему устройству компонентов безопасности и лучшим практикам их использования. Здесь вы найдёте ответы на следующие вопросы: как реализованы современные анти-XSS механизмы и как их правильно использовать в ASP .NET Core? Как правильно работать с cookies и какие подводные камни там могут встретиться? Как был переписан механизм защиты от CSRF? Как правильно работать с криптографическими алгоритмами? Кроме того, рассказывается про опыт участия в Bug Bounty по поиску уязвимостей в ASP .NET Core.

Перед чтением рекомендуется освежить в памяти атаки из списка OWASP Top 10.

Прототипом статьи является доклад Михаила Щербакова на конференции DotNext 2017 Moscow. Михаил — Microsoft .NET MVP, участник .NET Core Bug Bounty Program, соорганизатор сообщества .NET программистов (Московское комьюнити называется MskDotNet, питерское — SpbDotNet). По работе последние 5 лет занимается безопасностью. Работал в Positive Technologies, в Cezurity, сейчас как консультант работает напрямую с заказчиками, по большей части в этой же сфере. Профессиональные интересы: статический и динамический анализ кода, информационная безопасность, автоматизация отладки кода, исследование внутреннего устройства .NET CLR.

В этом тексте огромное количество картинок со слайдов. Осторожно, трафик!

В этой статье мы поговорим про атаки и механизмы защиты, а именно про Open Redirect, про изменения в Crypto API в .NET Core, про XSS и Client-side атаки, про настройку CSP, CSRF, CORS и вообще про правильные паттерны использования cookies.

У Microsoft сейчас открыта бессрочная Bug Bounty программа, и я в ней участвую. Если кто-то из вас интересуется и занимается безопасностью, вы можете поискать уязвимости в .NET-платформе, отправить им report. У них приятное вознаграждение, где-то в среднем 5- 10 тысяч они готовы платить за найденную верифицированную уязвимость. И это приятно, что Microsoft сейчас вкладывает довольно большие усилия в безопасность .NET-платформы и .NET Core в частности.

Начнем с предотвращения атаки Open Redirect. Я думаю, многие про него знают, но не знают, что именно это называется Open Redirect. Давайте посмотрим на демку. Я думаю, большинство из вас сходу поймут, в чём заключается атака.

Итак, у нас есть некий сайт, который написан на ASP.NET, он называется my-telegram.com, у нас есть некий злоумышленник, который составляет следующий url на форму логина. Это совершенно стандартная ASP.NET форма логина. Атакующий отправляет эту ссылку жертве и каким-то образом заставляет по этой ссылке перейти.

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

«Что-то пошло не так, введите заново пароль и логин». Обычная реакция — «наверное, я где-то неправильно что-то ввел», и пользователь повторяет ввод. Но если вы обратили внимание, в верхней строчке уже не my-telegram, а my-telergam, небольшая игра с символами. Что произошло? Первая форма логина на доверенном сайте совершенно нормально залогинила пользователя на этом сайте, дальше был редирект. А в редиректе был url вот на этот сайт. Если мы не проверяем url в редиректе, то он вполне себе валидно отправляет нас на другой сайт, где уже с помощью некой социальной инженерии заставляет нас повторно ввести логин и пароль, которые уходят на сайт атакующего, и дальше атакующий уже может с этим работать.

Как это предотвратить? У ASP.NET в контроллере есть метод, LocalRedirect, я думаю, все его видели, он как раз защищает от таких случаев, проверяет, что у вас не абсолютный путь, что он относительный и может редиректить только на этот сайт.

Либо вы можете сами написать реализацию, если хотите, чтобы она по дефолту, когда сайт неверный, не выбрасывала исключения, а просто редиректила на home-страничку. Это вся защита от этой атаки. Теперь вы все знаете, что такое Open Redirect.

В этом году OWASP собирал свою статистику, по ссылке на GitHub можно посмотреть. При всей простоте защиты, Open Redirect стоит на третьем месте по популярности в мире.

С этой же атаки началось мое участие в Bug Bounty. Мой первый репорт, который был пофиксен и оплачен, был как раз про обход встроенного механизма Open redirect. Но сейчас там все нормально, он пофиксен. LocalRedirect действительно защищает на 100% от возможного редиректа на сторонний сайт.

Следующее, про что хотелось бы поговорить, — это Data Protection. В Crypto API были огромные изменения в .NET Core. По сути, всё API было полностью переписано, поэтому давайте быстро пройдемся по основным моментам и посмотрим, что поменялось.

Во-первых, отказались от использования Machine Keys. Machine Keys раньше являлся master key для всей криптографии. С этим было много проблем, особенно в распределенной системе, вам нужно было сочинять какое-то свое хранилище ключей, чтобы то, что зашифровала одна нода, было возможно расшифровать другой нодой. Также не было нормальной возможности отозвать, например, зашифрованные cookies. Вам нужно было бы менять Machine Keys. Было очень много всяких неудобств. Сейчас от этого отказались, сделали нормальные высокоуровневые API из коробки. Раньше System.Security.Cryptography представляла из себя некий набор инструментов, используя которые очень легко было сделать ошибку.

Частый правильный кейс — использовать некую стороннюю библиотеку, которая уже предоставляет высокоуровневые API, и вам не нужно заботиться обо всех нюансах. Сейчас это есть в .NET Core из коробки. Есть хранилище ключей из коробки: вы можете сконфигурировать какое-то удаленное хранилище, где у вас будут лежать все ключики, и все ноды будут туда за ними ходить. Оно легко расширяется, вы можете использовать как уже существующие в Redis или в Azure, так и написать своё. Поддерживается ротация ключей, раз в 90 дней ключик меняется, и для создания нового шифротекста уже будет использоваться новый ключ, а старый — только для расшифровки старого. Также предоставляется изоляция подсистем из коробки. Можно кастомизировать, то есть использовать свои кастомные алгоритмы шифрования, чуть позже я покажу пример.

Итак, как выглядит новый Crypto API?

Довольно-таки примитивно, легко, так как у нас есть DI в .NET Core, вы можете просто в конструктор контроллера передать IDataProtectionProvider, создать из него протектор и использовать метод Protect и Unprotect для шифровки и расшифровки. Всё, больше вам ни о чем заботиться не нужно. И еще один параметр, на котором я ещё хотел остановиться, — это как раз та самая изоляция на уровне протекторов, где каждый протектор с разными строковыми идентификаторами может расшифровывать данные, которые только он зашифровал. Если вы хотите шифровать данные для разных пользователей и быть уверенным, что они не смогут чьи-то чужие зашифрованные данные расшифровать в своём аккаунте, то это удобная фича, которая доступна из коробки.

Есть еще такая вот вишенка:

Вы можете использовать time-limited протектор для создания токенов. Когда вам нужно определить время жизни вашего ключа, например, токена, вы просто его шифруете time-limited протектором, определяете его время жизни, и при расшифровке, если это время истекло, вы просто получите эксепшн.
Следующий момент — хранение паролей. Как все знают, в открытом виде мы пароли не храним никогда, вопрос, как сделать это правильно. Опять же, у нас есть механизм в .NET Core, паттерн для правильного создания хэшей:

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

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

Можете кастомизировать алгоритмы шифрования, которые вы хотите использовать. По умолчанию будет использована AES-256 с дополнением CBC. Это блочные алгоритмы шифрования, и без дополнительной подписи они уязвимы к атакам Padding Oracle. Эта проблема была как раз в .NET в большом фреймворке из-за неправильного использования System.Security.Cryptography. Здесь же из коробки шифротекст будет подписан еще хэшом, и в этой ситуации Padding Oracle невозможен, так что можете об этом не думать. Есть еще нюанс: каждый шифротекст будет иметь заголовок, который состоит из 32-битного magic header, следом за которым идет айдишник ключа. Это иногда бывает полезно для отладки, когда вы хотите понять, каким ключом был зашифрован текст. Вы просто смотрите на первые 20 байт и видите, одинаковыми или разными ключами они зашифрованы в зависимости от того, одинаковые или разные эти хедеры.

Перейдем к большой части, посвященной Client-side уязвимостям. Начнем с XSS. Все знают, что такое XSS. Но всё равно начнем с самых азов, потому что понимание, как работает в браузере Same-origin policy (SOP) очень важно для полного понимания атак на Client-side. Рассмотрим вот такой кейс:

У нас есть браузер, в одной вкладке открыт сайт foo-example с JavaScript-кодом, который выполняет GET-запрос на другой домен. Есть другой сайт по этому домену bar.other, который у нас возвращает Json на этот запрос, какие-то цены на продукты. И вот вопрос — отправит ли браузер этот запрос? В этом случае выглядит логично, что хорошо бы отправить этот запрос и получить ответ. Какая проблема с этим есть?

Если в нашем примере мы просто поменяем сайты, и вместо провайдера данных у нас какой-то mail.google, а здесь у нас какой-то сайт атакующего, который атакующий заставил нас открыть в своем браузере, то если бы этот запрос был отправлен и ответ получен, атакующий бы получил данные из нашего почтовый ящика, что плохо. Поэтому и существует Same-origin policy, который предотвращает чтение данных в подобном случае. А правильный ответ на мой изначальный вопрос, отправит ли браузер запрос — да, отправит. Браузер отправляет POST/GET-запросы в этой ситуации, но не позволяет JavaScript прочитать ответ этого запроса, поэтому утечки данных здесь произойти не может из-за Same-origin policy. Но на самом деле запросы будут отправлены, это будет важно для понимания других Client-side атак.

Что же такое вообще Same-origin policy? Это некие ограничения, которые накладываются на загруженный документ или скрипт из одного источника на взаимодействие с ресурсами из другого источника.

Что же такое источник, что такое origin? Origin представляет из себя набор схемы http, https либо какой-то другой, домена и порта. То есть скрипт, выполняющийся на одном домене, на одном Origin с портом и схемой, не может получить данные с другого Origin без каких-то дополнительных действий. Как атакующий может всё-таки получить данные, какие атаки на Client-side существуют?

Первая — это XSS, с которой мы начали. Суть атаки — если мы не можем с другого Origin получить данные, то давайте наш скрипт заинжектим прямо в Origin сайта, сделаем инъекцию нашего вредоносного скрипта на доверенную веб-страницу, и тогда из Origin мы уже можем делать запрос внутри этого Origin и получать данные страницы. Это суть XSS.

При всей известности и простоте это остается самой популярной атакой в мире. Она является очень хорошей точкой входа для других атак. Существует много атак, которые можно развернуть, начиная с XSS. Она является общеизвестной, при этом очень много проектов, где разработчики недостаточно используют встроенные средства защиты от XSS. И вообще не придают ей серьезное значение.
Давайте посмотрим, что у нас есть в ASP.NET, чтобы правильно построить защиту от этого вида атак. Возьмем два таких синтетических примера варианта XSS:

Первый вариант: у нас есть некий скрипт, у него есть source, в source вставлен какой-то путь. Если атакующий может манипулировать этим путем (загрузить свой source) или заинжектить всю эту строчку в документ, соответственно, он заинжектит свой скрипт. Это и есть XSS-атака.

Второй вариант — когда у нас фигурирует не параметр скрипта, а атакующий может в какой-то тег html заинжектить свой код, например, напрямую в

Читайте также:  Fps frames per second

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *