Подтвердить что ты не робот

Безопасно ли хранить мой "следующий" URL-адрес в подписанном cookie и перенаправлять на него беззаботным?

Я использую Flask, и мне пришло в голову, что это может быть довольно изящное решение для перенаправления на последнюю страницу пользователя после входа/выхода из системы, просто разместив session['next'] = request.url на каждой конечной точке моего приложения и просто попросив меня функции входа/выхода из системы перенаправляют право на session.get('next'). Это даже похоже на вариант в расширении Flask-Login, если вы включили USE_SESSION_FOR_NEXT.

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

http://flask.pocoo.org/snippets/62/

Есть ли причина, по которой этот метод чаще не развертывается? Это похоже на приятное, чистое и простое решение, которое очищает URL, сводит к минимуму для полей/обработки и устраняет уязвимость для открытия атак с перенаправлением, если вы не предпринимаете дополнительных шагов для проверки следующего URL-адреса. Какой улов?

4b9b3361

Ответ 1

TL; DR

  • Да, это безопасно.
  • Не беспокойтесь о том, чтобы скрывать URL-адрес или препятствовать "подмену". На самом деле вы не можете ничего сделать, поэтому вы готовитесь к обоим.
  • Потенциальная ошибка: после того, как вы установите перенаправление на сеанс, следующий вход будет следовать за ним независимо от того, до истечения срока действия сеанса. Чтобы исправить это, просто сохраните путь перенаправления как параметр GET (см. Нижнюю часть ответа).
  • Вот хороший чит-лист для перенаправления и пересылки проблем безопасности.

Это безопасный рабочий процесс, предполагая, что ваш сервер проверяет входящие запросы на все защищенные ресурсы.

Когда вы спрашиваете "если я еще должен проверять следующий URL-адрес перед перенаправлением", ответ на это нет, но вам нужно проверить все запросы на этот URL-адрес (после перенаправления), чтобы убедиться, что они вошли в систему.

В вашем вопросе звучит так, будто вы пытаетесь сохранить скрытый URL-адрес от пользователя до тех пор, пока он не войдет в систему. Это не обязательно.

Например, скажем, у вас есть два URL:

url 1:  "/login"  # anyone can access this
url 2:  "/secure_page"  # only a logged in user can access this

Скажем, пользователь не вошел в систему и пытается перейти к yoursite.com/secure_page. Они должны быть перенаправлены на вашу страницу входа каждый раз. Если они знают URL secure_page, это не должно ставить под угрозу безопасность. Фактически, они уже должны знать этот URL-адрес, потому что они сначала переходили на эту страницу, поэтому либо они набрали его, либо щелкнули ссылку, либо были сохранены в закладке или истории просмотра. Важно то, что когда вы обрабатываете запросы на secure_page, вам требуется, чтобы они вошли в систему.

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

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

http://yoursite.com/login?next=secure_page

Что происходит, они сохраняют этот следующий URL как параметр HTTP GET. Хотя он менее "чист", он более явный, поэтому он имеет свои плюсы и минусы. И если позже они перейдут на страницу входа в систему, это перенаправление больше не будет происходить, что может быть вашим желаемым поведением. С вашим текущим кодом, как только это перенаправление будет в сеансе, этот следующий логин после этого будет следовать за перенаправлением до истечения срока действия сеанса, который может быть после того, как пользователь уйдет, а кто-то другой использует этот веб-браузер.

Многие сайты делают это так, как я показал выше. Django делает это таким образом. В этом случае вредоносная ссылка может предоставить "следующий" URL-адрес и перенаправить его на какой-либо фишинг-сайт, но это можно легко предотвратить, если "следующий" URL-адрес не удаляется от вашего домена.

Вот основной чит-лист для безопасности переадресации/пересылки (вы перенаправляете, но другие, которые могут приступить сюда, могут рассматривать запросы на пересылку).

Ответ 2

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

При этом я не вижу причин, по которым вам не следует проверять URL-адрес, по крайней мере, чтобы убедиться, что вы перенаправляетесь на страницу в том же домене. Стоимость исполнения тривиальна, и я считаю, что все, что связано с потоком входа/выхода из системы, заслуживает дополнительного уровня контроля. Я также хотел бы убедиться, что у вас есть приемлемый случай по умолчанию, когда вы получаете запрос без этого поля в файле cookie.

Ответ 3

Как отметил @brendan, это решение будет работать нормально, используйте защитник @login_required для защиты представления.

Два случая:

Loggin in

Вы находитесь в /index (не защищенное представление) → авторизуйтесь успешно в представлении @login_protected, в этом случае, если вы вернетесь, поскольку /index доступен для всех, вам действительно все равно

Выход из системы

Вы находитесь в /profile view (protected view) → успешный выход в незащищенный вид, если вы вернетесь, декоратор не позволит вам войти в представление

Ответ 4

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

<X-Frame-Options','DENY'>

Хотя это не касается перенаправления, но его можно использовать здесь. Будьте осторожны.