ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 28.04.2024
Просмотров: 99
Скачиваний: 0
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
bankname/account/changepassword, то банк может проверить у текущего запроса параметр referer, и если он не совпадает с сайтом банка, а принадлежит кому-то другому, то запрос можно отклонить.
index?search=Test
atrap.min.css . font-awesome.mln.css style.css?26
css?family=Caveat|Montserrat|Raleway:.. jquery.min.js
■ apl.js
Щ bootstrap.min.js Щ default.js?1 | adsbygoogle.js Щ defaultlmagesm.png | headerimage.png 0 telegram-icon.png 0 tw-icon.png 0 yt-icon.png 3 ap-icon.png 3 sp-icon.png
' Request Headers
Fnov. info
:method: GET
:path: /search/index?search=Test rscheme: https
accept: text/html,application/xhtml+xml,application/xr accept-encoding: gzip, deflate, br accept-language: en-US,en;q=0.9, ru;q=0.8 cache-control: no-cache
cookie: _ym_uid=1546536376946461143; fid=db2333d3-48ee 5:S=ALNI_MaTFXuPU2SKpOH05Evhz8HrHP9mZA; _utmz=184115
9C26; utmc=18411502; _gads=undefined; PHPSESSID=f7
1.10.1615080112
pra
referer. https ://www
^el-LII'UJ. LIU UllliUlll
Рис. 7.1. Referer в утилитах разработчика
.flenov.info/ 1
ГТ^5"ВЯТ^ЯЙд1е
Chrome";v="88",
ia-irrm nnn
Загрузите мой сайт Flenov.info, введите что-то в поле поиска и откройте утилиты разработчика, затем перейдите на вкладку Network. Теперь введите что-то в строку поиска и нажмите кнопку Find (Найти). Находим самый первый запрос в левой панели и справа в разделе Request Headers ищем referer (рис 7.1). Как видите, тут указан мой сайт, потому что мы нажимали кнопку Find именно на той странице, которая указана в referer.
Попробуйте прогуляться по сайту и посмотрите, как меняется referer. Обратите внимание, что он всегда указывает на ту страницу, с которой мы переходим на следующую.
Таким образом, если форма будет располагаться на сайте хакера, то в Referer попадет его сайт.
А что, если хакер направит форму на свой сайт и потом отправит запрос на сайт банка, подделав referer? Это сработает, и вы сможете подделать этот параметр, но как насчет cookies? Именно в них находится информация о сессии, и она говорит сайту, авторизован пользователь или нет.
Если запрос будет отправляться сначала на сайт хакера, то браузер не предоставит необходимые cookies. Весь смысл в том, что запрос должен идти именно на сайт банка, чтобы ему передалась необходимая информация о текущем пользователе.
Да, защита по Referer может сработать, и этот параметр можно проверять, но не стоит все же ему доверять. Слишком все нежно и звучит ненадежно. Есть мнение, что если хакер сможет украсть cookie, то ему останется только получить имя пользователя, и можно будет отправлять запрос с сервера напрямую и подделывать поле Referer. Но ведь если хакер украдет cookie, то он сможет перехватить и сессию на сервере и, возможно, просто загрузив сайт, уже будет авторизован от имени пользователя, и не нужно ничего строить дополнительно.
Но допустим, что для смены пароля хакеру нужны cookies, чтобы отправить запрос от имени пользователя, имя пользователя и текущий пароль. Возможно, он украл cookie каким-то образом и, загрузив сайт, где-то увидел реальное имя пользователя, которое не так уж часто скрывается. Но вот текущий пароль хакер может не знать, и тут как раз поможет атака межсайтовых запросов. Создав поддельную форму для смены пароля, можно получить текущее значение и поменять его...
Но если хакер смог получить текущий пароль, то зачем его менять? Теоретически можно уже и не менять, а просто украсть пароль, и это тоже вариант атаки. Но если смены не произойдет, то это вызовет подозрение у пользователя: он же будет думать, что уже установлен новый пароль, а его нет.
В качестве дополнительной защиты от межсайтовых запросов можно реализовать что-то похожее на каптчу. Каждый раз, когда загружается форма, на сервере генерируется случайный код, который привязан к сессии и пользователю. Этот код добавляется к форме и отправляется со всеми данными на сервер. При защите от межсайтовой загрузки страниц предугадать подобный код будет невозможно.
Именно так работает встроенная защита в Microsoft .NET.
В .NET Core код защиты от межсайтовых атак может генерироваться автоматически. Для этого можно добавить сервис защиты Antiforgery в методе ConfigureServices класса Startup: services.AddAntiforgery(options =>
{
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME"; options.SuppressXFrameOptionsHeader = false;
});
После этого вы можете вручную контролировать создание защиты для каждой отдельной формы, на случай, если ее нужно отменить, указав в cshtml у формы свойство asp-antiforgery:
В данном случае защита отключается указанием значения false.
В .NET Framework можно также использовать специальный метод — расширение
AntiForgeryToken:
Выполнение этого кода приведет к тому, что .NET добавит к форме следующий невидимый параметр:
Этот код заставит браузер добавить к форме код защиты и отправит его вместе с пользовательскими данными на сервер. Но это не значит, что сервер в реальности произведет проверку. Ему нужно сообщить, что для определенного метода необходимо произвести проверку, потому что там ожидается код безопасности.
Например, следующий метод ChangePassword вызывается, когда пользователь отправляет данные на сервер методом post и в форме был указан код защиты, а значит, с помощью метаданных
[ValidateAntiForgeryToken] мы просим фреймворк проверить этот код:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangePassword(PasswordViewModel account)
{
}
Защита от межсайтовых запросов возлагается на фреймворки, а не на сами языки программирования, так что если говорить о PHP, то это язык программирования и защита не является его задачей. В C# защита тоже не является частью языка, это часть фреймворка .NET.
Главная идея в том, что на сервере мы сохраняем какой-то уникальный код, который привязан к сессии пользователя. Для этого можно сгенерировать 64 случайных байта и превратить их в строку из шестнадцатеричных значений, чтобы строка была короче (меньше передавать данных):
$_SESSION['secure_token'] = bin2hex(random_bytes(64));
Теперь эту же строку нужно добавить к форме, и когда пользователь отправляет данные на сервер, нужно проверить, что строки совпадают.
Но это если самому реализовывать защиту вручную на чистом PHP. Как я сказал, это вообще прерогатива фреймворков.
Давайте посмотрим, что есть у Symfony для защиты от CSRF. Когда мы создаем форму, то нужно сделать невидимое поле (type="hidden") со значением ключа, которое генерируем методом csrf_token:
Метод csrf_token в скобках получает какое-то имя, которое может указывать, для чего вы планируете использовать ключ. Просто на сайте может быть несколько различных форм, и будет хорошо просто разделить их между собой логически.
Имя поля input может быть произвольным, я его назвал token, а вы можете выбрать любое имя, главное потом при проверке кода на сервере использовать его же.
Теперь на сервере проверка токена может выглядеть так:
public function changepassword(Request $request)
{
if ($this->isCsrfTokenValid('change-password',
$request->request->get('token'))) {
// ключ верный
}
}
В принципе это и все — достаточно простая реализация простой защиты.
Рассматривать все возможные фреймворки я не буду, потому что для PHP их существует... даже не знаю сколько, но точно уж больше, чем пальцев одной руки. Я же использую только Symfony, поэтому и рассказал вам о нем.
Cross-origin Resource Sharing, или совместное использование ресурсов между разными источниками, — это технология, которая позволяет разделять ресурсы сайта с другими. С ее помощью можно указать, при обращении к каким ресурсам наш сайт сможет отдавать свои ресурсы.
К ffl | Elements | Console Sources!^ Network | ^^rformance Memory Application | Secur |
• 0 | V Q. | О Preserve log Q Disabl^Betie^ | впмпе v ♦ 4 | |
Filter | | □ Hide data URLs 0 XHR | JS CSS Img Media Font Doc WS Manifest | |
| | x Headers | Preview Response Initiator Timing | Cool |
index?search=Test
atrap.min.css . font-awesome.mln.css style.css?26
css?family=Caveat|Montserrat|Raleway:.. jquery.min.js
■ apl.js
Щ bootstrap.min.js Щ default.js?1 | adsbygoogle.js Щ defaultlmagesm.png | headerimage.png 0 telegram-icon.png 0 tw-icon.png 0 yt-icon.png 3 ap-icon.png 3 sp-icon.png
' Request Headers
Fnov. info
:method: GET
:path: /search/index?search=Test rscheme: https
accept: text/html,application/xhtml+xml,application/xr accept-encoding: gzip, deflate, br accept-language: en-US,en;q=0.9, ru;q=0.8 cache-control: no-cache
cookie: _ym_uid=1546536376946461143; fid=db2333d3-48ee 5:S=ALNI_MaTFXuPU2SKpOH05Evhz8HrHP9mZA; _utmz=184115
9C26; utmc=18411502; _gads=undefined; PHPSESSID=f7
1.10.1615080112
pra
referer. https ://www
^el-LII'UJ. LIU UllliUlll
Рис. 7.1. Referer в утилитах разработчика
.flenov.info/ 1
ГТ^5"ВЯТ^ЯЙд1е
Chrome";v="88",
ia-irrm nnn
Загрузите мой сайт Flenov.info, введите что-то в поле поиска и откройте утилиты разработчика, затем перейдите на вкладку Network. Теперь введите что-то в строку поиска и нажмите кнопку Find (Найти). Находим самый первый запрос в левой панели и справа в разделе Request Headers ищем referer (рис 7.1). Как видите, тут указан мой сайт, потому что мы нажимали кнопку Find именно на той странице, которая указана в referer.
Попробуйте прогуляться по сайту и посмотрите, как меняется referer. Обратите внимание, что он всегда указывает на ту страницу, с которой мы переходим на следующую.
Таким образом, если форма будет располагаться на сайте хакера, то в Referer попадет его сайт.
А что, если хакер направит форму на свой сайт и потом отправит запрос на сайт банка, подделав referer? Это сработает, и вы сможете подделать этот параметр, но как насчет cookies? Именно в них находится информация о сессии, и она говорит сайту, авторизован пользователь или нет.
Если запрос будет отправляться сначала на сайт хакера, то браузер не предоставит необходимые cookies. Весь смысл в том, что запрос должен идти именно на сайт банка, чтобы ему передалась необходимая информация о текущем пользователе.
Да, защита по Referer может сработать, и этот параметр можно проверять, но не стоит все же ему доверять. Слишком все нежно и звучит ненадежно. Есть мнение, что если хакер сможет украсть cookie, то ему останется только получить имя пользователя, и можно будет отправлять запрос с сервера напрямую и подделывать поле Referer. Но ведь если хакер украдет cookie, то он сможет перехватить и сессию на сервере и, возможно, просто загрузив сайт, уже будет авторизован от имени пользователя, и не нужно ничего строить дополнительно.
Но допустим, что для смены пароля хакеру нужны cookies, чтобы отправить запрос от имени пользователя, имя пользователя и текущий пароль. Возможно, он украл cookie каким-то образом и, загрузив сайт, где-то увидел реальное имя пользователя, которое не так уж часто скрывается. Но вот текущий пароль хакер может не знать, и тут как раз поможет атака межсайтовых запросов. Создав поддельную форму для смены пароля, можно получить текущее значение и поменять его...
Но если хакер смог получить текущий пароль, то зачем его менять? Теоретически можно уже и не менять, а просто украсть пароль, и это тоже вариант атаки. Но если смены не произойдет, то это вызовет подозрение у пользователя: он же будет думать, что уже установлен новый пароль, а его нет.
В качестве дополнительной защиты от межсайтовых запросов можно реализовать что-то похожее на каптчу. Каждый раз, когда загружается форма, на сервере генерируется случайный код, который привязан к сессии и пользователю. Этот код добавляется к форме и отправляется со всеми данными на сервер. При защите от межсайтовой загрузки страниц предугадать подобный код будет невозможно.
Именно так работает встроенная защита в Microsoft .NET.
В .NET Core код защиты от межсайтовых атак может генерироваться автоматически. Для этого можно добавить сервис защиты Antiforgery в методе ConfigureServices класса Startup: services.AddAntiforgery(options =>
{
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME"; options.SuppressXFrameOptionsHeader = false;
});
После этого вы можете вручную контролировать создание защиты для каждой отдельной формы, на случай, если ее нужно отменить, указав в cshtml у формы свойство asp-antiforgery:
В данном случае защита отключается указанием значения false.
В .NET Framework можно также использовать специальный метод — расширение
AntiForgeryToken:
Выполнение этого кода приведет к тому, что .NET добавит к форме следующий невидимый параметр:
Этот код заставит браузер добавить к форме код защиты и отправит его вместе с пользовательскими данными на сервер. Но это не значит, что сервер в реальности произведет проверку. Ему нужно сообщить, что для определенного метода необходимо произвести проверку, потому что там ожидается код безопасности.
Например, следующий метод ChangePassword вызывается, когда пользователь отправляет данные на сервер методом post и в форме был указан код защиты, а значит, с помощью метаданных
[ValidateAntiForgeryToken] мы просим фреймворк проверить этот код:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangePassword(PasswordViewModel account)
{
}
Защита от межсайтовых запросов возлагается на фреймворки, а не на сами языки программирования, так что если говорить о PHP, то это язык программирования и защита не является его задачей. В C# защита тоже не является частью языка, это часть фреймворка .NET.
Главная идея в том, что на сервере мы сохраняем какой-то уникальный код, который привязан к сессии пользователя. Для этого можно сгенерировать 64 случайных байта и превратить их в строку из шестнадцатеричных значений, чтобы строка была короче (меньше передавать данных):
$_SESSION['secure_token'] = bin2hex(random_bytes(64));
Теперь эту же строку нужно добавить к форме, и когда пользователь отправляет данные на сервер, нужно проверить, что строки совпадают.
Но это если самому реализовывать защиту вручную на чистом PHP. Как я сказал, это вообще прерогатива фреймворков.
Давайте посмотрим, что есть у Symfony для защиты от CSRF. Когда мы создаем форму, то нужно сделать невидимое поле (type="hidden") со значением ключа, которое генерируем методом csrf_token:
Метод csrf_token в скобках получает какое-то имя, которое может указывать, для чего вы планируете использовать ключ. Просто на сайте может быть несколько различных форм, и будет хорошо просто разделить их между собой логически.
Имя поля input может быть произвольным, я его назвал token, а вы можете выбрать любое имя, главное потом при проверке кода на сервере использовать его же.
Теперь на сервере проверка токена может выглядеть так:
public function changepassword(Request $request)
{
if ($this->isCsrfTokenValid('change-password',
$request->request->get('token'))) {
// ключ верный
}
}
В принципе это и все — достаточно простая реализация простой защиты.
Рассматривать все возможные фреймворки я не буду, потому что для PHP их существует... даже не знаю сколько, но точно уж больше, чем пальцев одной руки. Я же использую только Symfony, поэтому и рассказал вам о нем.
-
Cross-origin — делим ресурсы
Cross-origin Resource Sharing, или совместное использование ресурсов между разными источниками, — это технология, которая позволяет разделять ресурсы сайта с другими. С ее помощью можно указать, при обращении к каким ресурсам наш сайт сможет отдавать свои ресурсы.