.NET Разработчик
6.53K subscribers
442 photos
3 videos
14 files
2.12K links
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#.

Для связи: @SBenzenko

Поддержать канал:
- https://boosty.to/netdeveloperdiary
- https://patreon.com/user?u=52551826
- https://pay.cloudtips.ru/p/70df3b3b
Download Telegram
День 1245. #Безопасность #СписокУязвимостей
Памятка по Уязвимостям в C# Приложениях. Продолжение
Начало

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

6. Неправильный контроль доступа
Проблема возникает, когда контроль доступа в приложении реализован неправильно и может быть обойдён злоумышленником. Проблемы обхода аутентификации, по сути, подмножество проблем контроля доступа. Однако помимо аутентификации, которая просит пользователя подтвердить свою личность («Кто вы?»), авторизация отвечает за вопрос: «Что разрешено делать этому пользователю?». Надлежащие аутентификация и авторизация вместе гарантируют, что пользователи не смогут получить доступ к функциям за пределами их разрешений.
Существует несколько способов настройки авторизации для пользователей: управление доступом на основе ролей или утверждений, списки контроля доступа и многое другое.

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

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

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

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

9. Уязвимости шифрования
Проблемы с шифрованием, вероятно, являются одной из самых серьёзных уязвимостей, которые могут возникнуть в приложении. Уязвимости шифрования относятся к случаям, когда шифрование и хеширование реализованы неправильно. Это может привести к массовым утечкам данных и обходу аутентификации из-за спуфинга сеанса, когда злоумышленник выдаёт себя за аутентифицированного пользователя, чтобы получить доступ к важным данным или информации.

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

Продолжение следует…

Источник:
https://dzone.com/articles/c-applications-vulnerability-cheatsheet
👍5
День 1251. #Безопасность #СписокУязвимостей
Памятка по Уязвимостям в C# Приложениях. Продолжение
Начало 1-4
Продолжение 5-9

10. Небезопасная конфигурация TLS и неправильная проверка сертификата
Помимо правильного шифрования информации в ваших хранилищах данных, вам также необходимо убедиться, что вы общаетесь с доверенным компьютером, а не со злоумышленником. TLS использует цифровые сертификаты в качестве основы для шифрования с открытым ключом, и вам необходимо проверить эти сертификаты, прежде чем устанавливать соединение с третьей стороной. Вы должны убедиться, что сервер, к которому вы пытаетесь подключиться, имеет сертификат, выданный доверенным центром сертификации (certificate authority - CA), и что ни один из сертификатов в цепочке не просрочен.

11. Массовое присвоение (оверпостинг)
Относится к практике присвоения значений нескольким переменным или свойствам объекта. Уязвимости массового присвоения возникают, когда приложение автоматически назначает пользовательский ввод нескольким переменным, объектам или свойствам. Это функция многих платформ приложений, предназначенная для упрощения разработки.

Однако эта функция иногда позволяет злоумышленникам перезаписывать, изменять или создавать новые переменные или свойства объекта по своему желанию. Это может привести к обходу аутентификации и манипулированию логикой программы. Чтобы предотвратить массовое присвоение, вы можете отключить эту функцию в используемой вами среде или использовать белый список, чтобы разрешить присвоение только для определённых свойств или переменных. Например, в ASP.NET можно использовать атрибут Bind на аргументе метода действия контроллера.

12. Отравление заголовка Host
Веб-серверы часто размещают несколько разных веб-сайтов на одном и том же IP-адресе. После того, как HTTP-запрос поступает на IP-адрес, сервер перенаправляет запрос на хост, указанный в заголовке Host. Хотя заголовки Host обычно устанавливаются браузером пользователя, они всё равно являются пользовательским вводом, и поэтому им нельзя доверять.

Если веб-приложение не проверяет заголовок Host перед его использованием для создания относительных адресов, злоумышленники могут запустить ряд атак, таких как XSS, подделка запросов на стороне сервера (SSRF) или атак с отравлением веб-кэша через заголовок Host. Например, если приложение использует заголовок Host для определения местоположения сценариев, злоумышленник может отправить вредоносный заголовок Host, чтобы приложение выполнило вредоносный сценарий:
var scriptURL = $"https://{Request.Host}/script.js";

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

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

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

Продолжение следует…

Источник:
https://dzone.com/articles/c-applications-vulnerability-cheatsheet
👍2
День 1259. #Безопасность #СписокУязвимостей
Памятка по Уязвимостям в C# Приложениях. Продолжение
Начало 1-4
Продолжение 5-9
Продолжение 10-13

14. Подделка межсайтовых запросов (Cross-Site Request Forgery – CSRF)
CSRF — это техника атаки на других пользователей веб-приложения, используемая на стороне клиента. С помощью CSRF злоумышленники могут отправлять HTTP-запросы, которые якобы исходят от жертвы, выполняя нежелательные действия от имени жертвы. Например, злоумышленник может изменить ваш пароль или перевести деньги с вашего банковского счета без вашего разрешения. См. пример.
В отличие от открытых перенаправлений, существует надежный способ предотвратить CSRF: использовать комбинацию токенов CSRF и SameSite-куки, а также избегать использования запросов GET для действий по изменению состояния.

15. Подделка запроса на стороне сервера (Server-Side Request Forgery – SSRF)
SSRF — это уязвимость, которая возникает, когда злоумышленник может отправлять запросы от имени сервера. Она позволяет злоумышленникам «подделывать» сигнатуры запросов уязвимого сервера, тем самым занимая привилегированное положение в сети, обходить средства управления брандмауэром и получать доступ к внутренним службам.
В зависимости от разрешений, предоставленных уязвимому серверу, злоумышленник может читать конфиденциальные файлы, выполнять внутренние вызовы API и получать доступ к внутренним службам, таким как скрытые инструменты администратора. Самый простой способ предотвратить уязвимости SSRF — никогда не делать исходящие запросы на основе пользовательского ввода. Если их приходится делать, необходимо проверять эти адреса перед инициированием запроса.

16. Нарушение границ доверия
«Границы доверия» относятся к тому, где ненадёжные пользовательские данные входят в контролируемую среду. Например, HTTP-запрос считается ненадёжными данными до тех пор, пока он не будет проверен сервером.
Должно быть чёткое различие между тем, как вы храните, транспортируете и обрабатываете доверенные и ненадёжные входные данные. Нарушения границ доверия происходят, когда это различие не соблюдается, а надёжные и ненадёжные данные смешиваются друг с другом. Например, если доверенные и недоверенные данные хранятся в одной и той же структуре данных или базе данных, приложение начнёт их путать. В этом случае ненадёжные данные могут быть ошибочно приняты за проверенные.
Хороший способ предотвратить нарушение границ доверия — никогда не записывать ненадёжные входные данные в хранилища, пока они не будут проверены.

17. Удалённое выполнение кода (Remote Code Execution - RCE)
RCE, представляют собой класс уязвимостей, которые возникают, когда злоумышленники могут выполнить свой код на вашем компьютере. Один из способов — уязвимости внедрения команд, когда пользовательский ввод объединяется непосредственно с системной командой. Приложение не может различить, где находится пользовательский ввод, а где системная команда, поэтому приложение выполняет пользовательский ввод как код. Злоумышленник сможет выполнять произвольные команды на машине.
Самый простой способ предотвратить удалённое выполнение кода — убедиться, что код, представленный в виде строки, и предназначенный для исполнения, получен только из надёжных источников, или внедрить надёжную проверку ввода в виде списка разрешений.

Продолжение следует…

Источник:
https://dzone.com/articles/c-applications-vulnerability-cheatsheet
👍8
День 1268. #Безопасность #СписокУязвимостей
Памятка по Уязвимостям в C# Приложениях. Продолжение
1-4
5-9
10-13
14-17

Инъекции. Начало
Проблемы с инъекциями возникают, когда приложение не может правильно отличить ненадёжные пользовательские данные от кода.

18. SQL-инъекции
При атаке с SQL-инъекцией злоумышленник вводит данные для управления командами SQL. Когда приложение не проверяет пользовательский ввод должным образом, злоумышленники могут вставлять спецсимволы языка SQL, чтобы нарушить логику запроса; тем самым выполняя произвольный код SQL.
Это позволит злоумышленнику изменять структуру SQL-запросов для кражи или изменения данных, или потенциального выполнения произвольных команд в операционной системе. Лучший способ предотвратить SQL-инъекции — использовать параметризованные запросы, что делает SQL-инъекции практически невозможными.

19. NoSQL-инъекции
Относятся к атакам, которые внедряют данные в логику языков NoSQL (Not Only SQL) баз данных. Современные базы данных NoSQL, такие как MongoDB, Couchbase, Cassandra и HBase, уязвимы для атак путем инъекций. Синтаксис запросов NoSQL зависит от базы данных, и запросы часто пишутся на языке приложения. По той же причине методы предотвращения NoSQL-инъекций в каждую базу данных также зависят от базы данных.

20. LDAP-инъекции
Облегчённый протокол доступа к каталогам (Lightweight Directory Access Protocol - LDAP) — это способ запроса к службе каталогов о пользователях и устройствах системы. Например, он используется для запросов к Microsoft Active Directory. Когда приложение использует ненадёжные входные данные в запросах LDAP, злоумышленники могут отправлять специально созданные данные и обходить аутентификацию или портить данные, хранящиеся в каталоге.

21. Инъекции в журналы
Вы задумывались когда-нибудь о том, что записи в файле журнала могут вам лгать? Файлы журнала, как и другие системные файлы, могут быть изменены злоумышленниками (например, чтобы замести следы во время атаки). Инъекции в журналы происходят, когда злоумышленник обманом заставляет приложение записывать поддельные записи в ваши файлы журналов.
Часто они происходят, когда приложение не экранирует символы новой строки «\n» во входных данных, записываемых в журналы. Злоумышленники могут использовать символ новой строки для вставки новых записей в журналы приложений. Другой способ заключается во внедрении вредоносного HTML в записи журнала, чтобы попытаться провести XSS-атаку на браузер администратора, который просматривает журналы.
Чтобы предотвратить атаки через инъекции в журналы, вам нужен способ отличить настоящие записи журнала от поддельных, введённых злоумышленником. Один из способов сделать это — добавить к каждой записи журнала дополнительные метаданные, такие как отметка времени, идентификатор процесса и имя хоста. Вы также должны относиться к содержимому файлов журналов как к ненадёжным входным данным и проверять их перед доступом к ним или операциями с ними.

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

Окончание следует…

Источник:
https://dzone.com/articles/c-applications-vulnerability-cheatsheet
👍6
День 1269. #Безопасность #СписокУязвимостей
Памятка по Уязвимостям в C# Приложениях. Окончание
1-4
5-9
10-13
14-17
18-22

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

24. Инъекции в регулярные выражения
Иногда приложения позволяют пользователям предоставлять серверу собственные шаблоны регулярных выражений. Атака с инъекцией в регулярное выражение – вид атаки на «отказ в обслуживании» (ReDoS – подробнее об этой атаке в будущих постах) - происходит, когда злоумышленник предоставляет механизму регулярных выражений шаблон, для оценки которого требуется много времени.

25. XPath-инъекции
XPath — это язык запросов, используемый в XML-документах для запроса и выполнения операций с данными, хранящимися в XML-документах. XPath-инъекция — это инъекция в выражения XPath, чтобы изменить результат запроса. Подобно SQL-инъекции, её можно использовать для обхода бизнес-логики, повышения привилегий пользователя и утечки конфиденциальных данных. Поскольку приложения всё ещё часто используют XML для передачи конфиденциальных данных между системами и веб-сервисами, именно эти места наиболее уязвимы для XPath-инъекций.

26. Инъекции в заголовки
Происходят, когда заголовки ответов HTTP динамически создаются из ненадёжных входных данных. В зависимости от того, на какой заголовок ответа влияет уязвимость, инъекция в заголовок может привести к межсайтовому скриптингу, открытому перенаправлению или краже сессии.
Например, если заголовком Location можно управлять с помощью параметра URL, злоумышленники могут вызвать открытое перенаправление, указав свой вредоносный сайт. Злоумышленники могут даже выполнять вредоносные сценарии в браузере жертвы или заставлять жертв загружать вредоносное ПО, отправляя жертве полностью контролируемые HTTP-ответы посредством инъекции в заголовок.
Вы можете предотвратить эту атаку, избегая записи пользовательского ввода в заголовки ответов, удаляя символы новой строки из пользовательского ввода (символы новой строки используются для создания новых заголовков ответов HTTP) или используя белый список для проверки значений заголовков.

27. Инъекции в сессии и небезопасные cookie
Если злоумышленник может манипулировать содержимым cookie-файла сессии или украсть чужие cookie, он может обмануть приложение, заставив его думать, что он является кем-то другим. Существует три основных способа, с помощью которых злоумышленник может получить доступ к чужой сессии:
1) Перехват сессии, когда злоумышленник крадёт чужой cookie-файл сессии и использует его как свой. Злоумышленники часто крадут cookie-файлы сессии с помощью атак XSS или MITM (man-in-the-middle).
2) Фальсификация сессии, когда злоумышленники могут изменить свой cookie-файл сессии, чтобы изменить то, как сервер интерпретирует их личность. Это происходит, когда состояние сессии передаётся в файле cookie, а он неправильно подписан или не зашифрован.
3) Спуфинг сессии – это «подделка» сессии, когда её идентификатор предсказуем. В этом случае злоумышленники могут подделывать настоящие cookie-файлы сессии и входить в систему как кто-то другой.

Источник: https://dzone.com/articles/c-applications-vulnerability-cheatsheet
👍8
День 1278. #Безопасность
Атаки на Отказ в Обслуживании с помощью Регулярных Выражений (ReDoS)
Регулярные выражения сложно оценивать. Неправильный шаблон может привести к низкой производительности, ошибочным результатам и даже к уязвимости.

Плохо спроектированные шаблоны регулярных выражений могут привести к неудачной проверке входных данных, негерметичным брандмауэрам и даже атакам на отказ в обслуживании (DoS). При DoS-атаке злоумышленник замедляет работу онлайн-сервиса или делает его недоступным для пользователей. Существует множество различных типов DoS, одним из которых является ReDoS, когда злоумышленник предоставляет механизму регулярных выражений строку, для оценки которой требуется много времени с помощью так называемых «злых шаблонов» (evil regex).

Большинство оценщиков регулярных выражений имеют экспоненциальную сложность в худшем случае, т.е. время оценки растёт экспоненциально по отношению к размеру входной строки. Шаблоны, которые могут привести к зависанию приложения при оценке, имеют две характеристики:
1) часто включают повторение сложных подвыражений (+ и * в сложных подвыражениях),
2) внутри этих повторяющихся подвыражений есть дополнительные повторяющиеся символы и выражения, которые соответствуют суффиксу другого совпадения.

Например:
^(a+)+$

Подвыражение в скобках ищет повторяющийся символ «a». Оно также проверяет, является ли всё выражение повторением какого-либо из подвыражений! Допустим, злоумышленник вводит такие данные:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Здесь каждая дополнительная буква "a" заставит оценщик проверять наличие повторений дополнительного подвыражения, таким образом удваивая количество времени обработки.

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

Другой пример - при регистрации проверка, содержит ли пароль пользователя его имя. Если приложение вслепую использует имя пользователя как шаблон без очистки спецсимволов, например:
var r = new Regex(username, RegexOptions.IgnoreCase);
var result = r.Match(password);
Тогда злоумышленник может внедрить вредоносное регулярное выражение через поле имени пользователя:
username: ^(a+)+$ 
password: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

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

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

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

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

Источник: https://sec.okta.com/articles/2020/04/attacking-evil-regex-understanding-regular-expression-denial-service
👍16
День 1674. #Безопасность
Политика
Безопасности Контента. Начало
Политика безопасности контента (Content Security Policy, CSP) представляет собой HTTP-заголовок Content-Security-Policy, который указывает браузерам, откуда загружать (и, в случае JavaScript, исполнять) контент, что может сделать почти невозможным осуществление межсайтового скриптинга. Значение заголовка состоит из директив и связанных значений.

Основная директива default-src предоставляет браузеру список всех действительных источников* или URI ресурсов.

*Источник определяется как следующие три значения:
- схема – http: или https:;
- полностью определённое имя доменаwww.example.com;
- порт – по умолчанию 80 для HTTP или 443 для HTTPS (если используется порт по умолчанию, то обычно он не является частью значения источника).
Если все три части различных источников идентичны, значит они совпадают. Например, у www.example.com и example.com разный источник, поскольку имена доменов не совпадают.

Кроме HTTP-заголовка можно использовать тег <meta>:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
Однако, это не очень удобно, когда значение директивы длинное. Кроме того, не будут работать некоторые функции CSP.

CSP определяет большое количество директив для различных видов ресурсов:
- base-uri – значения или пути, разрешенные для <base href="">;
- child-src - фреймы и веб-воркеры,
- connect-src - запросы HTTP и WebSocket,
- font-src – шрифты,
- form-action – значения для атрибута action элементов <form>;
- img-src – изображения,
- media-src - аудио- и видеофайлы,
- object-src – плагины,
- script-src - код JavaScript,
- style-src - cтили CSS,
и другие.

Специализированные директивы переопределяют значения default-src.

В заголовке директивы разделяются точкой с запятой, а их значения пробелами, например:
default-src 'self'; style-src 'self' https://cdn.jsdelivr.net

Здесь мы разрешаем использовать ресурсы только из того же источника, что и сама страница ('self'), а также разрешаем получать стили из сети доставки контента (CDN). Заметьте, что для style-src также указано значение 'self', чтобы была возможность использовать локальные файлы стилей (т.к. style-src полностью перезаписывает значение default-src).

Для указания источника есть следующие варианты:
- сайт – https://example.com;
- путь – https://example.com/assets/ (завершающий слеш обязателен для указания папки, а не файла с таким именем);
- полный URI – https://example.com/assets/style.css;
- подстановочный знак (*).
Рекомендуется использовать наиболее строгое указание источника, например, не разрешать все ресурсы из сети CDN.

Продолжение следует…

Источник: Кристиан Венц “
Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 2.
👍2
День 1675. #Безопасность
Политика
Безопасности Контента. Продолжение
Начало

Встроенный код
Если существует директива CSP default-src или style-src, то встроенные стили перестают работать. Аналогично, при наличии default-src или script-src встроенный код JavaScript больше выполняться не будет. Это позволяет защититься от внедрения кода вида
<script>/* вредоносный код */</script>.
При этом
<script src="script.js"></script>
будет работать. Обычно лучше избегать встроенного кода. Вынесите код JavaScript и CSS во внешние файлы.

Однако, если нужно активировать встроенный контент, есть несколько вариантов:
1. Атрибут nonce (одноразовый номер)
Случайный одноразовый токен (например, GUID), который добавляется в HTTP заголовок:
default-src 'self'; style-src 'self' 'nonce-123456'; script-src 'self' 'nonce-123456'
и во все элементы <script> и <style>, где используются встроенный код:
<script nonce="123456'">…</script>

2. Хэш контента элемента
Нужно вычислить хеш SHA256, SHA384 или SHA512 контента элемента <script> или <style>, включая разрывы строк и другие пробельные символы, и добавить в HTTP-заголовок значение 'sha<алгоритм>-<хэш>':
default-src 'self'; script-src 'self' 'sha256-nzw…='
Теперь эта политика явно разрешает встроенный код JavaScript, соответствующий хэшу.

Использование хэша не распространяется на:
- атрибуты обработчиков событий (например, onclick);
- ссылки JavaScript: (<a href="JavaScript:…">);
- атрибуты стилей (style="…").
Для активации этих функций, к значениям политики script-src или style-src надо добавить константу 'unsafe-hashes' (в дополнение к хэшам кода в этих атрибутах).
Также перестанет работать динамическое выполнение кода (eval(), setInterval(), setTimeout() со строковыми аргументами и т.п.). Чтобы включить это, нужно добавить 'unsafe-eval'.

3. Значение 'unsafe-inline'.
Разрешает исполнение встроенного кода (практически сводя на нет преимущества CSP).

Проверка кода JavaScript с помощью Subresource Integrity (SRI)
Если вы загружаете файл JavaScript со стороннего сервера, то можно проверить, что он не был подделан. Присвойте атрибуту integrity тега <script> хэш содержимого файла JavaScript:
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="></script>
Если содержимое файла JavaScript не совпадает с хэшем, браузер откажется выполнить код.

Окончание следует…

Источник: Кристиан Венц “
Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 2.
👍9
День 1676. #Безопасность
Политика
Безопасности Контента. Окончание
Начало
Продолжение

Отправка отчётов
Часто полезно знать, когда политика CSP нарушается. Это означает, что либо вы не разрешили использование какого-либо источника, либо есть уязвимость, которая активно эксплуатируется.

Директива report-uri заставит браузер отправлять POST-запрос на выбранную конечную точку при нарушении одной из политик:
default-src 'self'; style-src 'self' https://cdn.jsdelivr.net …; report-uri /csp-reports

Браузер отправит отчёт в формате JSON на эту конечную точку (которая также может находиться на другом домене) с информацией, какая политика была нарушена, какой файл (скрипт) её нарушил, в каком месте кода страницы он был вызван, и т.п. Существуют коммерческие системы, которые будут принимать ваши отчёты CSP и форматировать их в приятные UI представления (например, https://report-uri.com/). Стоит ли отправлять информацию о безопасности вашего сайта третьей стороне – решать вам.

Однако, можно не дожидаться, пока в производственной среде что-то перестанет работать, прежде чем исправлять это. HTTP-заголовок Сontent-Security-Policy-Report-Only подойдёт для тестирования политик. В отличие от заголовка Content-Security-Policy, он не будет применять политики безопасности контента, а просто будет сообщать о найденных нарушениях политик на заданную конечную точку (если она задана в report-uri).

При добавлении политик CSP к уже имеющемуся сайту полезно начать с использования заголовка Сontent-Security-Policy-Report-Only и политики, запрещающей всё. Для этого используется константа 'none':
default-src 'none'; form-action 'none'; report-uri /csp-reports

Затем, по мере получения отчётов либо вносите изменения в сайт, либо ослабляйте политики.

Конечная цель – максимально строгая CSP, насколько это возможно при используемом вами стеке. Обязательно нужно отключить плагины
и базовый URI:
object-src 'none'; base-uri 'none'

Также стоит рассмотреть возможность ограничения контента JavaScript только теми скриптами, для которых задан одноразовый токен:
script-src 'nonce-…'

Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 2.
👍9
День 1680. #Безопасность
Cookie и Управление Сессиями
Управление сессиями в ASP.NET Core зависит от файлов cookie. Сервер отправляет cookie с использованием HTTP-заголовка Set-Cookie, который содержит имя файла cookie, его значение и необязательные атрибуты, например дату истечения срока действия (по умолчанию cookie истекает при закрытии браузера). Браузер может принять, отклонить файл cookie или спросить пользователя, что делать. Почти всегда действует первый вариант. Отключение файлов cookie в браузере практически не позволяет использовать многие веб-приложения.

Поскольку cookie хранятся в браузере, их значениями легко манипулировать. Нельзя хранить конфиденциальную информацию в файле cookie, например текущее имя пользователя или его привилегии. Управление сессиями использует cookie, но снижает риски манипулирования данными. Сервер хранит уникальный идентификатор сессии, который отправляется клиенту в виде файла cookie. Идентификатор генерируется на сервере, он довольно длинный, и его практически невозможно угадать.

В ASP.NET Core функциональность сессий должна быть активирована явно. В Program.cs нужно вызвать builder.Services.AddSession() и app.UseSession().

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

Злоумышленник может украсть идентификатор сессии 3 способами:
1. на стороне клиента, как правило, используя межсайтовый скриптинг;
2. на стороне сервера, но осуществить такую атаку довольно непросто;
3. при передаче данных между клиентом и сервером через анализ трафика (сниффинг). Обычно такое возможно, только через HTTP.
См. также Принудительный HTTPS в ASP.NET Core.

Защитить файлы cookie можно с помощью флагов:
- HttpOnly – скрывает cookie от прямого доступа из кода JavaScript, что затрудняет межсайтовый скриптинг;
- secure – гарантирует, что cookie отправляется только через HTTPS.

Настройку флагов сеансовых файлов cookie нужно сделать явно в Program.cs:
builder.Services.AddSession(opt => {
opt.Cookie.HttpOnly = true;
opt.Cookie.SecurePolicy =
CookieSecurePolicy.Always;
});

Там же можно ограничить время, в течение которого можно использовать сеансовые cookie (по умолчанию 20 минут бездействия):
opt.IdleTimeout = TimeSpan.FromMinutes(5);

Обнаружение перехвата сессии
Есть несколько признаков – но не доказательств! – успешной атаки:
1. Изменение IP-адреса.
Однако на это могут быть и законные причины: переключение мобильных устройств с Wi-Fi на мобильный интернет и обратно, балансировщики интернет-нагрузки в сети компании, автоматический сброс подключения через 24 часа у некоторых провайдеров и т.п.
2. Изменение других заголовков HTTP, например, строки user agent.
Это более весомый признак, хотя может случаться при обновлении браузера, поэтому сравнивать useк agent как строки посимвольно – не очень хорошая идея.

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

Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 3.
👍17
День 1759. #Оффтоп #Безопасность
Осторожно: URL – Это Указатели на Изменяемые Сущности

Люди часто оценивают URL как: «Безопасные или вредоносные». В частности, поставщики продуктов безопасности ставят URL в один ряд с такими индикаторами опасности, как хэш известного вредоносного файла, вредоносный/скомпрометированный цифровой сертификат или заведомо вредоносный IP.

К сожалению, это разные вещи. Хэш файла никогда не меняется, содержимое файла не может измениться без изменения его хэша, и «безвредный» файл не может стать «вредоносным»*.
*Мы говорим о самом файле, а не о пути к файлу.

Однако IP или URL, может легко измениться с «безобидного» на «опасный» и наоборот. IP – просто указатель, а URL — указатель на указатель. И даже после того, как клиент подключается к целевому серверу, этот сервер решает, как интерпретировать запрос, и может каждый раз возвращать разное содержимое.

Поэтому не только URL со временем может измениться с безобидного на вредоносный (например, злоумышленник приобретёт домен после истечения срока его регистрации). URL может даже быть одновременно безвредным и вредоносным в зависимости от того, кто его запрашивает (например, злоумышленник может «замаскировать» свою атаку, чтобы вернуть вредоносный контент целевым жертвам, одновременно предоставляя безвредный контент другим). Или сервер может выдавать разные ответы разным клиентам.

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

Как это возможно? Злоумышленники просто воспользовались тем фактом, что URL являются указателями на изменяемые объекты. Скорее всего злоумышленник разместил заказ на рекламу и указал ссылку на редиректор, который перенаправлял на какую-то страницу на YouTube. Система проверки рекламы Google проверила целевой URL, чтобы убедиться, что он действительно указывает на YouTube, и начала показывать рекламу. Затем злоумышленник обновил редиректор на свой мошеннический сайт — классическая уязвимость «время проверки, время использования».

Цепочка перенаправлений браузера при нажатии ссылки
Из-за того, как работает модель безопасности веб-платформы, способность Google обнаруживать такого рода уловки ограничена: после того, как браузер пользователя покидает сервер googleadservices.com, рекламная система Google не знает, где в итоге окажется пользователь, и не может знать, что следующий редиректор теперь отправляет пользователя на сайт атаки.

Более того, вы можете подсмотреть на подсказку статуса браузера в нижнем углу браузера, чтобы увидеть, куда ведёт ссылка, прежде чем нажать на неё. Но на самом деле перед этим есть ещё один уровень косвенности: ссылка (элемент <a>) сама по себе является указателем-на-указатель-на-указатель. Благодаря манипуляциям с JavaScript URL, на который указывает ссылка на странице, может измениться при нажатии на него.

В частности, страница результатов поиска Google помещает URL в тэг <a>, но, когда пользователь нажимает на него, URL изменяется на «настоящий»: googleadservices.com/... и только потом осуществляется перенаправление на целевой URL.

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

Источник: https://textslashplain.com/2023/10/13/beware-urls-are-pointers-to-mutable-entities/
👍10
День 1896. #Оффтоп #Безопасность
Бэкдор в SSH Linux

«Linux безопасен», - говорили они. «В Linux нет вирусов», - говорили они.

Зато туда едва не проник бэкдор, который мог позволить его автору получать root доступ к любой (!!!) машине под управлением Linux и в которой была установлена нужная версия библиотеки XZ Utils. Причём сделал это один из её главных контрибуторов и довольно хитро - в make-файле (которые обычно никто досконально не проверяет). Бэкдор активировался при сборке проекта. Насколько я понял, достаточно было добавить малозаметную точку в файл в очередном релизе, чтобы сборка «выбрасывала ошибку» при поиске одной из нужных библиотек, и вместо неё использовала «стандартную» с уязвимостью. После этого оставалось только ждать, пока все серверы обновят версию библиотеки и…

По иронии судьбы обнаружил это парень из Microsoft. Он заметил, что его входы в систему стали занимать дольше обычного (2,5 секунды против 2х раньше), и стал копать. Из-за этой счастливой случайности уязвимость не успела распространиться далее нескольких превью версий.

Национальная база данных уязвимостей США присвоила этой уязвимости критичность 10 из 10.

Больше подробностей об этом, а также чем процесс релиза кода в Microsoft отличается от процесса в «диком опенсорсе» смотрите в видео Dave’s Garage.
👍27
День 1970. #Безопасность
Межсайтовая Подделка Запросов (CSRF). Начало

В 2005 г. исследователь в области информационной безопасности Сами Камкар обнаружил уязвимость в популярной в то время социальной сети Myspace. Ему удалось внедрить код JavaScript на страницу своего профиля. Это классическая XSS-атака. Код отправлял HTTP-запрос от имени жертвы, добавляя её в список друзей Камкара. Не прошло и 20 часов, как у него было более миллиона друзей на Myspace.

Название атаки (Cross-Site Request Forgery - межсайтовая подделка запросов), по сути, описывает ее анатомию. Какой-то другой сайт (созданный злоумышленником) принудительно отправляет от имени клиента поддельный запрос. Чаще всего это выглядит так:
1. Пользователь ранее посещал (целевой) сайт и создал состояние – например, выполнил вход или добавил товары в корзину. Это состояние сохраняется, обычно в виде файла cookie (скажем, сеансового файла cookie, а сессия содержит состояние входа в систему или содержимое корзины).
2. Пока браузер открыт и сессия активна, пользователь переходит на другой сайт, контролируемый злоумышленником. Этот сайт делает запрос на целевой сайт, с которым пользователь ранее взаимодействовал, одним из двух способов:
- в случае GET-запроса сайт злоумышленника содержит код JavaScript, выполняющий запрос через скрытый iframe или <img> с адресом целевого сайта в атрибуте href;
- в случае POST-запроса сайт злоумышленника содержит элемент <form> с атрибутом method=POST и адресом целевого сайта в атрибуте action. А страница содержит код JavaScript, который отправляет данные формы.

В итоге целевой сайт получает HTTP-запрос, отправленный браузером пользователя. Запрос содержит сеансовый файл cookie для идентификации пользователя. Поэтому сайт может выполнять действия «от имени» пользователя. GET-запросы обычно не так страшны, поскольку не меняют состояния (в соответствии с лучшими практиками), а вот POST-запросы могут действительно повлиять на приложение.

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

Эту атаку ещё называют "катание на сессии", т.к. сессия пользователя не крадётся, злоумышленник просто использует её "втёмную".

Именно так Сами Камкар завел новых друзей на Myspace: он нашел XSS-уязвимость и внедрил код JavaScript, который выполнял POST-запрос, чтобы «добавить пользователя в друзья».

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

Окончание следует…

Источник: Кристиан Венц “
Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍21
День 1971. #Безопасность
Межсайтовая Подделка Запросов (CSRF). Окончание

Начало

В случае с CSRF есть два аспекта, которые делают атаку возможной:
1. Злоумышленник может точно предсказать HTTP-запрос. Это сделать несложно, проанализировав настоящий запрос. Данные формы передаются в открытом виде, поэтому их легко подменить, имитировав нужные параметры.
2. Активная сессия. Но файлы cookie клиента автоматически отправляются на сервер, которому они принадлежат. Злоумышленнику не нужно красть идентификатор сессии; он использует сессию пользователя.

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

Делаем HTTP-запрос непредсказуемым
Если к данным формы мы добавим дополнительный случайный токен, то атака завершится неудачей. Злоумышленник не сможет предугадать токен, поэтому не сможет создать валидный запрос. Если приложение использует одноразовые токены, то каждый из них будет действителен только один раз. Случайный токен будет явной частью HTML-формы, и такой же токен в файле cookie будет отправлен клиентом автоматически. На сервере оба этих значения проверяются. Если они отсутствуют или не совпадают, то приложение выдаёт ошибку 400 Bad Request.

В ASP.NET Core такой механизм уже есть и активирован по умолчанию. ASP.NET Core автоматически добавляет в форму дополнительное скрытое поле, вроде такого:
html 
<input name="__RequestVerificationToken" type="hidden"
value="CfDJ8FflGUpl_…U90c" />

А сервер отправляет cookie, например:
 
.AspNetCore.Antiforgery.Za7zYHoQn5w=CfDJ8FflGUpl_…0ueI

Всего символов в значениях поля и cookie около 150. Примерно первые 20 совпадают, остальные нет. При каждой перезагрузке формы токен в поле меняется, но файл cookie останется прежним. Так приложение может работать на нескольких вкладках браузера с общим файлом cookie.

Никакой дополнительной настройки не требуется, если вы используете форму следующими способами:
- <form method="post">...</form>
- @Html.BeginForm(...)

Механизм защиты от CSRF представляет собой промежуточное ПО, которое автоматически активируется, при использовании стандартных методов в классе Program:
- MVC (AddMvc(), AddControllersWithViews() или MapControllerRoute()),
- Razor Pages (AddRazorPages() или MapRazorPages()),
- Blazor (MapBlazorHub())

Если вы хотите избавиться от токенов (а у вас для этого должна быть очень веская причина, например другое приложение, отправляющее POST-запрос в вашу конечную точку), то либо:
- используйте <!form>...<!/form>;
- деактивируйте CSRF-токен для каждой формы с помощью asp-antiforgery="false".

Токен по умолчанию генерируется и добавляется в любую форму, но не проверяется автоматически. Используя фильтры в ASP.NET Core (атрибуты или глобальные фильтры), можно реализовать 3 варианта:
- AutoValidateAntiForgeryToken – требует (и проверяет) токены для всех HTTP-запросов, меняющих состояние приложения (все, кроме GET, HEAD, OPTIONS и TRACE);
- ValidateAntiForgeryToken – гарантирует, что метод-действие, помеченный этим атрибутом, проверит запрос, независимо от HTTP-метода;
- IgnoreAntiForgeryToken – отключает проверку токенов.

Источник: Кристиан Венц “Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍15
День 2189. #Безопасность
CORS. Использование Ресурсов Между Разными Источниками. Начало
Рассмотрим, что было бы, если бы можно было использовать JavaScript для вызова конечной точки из другого источника.

См. определение источника тут.

Ниже показан простой веб-API https://localhost:3000 с конечными точками Get() и Post():
using Microsoft.AspNetCore.Mvc;
namespace MyApp.Controllers;

[Route("api/[controller]")]
[ApiController]
public class CorsController : ControllerBase
{
// GET: api/Cors
[HttpGet]
public int Get()
{
return new Random().Next(10, 100);
}
// POST api/Cors
[HttpPost]
public void Post([FromBody] int value)
{
}
}

Get() возвращает случайное число между 10 и 99, а Post() ничего не делает.

В другом проекте, в другом источнике https://localhost:5000, для вызова этого API страница Razor использует JavaScript:
@page
<div class="text-center">
<h1 class="display-4">CORS</h1>
<div id="output"></div>
</div>
@section Scripts {
<script>
fetch("https://localhost:3000/api/Cors")
.then(response => response.json())
.then(data => {
document
.getElementById("output")
.textContent = data;
});
</script>
}

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

Запрос был отправлен, но JS не получил никаких данных. Причина: правило ограничения домена (CORS). Если бы этот запрос работал, злоумышленник мог бы использовать JS для отправки HTTP-запроса на страницу, чтобы, например, добавить товар в корзину – автоматически с использованием файла cookie идентификатора сессии пользователя (см. также Безопасность Cookie). В рамках анализа ответа злоумышленник мог бы извлечь antiforgery-токен из формы и, следовательно, обойти защиту от межсайтовой подделки запросов.

И хотя данный вид атаки ещё не был изобретен, когда появилось правило ограничения домена, поскольку JS не может получить доступ к HTTP-ответу (спасибо правилу ограничения домена), атака не сработает.

Продолжение следует…

Источник: Кристиан Венц “
Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍17
День 2190. #Безопасность
CORS. Использование Ресурсов Между Разными Источниками. Продолжение

Начало

Но что, если у JavaScript кода приложения есть законный интерес к вызову API? Если внимательно посмотреть на HTTP-запрос, который был сгенерирован, когда мы попытались вызвать API из JavaScript, мы заметим кое-что любопытное. Заголовок Origin не отправляется с каждым запросом, но браузер автоматически добавляет его при кросс-доменном запросе:
GET /api/Cors HTTP/2
Host: localhost:3000

Origin: https://localhost:5000

Заголовок содержит источник – протокол, домен, порт – вызывающей страницы. Тогда сервер может взять эту информацию и решить, может ли код JavaScript иметь доступ к данным, поступающим с сервера. Если да, то HTTP-ответ должен включать заголовок Access-Control-Allow-Origin и в качестве значения для него должен использовать отправленный источник (или заполнитель *, но, как всегда, лучше быть как можно более явным):
Access-Control-Allow-Origin: https://localhost:5000

Этот механизм называется совместное использование ресурсов между источниками (CORS), и ASP.NET Core поддерживает его – нет необходимости реализовывать его вручную. В диспетчере пакетов NuGet по запросу «CORS» выдаётся длинный список результатов. Но все они предназначены для .NET Standard и .NET Framework. ASP.NET Core автоматически использует собственную версию пакета Microsoft.AspNetCore.Cors. CORS поставляется как промежуточное ПО в ASP.NET Core, поэтому нужно сделать его доступным и активировать. В классе Program требуется:
- добавить поддержку CORS (и настроить её), с помощью AddCors();
- активировать CORS - UseCors().

При вызове AddCors() можно указать параметры. Обычно нужно настроить хотя бы одну политику CORS (т.е. определить разрешённые источники):
builder.Services.AddCors(opts =>
{
opts.AddPolicy("CORS API Endpoint",
bldr =>
{
bldr.WithOrigins("https://localhost:5000");
});
});

Важно:
- Используйте источник клиента API, а не URL самого API!
- Источник должен состоять только из протокола, домена и порта, без слеша в конце.

Можно использовать произвольное количество политик, и у каждой может быть любое количество источников. Переменная bldr (типа CorsPolicyBuilder) также предоставляет методы, чтобы явно разрешить другие фрагменты информации для кросс-доменного запроса с использованием JS:
- WithExposedHeaders() – список заголовков HTTP-ответа, которые возвращаются и становятся доступными для JS;
- WithHeaders() – список разрешённых дополнительных заголовков HTTP-запросов, к которым клиент хотел бы получить доступ;
- WithMethods() – список разрешённых дополнительных HTTP-методов.
- AllowAnyHeader() – разрешать все заголовки;
- AllowAnyMethod() – разрешать все методы.

По умолчанию никакие учётные данные, например заголовки Authorization, не отправляются вместе с кросс-доменным запросом. Опять же, причина
тому – защита от межсайтовой подделки запросов. Если вы хотите, чтобы эта информация была доступна для API, метод AllowCredentials() сообщает клиенту, что её можно отправлять, а DisallowCredentials() - явно запрещает.

Наконец, можно использовать политику по умолчанию:
options.AddDefaultPolicy(
bldr =>
{
bldr.WithOrigins("https://localhost:5000");
});


Окончание следует…

Источник: Кристиан Венц “
Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
👍17
День 2191. #Безопасность
CORS. Использование Ресурсов Между Разными Источниками. Окончание

Начало
Продолжение

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

1. Глобально
Нужна политика по умолчанию, затем нужно добавить вызов метода UseCors(). Важен порядок. CORS необходимо активировать:
- после маршрутизации (UseRouting()),
- перед кешированием ответов, аутентификацией и авторизацией (UseResponseCaching(), UseAuthentication(), UseAuthorization()).

Для политики по умолчанию достаточно вызвать:
app.UseCors();


2. Для конечных точек
Для именованных политик также нужен вызов UseCors() в Program.cs, но т.к. нет политики по умолчанию, затем необходимо добавить атрибут [EnableCors] с именем политики в класс контроллера (для всех методов) или только в отдельные методы:
[Route("api/[controller]")]
[EnableCors("CORS API Endpoint")]
[ApiController]
public class CorsController : ControllerBase
{

}

Теперь все методы в контроллере API отправляют правильный заголовок Access-Control-Allow-Origin. При этом атрибут [DisableCors] отключит политику для отдельных методов контроллера. Применив эти изменения к API и снова вызвав страницу из изначального примера, мы получаем желаемый результат. На этот раз не только проходит HTTP-запрос, но и код JS может получить доступ к возвращаемому значению и отобразить его.

3. Для маршрутов
Применяе именованные политики к маршрутам. В ASP.NET Core это настраивается в методе app.UseEndpoints() с помощью расширения RequireCors() после вызова MapControllers(), MapControllerRoute(), MapGet() или аналогичных:
app.UseEndpoints(eps =>
{
eps.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireCors("CORS API Endpoint");
});


CORS на стероидах: предварительные запросы
GET-запрос из нашего примера всё равно выполняется, даже если не соответствует политике (т.к. считается, что GET-запросы не изменяют состояния приложения), но код JS не получает доступа к возвращаемым данным. POST (и другие) запросы могут изменить состояние приложения, поэтому их нельзя просто отправить. В таких случаях браузеры отправляют предварительные запросы (preflight request). Сначала - запрос OPTIONS. Он также не должен ничего изменить на сервере. Если ответ содержит заголовок Access-Control-Allow-Origin с соответствующим значением, и ответ положительный, на сервер будет отправлен ещё один запрос, чтобы получить ресурсы.

Поскольку REST API не имеют состояния, сервер должен проверять все запросы. Но мы можем указать (через заголовок Access-Control-Max-Age), что предварительный запрос не обязательно делать каждый раз. В .NET это можно легко настроить внутри метода AddCors:
builder.Services.AddCors(opts =>
{
opts.AddPolicy("CORS API Endpoint",
bldr =>
{
bldr.

.SetPreflightMaxAge(TimeSpan.FromMinutes(10));
});
});

SetPreflightMaxAge даст указание клиенту кэшировать предварительный запрос CORS на 10 минут (т.е. он отправляет заголовок Access-Control-Max-Age со значением 600).

Источники:
- Кристиан Венц “
Безопасность ASP.NET Core”. М.: ДМК Пресс, 2023. Глава 4.
-
https://steven-giesel.com/blogPost/5fc7cb62-d5ad-4f07-831c-d6c1c6974641/cache-cors-preflight-requests
👍13
День 2231. #Безопасность
Атрибуты
Безопасности Файлов Cookie
Один из самых распространённых способов, которым веб-браузеры используют cookie, — это аутентификация пользователя и сохранение сессии. Злоумышленники могут украсть или подделать cookie для получения доступа к аутентифицированным областям и существующим сессиям пользователя.

Существует 3 распространённых атаки с использованием cookie:
1. Атаки с использованием межсайтового скриптинга (XSS) и атаки типа «человек посередине» (MITM) часто используются для кражи файлов cookie.
2. Атаки с использованием межсайтовой подделки запросов (CSRF) используют способ обработки файлов cookie браузерами для выполнения вредоносных действий от имени аутентифицированных пользователей.

Спецификация протокола HTTP содержит несколько механизмов, которые разработчики могут использовать для снижения риска доступа злоумышленников к содержимому cookie с конфиденциальными данными, их повторного использования или подделки. Ниже перечислены атрибуты заголовка HTTP Set-Cookie, которые можно использовать для повышения безопасности файлов cookie.

1. Expire и Max-Age
Определяют срок действия cookie. Expire устанавливает абсолютную дату/время истечения срока действия (формат: weekday, DD-MM-YYYY hh:mm:ss GMT), а атрибут Max-Age - ограничение по времени с момента установки cookie. Если Expire и Max-Age не установлены, браузер обрабатывает cookie как сеансовый и удаляет его при закрытии браузера. Если установлены, сохраняет cookie как постоянный на стороне клиента и удаляет в соответствии со значениями Expire и Max-Age (в зависимости от того, что наступит раньше).

2. Secure
Указывает, что cookie может передаваться только с использованием HTTPS-соединений и никогда не отправляется в открытом виде. Браузер не будет отправлять Secure cookie с запросами HTTP.
Атрибут Secure предназначен для защиты от атак типа «человек посередине» (MITM). Однако он защищает только конфиденциальность файла cookie, а не его целостность. Злоумышленник не получит cookie с сервера через незашифрованное соединение, но всё равно может отправить поддельный cookie на сервер в виде обычного текста.

3. Domain
Объявляет домен, на который будет отправлен cookie (а также все поддомены). Если атрибут Domain не установлен, cookie будет отправлен только на исходный хост (без поддоменов). Поэтому наиболее безопасный способ — не устанавливать атрибут Domain, если это не необходимо.

4. Path
URL-путь, по которому будет отправлен cookie (включая все подпути). По умолчанию - / (все URL-пути на сервере).

5. HttpOnly
Введён для предотвращения атак XSS. Браузер будет отправлять cookie с этим атрибутом только в ответ на HTTP-запросы, т.е. к ним нельзя будет получить доступ из клиентского кода JavaScript. Однако атрибут HttpOnly не защищает cookie от перезаписи. Браузер может хранить только ограниченное количество файлов cookie для домена. Злоумышленник может использовать атаку переполнения хранилища cookie, тем самым удаляя исходный cookie из памяти браузера и добавляя cookie с тем же именем без атрибута HttpOnly.

6. SameSite
Предписывает веб-браузерам отправлять cookie по-разному в зависимости от того, как посетитель взаимодействует с сайтом, установившим cookie. Используется для защиты от атак CSRF. Может иметь одно из следующих значений:
- SameSite=Strict: cookie отправляется только, если вы в данный момент находитесь на сайте, который установил cookie. Если вы переходите с другого сайта (например, из результатов поиска в Google), такой cookie не отправляется с первым запросом.
- SameSite=Lax: файл куки отправляется с GET-запросами верхнего уровня, но не отправляется для встроенного контента (рисунки, CSS, JS).
- SameSite=None: ограничений нет.
Внимание: если атрибут SameSite не установлен, можно ожидать разного поведения браузеров и разных версий одного браузера.

См. также Cookie и Управление Сессиями

Источник: https://www.invicti.com/learn/cookie-security-flags/
👍16