Я пишу приложение (Django, так оно и происходит), и я просто хочу понять, что такое «токен CSRF» и как он защищает данные. Являются ли почтовые данные небезопасными, если вы не используете токены CSRF?
Я пишу приложение (Django, так оно и происходит), и я просто хочу понять, что такое «токен CSRF» и как он защищает данные. Являются ли почтовые данные небезопасными, если вы не используете токены CSRF?
Ответы:
www.mybank.com
mybank.com
приведет к запросу (концептуально) формы http://www.mybank.com/transfer?to=<SomeAccountnumber>;amount=<SomeAmount>
. (Ваш номер счета не нужен, поскольку он подразумевается вашим логином.)www.cute-cat-pictures.org
, не зная, что это вредоносный сайт.mybank.com
(требует некоторой удачи!), Он может включить на своей странице запрос типа http://www.mybank.com/transfer?to=123456;amount=10000
(где указан 123456
номер их учетной записи на Каймановых островах). и 10000
это сумма, которую вы ранее думали, что вы были рады иметь).www.cute-cat-pictures.org
страницу, поэтому ваш браузер выполнит этот запрос.www.mybank.com
файлом cookie, и он будет выглядеть совершенно законно. Там идут ваши деньги!Это мир без токенов CSRF .
Теперь для лучшего с токенами CSRF :
http://www.mybank.com/transfer?to=123456;amount=10000;token=31415926535897932384626433832795028841971
.mybank.com
будет отображаться на их собственной веб-странице, когда оно будет предоставлено вам. Это отличается каждый раз, когда они обслуживают любую страницу никому.www.mybank.com
.Результат: Вы сохраняете свои 10000
денежные единицы. Я предлагаю вам пожертвовать часть этого в Википедии.
(Ваш пробег может отличаться.)
РЕДАКТИРОВАТЬ из комментария стоит прочитать:
Стоит отметить, что скрипт www.cute-cat-pictures.org
обычно не имеет доступа к вашему токену анти-CSRF www.mybank.com
из-за контроля доступа HTTP. Эта заметка важна для некоторых людей, которые необоснованно отправляют заголовок Access-Control-Allow-Origin: *
для каждого ответа веб-сайта, не зная, для чего он нужен, просто потому, что они не могут использовать API с другого веб-сайта.
www.cute-cat-pictures.org
обычно не имеет доступа к вашему токену анти-CSRF www.mybank.com
из-за контроля доступа HTTP. Это примечание важно для некоторых людей, которые необоснованно отправляют заголовок Access-Control-Allow-Origin: *
для каждого ответа веб-сайта, не зная, для чего он нужен, просто потому, что они не могут использовать API с другого веб-сайта.
Да, почтовые данные в безопасности. Но происхождение этих данных не так. Таким образом, кто-то может заставить пользователя с помощью JS войти на ваш сайт, просматривая веб-страницу злоумышленника.
Чтобы предотвратить это, django отправит случайный ключ как в cookie, так и в данные формы. Затем, когда пользователи отправляют сообщения POST, он проверяет, идентичны ли два ключа. В случае обмана пользователя сторонний веб-сайт не может получить куки-файлы вашего сайта, что приводит к ошибке аутентификации.
Сайт генерирует уникальный токен при создании страницы формы. Этот токен необходим для отправки / получения данных на сервер.
Поскольку токен генерируется вашим сайтом и предоставляется только при создании страницы с формой, какой-то другой сайт не может имитировать ваши формы - он не будет иметь токен и, следовательно, не сможет публиковать на вашем сайте.
В блоге Cloud Under есть хорошее объяснение токенов CSRF.
Представьте, что у вас есть веб-сайт, похожий на упрощенный Twitter, размещенный на a.com. Зарегистрированные пользователи могут вводить некоторый текст (твит) в форму, которая отправляется на сервер в виде запроса POST и публикуется при нажатии кнопки отправки. На сервере пользователь идентифицируется с помощью файла cookie, содержащего его уникальный идентификатор сеанса, поэтому ваш сервер знает, кто опубликовал твит.
Форма может быть такой простой:
<form action="http://a.com/tweet" method="POST"> <input type="text" name="tweet"> <input type="submit"> </form>
Теперь представьте, плохой парень копирует и вставляет эту форму на свой вредоносный веб-сайт, скажем, b.com. Форма все еще будет работать. Пока пользователь входит в ваш Твиттер (т. Е. У него есть действующий файл cookie сеанса для a.com), запрос POST будет отправляться
http://a.com/tweet
и обрабатываться как обычно, когда пользователь нажимает кнопку отправки.Пока что это не большая проблема, если пользователь знает, что именно делает форма, но что если наш плохой парень подправит форму следующим образом:
<form action="https://example.com/tweet" method="POST"> <input type="hidden" name="tweet" value="Buy great products at http://b.com/#iambad"> <input type="submit" value="Click to win!"> </form>
Теперь, если один из ваших пользователей попадет на сайт злоумышленника и нажмет кнопку «Нажмите, чтобы выиграть!» Кнопка, форма отправляется на ваш сайт, пользователь правильно идентифицируется по идентификатору сеанса в куки и скрытый твит публикуется.
Если бы наш плохой парень был еще хуже, он бы заставил невинного пользователя отправить эту форму, как только они откроют его веб-страницу с помощью JavaScript, возможно, даже полностью скрытого в невидимом фрейме. Это в основном подделка межсайтовых запросов.
Форма может быть легко отправлена отовсюду. Обычно это общая черта, но во многих случаях важно разрешить отправку формы только из домена, к которому она принадлежит.
Еще хуже, если ваше веб-приложение не различает запросы POST и GET (например, в PHP с использованием $ _REQUEST вместо $ _POST). Не делай этого! Запросы на изменение данных могут быть отправлены так же просто, как
<img src="http://a.com/tweet?tweet=This+is+really+bad">
встроенные в вредоносный веб-сайт или даже по электронной почте.Как сделать так, чтобы форму можно было отправлять только с моего собственного сайта? Вот где появляется токен CSRF. Маркер CSRF - это случайная, трудно угадываемая строка. На странице с формой, которую вы хотите защитить, сервер сгенерирует случайную строку, токен CSRF, добавит ее в форму в качестве скрытого поля и также каким-то образом запомнит, либо сохранив ее в сеансе, либо установив cookie содержащий значение. Теперь форма будет выглядеть так:
<form action="https://example.com/tweet" method="POST"> <input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn"> <input type="text" name="tweet"> <input type="submit"> </form>
Когда пользователь отправляет форму, сервер просто должен сравнить значение отправленного поля csrf-token (имя не имеет значения) с токеном CSRF, запомненным сервером. Если обе строки равны, сервер может продолжить обработку формы. В противном случае сервер должен немедленно прекратить обработку формы и ответить ошибкой.
Почему это работает? Есть несколько причин, по которым злоумышленник из нашего примера не может получить токен CSRF:
Копирование статического исходного кода с нашей страницы на другой веб-сайт было бы бесполезным, поскольку значение скрытого поля меняется с каждым пользователем. Если бы сайт злоумышленника не знал токен CSRF текущего пользователя, ваш сервер всегда отклонял бы запрос POST.
Поскольку вредоносная страница злоумышленника загружается браузером вашего пользователя из другого домена (b.com вместо a.com), у злоумышленника нет шансов написать код JavaScript, который загружает контент и, следовательно, текущий токен CSRF нашего пользователя из Ваш сайт. Это связано с тем, что веб-браузеры по умолчанию не разрешают междоменные запросы AJAX.
Плохой парень также не может получить доступ к куки, установленному вашим сервером, потому что домены не будут совпадать.
Когда следует защищать от подделки межсайтовых запросов? Если вы можете быть уверены, что не смешиваете GET, POST и другие методы запросов, как описано выше, хорошим началом будет защита всех запросов POST по умолчанию.
Вам не нужно защищать запросы PUT и DELETE, потому что, как объяснено выше, стандартная HTML-форма не может быть отправлена браузером с использованием этих методов.
С другой стороны, JavaScript действительно может делать другие типы запросов, например, используя функцию $ .ajax () jQuery, но помните, что для работы запросов AJAX домены должны совпадать (если вы не настроили явно свой веб-сервер) ,
Это означает, что часто вам даже не нужно добавлять токен CSRF в запросы AJAX, даже если они являются запросами POST, но вам нужно будет убедиться, что вы обходите проверку CSRF только в своем веб-приложении, если запрос POST на самом деле AJAX запрос. Вы можете сделать это, посмотрев на наличие заголовка типа X-Requested-With, который обычно включают в себя запросы AJAX. Вы также можете установить другой пользовательский заголовок и проверить его наличие на стороне сервера. Это безопасно, потому что браузер не будет добавлять пользовательские заголовки к обычной отправке формы HTML (см. Выше), поэтому у мистера Плохого парня нет шансов смоделировать это поведение с помощью формы.
Если вы сомневаетесь в запросах AJAX, потому что по какой-то причине вы не можете проверить заголовок, такой как X-Requested-With, просто передайте сгенерированный токен CSRF в свой JavaScript и добавьте токен в запрос AJAX. Есть несколько способов сделать это; либо добавьте его в полезную нагрузку, как обычная форма HTML, либо добавьте пользовательский заголовок в запрос AJAX. Пока ваш сервер знает, где искать его во входящем запросе и может сравнить его с исходным значением, которое он запоминает из сеанса или файла cookie, вы сортируетесь.
Корень всего этого - убедиться, что запросы поступают от реальных пользователей сайта. Для форм генерируется токен csrf, который должен быть привязан к сеансам пользователя. Используется для отправки запросов на сервер, на котором токен их проверяет. Это один из способов защиты от csrf, другим будет проверка заголовка реферера.