Что такое токен CSRF? Каково его значение и как оно работает?
Ладно, ребята, я пишу приложение для Django и просто хочу понять, что на самом деле представляет собой токен csrf и как он защищает данные. Являются ли почтовые данные небезопасными, если вы не используете токены csrf?
Я знаю, как использовать csrf_token, но мне просто нужно немного информации, как это работает.
5 ответов
Подделка межсайтовых запросов (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
печенье, и это будет выглядеть совершенно законно. Там идут ваши деньги!
Это мир без токенов 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 с другого сайта.
Да, почтовые данные в безопасности. Но происхождение этих данных не так. Таким образом, кто-то может заставить пользователя с помощью JS войти на ваш сайт, просматривая веб-страницу злоумышленника.
Чтобы предотвратить это, django отправит случайный ключ как в файле cookie, так и в данных формы. Затем, когда пользователи отправляют сообщения POST, он проверяет, идентичны ли два ключа. В случае обмана пользователя сторонний веб-сайт не может получить файлы cookie вашего сайта, что приводит к ошибке аутентификации.
Позволь мне привести пример…
Представьте, что у вас есть веб-сайт, похожий на упрощенный 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>
Теперь, если один из ваших пользователей попадает на сайт злоумышленника и нажимает кнопку "Нажмите, чтобы выиграть!", Форма отправляется на ваш сайт, пользователь правильно идентифицируется по идентификатору сеанса в файле cookie, и скрытый твит получает опубликован.
Если бы нашему плохому парню было еще хуже, он заставил бы невинного пользователя отправить эту форму, как только они откроют его веб-страницу с помощью JavaScript, возможно, даже полностью скрытого в невидимом фрейме. Это в основном подделка межсайтовых запросов.
Форма может быть легко представлена отовсюду и везде. Обычно это обычная функция, но во многих случаях важно разрешить отправку формы только из домена, к которому она принадлежит.
Еще хуже, если ваше веб-приложение не различает запросы POST и GET (например, в PHP с использованием $_REQUEST вместо $_POST). Не делай этого! Запросы на изменение данных можно отправить так же просто, как 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.
Плохой парень также не может получить доступ к cookie, установленному вашим сервером, потому что домены не будут совпадать.
Когда следует защищать от подделки межсайтовых запросов? Если вы можете быть уверены, что не смешиваете 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, другим будет проверка заголовка реферера.