Я хочу использовать токен, чтобы предотвратить атаки CSRF на моем сайте (написанные с помощью PHP). Я использовал его в формах, и он работает хорошо. Но выход из системы не является формой; Это только гиперссылка.
Является ли это безопасным, если я помещаю токен в строку запроса следующим образом:
<a href="logout.php?token=9ae328eea8a72172a2426131a6a41adb">Logout</a>
Если у вас есть какие-либо проблемы, каковы ваши предложения и решения?
Я считаю, что одним из главных недостатков использования CSRF-токена в запросах GET является возможность некомпетентного пользователя легко разгласить его токен, скопировав ссылку с токеном и вставляя ее в какой-то общедоступный контент, такой как комментарий / сообщение / etc … Также GET параметры запроса, включая CSRF-токены, обычно регистрируемые HTTP-серверами / прокси-серверами, и это создает другой риск.
Поэтому я предлагаю вам внедрить CSRF-безопасные ссылки, используя что-то вроде этого:
<form name="logout" action="logout.php" method="post"> <input type="hidden" name="token" value="9ae328eea8a72172a2426131a6a41adb"/> </form> ... <a href="/nojs.html" onclick="document.logout.submit(); return false">Logout</a>
Да, если токен CSRF защищен и проверен: в обоих случаях подход одинаковый.
Материал из Википедии: Межсайтовый запрос на подделку – Предотвращение :
На веб-сайтах доступны различные контрмеры CSRF. Требование секретности, токена, специфичного для пользователя, во всех формах и побочных URL-адресах предотвращает CSRF; сайт злоумышленника не может помещать правильный токен в свои материалы.
Не имеет значения, имеет ли токен значение формы или параметр строки запроса 1 . Подход, который предотвращает CSRF путем включения маркера в формы, можно адаптировать к (и действительным для) гиперссылкам 2 .
1 MitM, который может перехватывать URL-адрес, может так же легко перехватить HTML-форму. Это выходит за рамки стандартной атаки CSRF или ее смягчения.
2 Предполагается, что токен – это значение для пользователя (и времени). Простой HMAC-хэш идентификатора сеанса должен быть достаточным в большинстве случаев.
Другие сделали несколько хороших моментов. Я добавляю этот ответ, чтобы увеличить их. Всегда фильтруйте и проверяйте пары имени / значения строки запроса.
Учитывая : у вас есть база данных, и вы хотите создать ссылку, чтобы помочь динамически получать (но не изменять) контент, к которому может быть привязан пользователь. Пример: статьи новостей, тематические исследования, общедоступные профили пользователей.
Требование : используйте строку запроса и сдерживайте CSRF с помощью токена.
Одной из целей токена CSRF является проверка того, что входящий HTTP-запрос был сгенерирован на странице, обслуживаемой из вашего домена (независимо от того, играют ли сеансы. Маркер сеанса – отдельный зверь). Значок CSRF работает лучше всего, когда вы используете более одного вектора защиты .
Сравнение: убедитесь, что поданный токен соответствует одному в сеансе.
Время: вы можете указать, что токен хорош только на определенный период в будущем.
public function setFormToken() { $token = $this->cipher->getFormToken(); //Some hashing algorithm. $this->formToken = $token; //In this example, used to insert the token into HTML. $_SESSION['token'] = $token; //Save the token for comparison upon form submission / HTTP query string processing. $_SESSION['tokenExpireTime'] = time() + (60 * FORM_TOKEN_EXPIRE_MINUTES); //This is just an abstract example. return; }
Затем, помимо сравнения поданного токена с тем, который был в сеансе, убедитесь, что период подачи заявки все еще действителен.
private function hasTokenTimeLeft() { if(isset($_SESSION['tokenExpireTime']) && (time() < $_SESSION['tokenExpireTime'])) { return true; } throw new SecurityException("Token time has expired for this POST request.", 911); }
Сеансы: если сеанс истек или отсутствует, неверный запрос HTTP для вашего контента должен завершиться неудачно.
Запросить информацию : с запросом HTTP POST некоторые попытки проверить, что токен, пользовательский агент и IP соответствуют одному из исходного HTTP-запроса GET (что означает сохранение его в сеансе перед ответом на запрос GET).
Строки запроса , как упоминалось ранее, могут кэшироваться. В этом нет никаких проблем, если данные должны быть общедоступными. Подумайте о том, кто-то закладок продукта на веб-сайте электронной коммерции.
Что вы должны спросить себя: « Должен ли я получить этот контент из любого места, в любое время, по этой ссылке с помощью строки запроса ?» Если да, не используйте true, backend, случайно сгенерированный токен CSRF. Представьте, что вы работаете в избранном офисе из уст в уста, а люди посылают ссылки своим друзьям и родственникам по электронной почте (хорошо, плохая практика). В этом случае вы никогда не хотите устанавливать «провод отключения» и вызывать неисправность. Если сначала необходимо создать новый токен на бэкэнд, электронная почта по вашей ссылке не будет работать.
Если вы не сможете получить доступ к контенту за пределами вашего контекста безопасности (то есть перед входом в систему), вы можете принять любые меры, необходимые для укрепления стратегии токена CSRF с использованием строк запроса .
Ваш отрыв – отличный пример.
<a href="logout.php?token=9ae328eea8a72172a2426131a6a41adb">Logout</a>
Никто извне вашего контекста безопасности не сможет использовать функцию выхода из системы. Вы хотите «проезд», если кто-то отправляет эту ссылку по электронной почте! Очевидно, что сеансы интегрированы в это решение (токен должен храниться где-то, пока пользователь использует эту страницу). Длительность сеанса и выход из системы следует тщательно контролировать, и я говорю, что вы делаете хорошую работу.
Шифрование . Единственное, что вы могли бы сделать лучше, это шифровать хэш / токен для строки запроса, затем расшифровать его и проверить при отправке. Кроме того, вы можете разбить токен на кусочки, смешать куски и в основном использовать некоторую безопасность по методам строковой маскировки, чтобы сделать ваш токен CSRF более устойчивым.