Безопасно ли хранить мой «следующий» 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-адреса. В чем подвох?

    TL; DR

    1. Да, это безопасно.
    2. Не беспокойтесь о том, чтобы скрывать URL-адрес или препятствовать «спуфированию». На самом деле вы не можете этого сделать, поэтому вы готовитесь к обоим.
    3. Потенциальная ошибка: после того, как вы установите перенаправление на сеанс, следующий вход будет следовать за ним независимо от того, до истечения срока действия сеанса. Способ исправить это просто сохранить путь перенаправления как параметр GET (см. Нижнюю часть ответа).
    4. Вот хороший чит-лист для перенаправления и пересылки проблем безопасности.

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

    Когда вы спрашиваете «если я еще должен проверять следующий 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 , это не должно secure_page вашу безопасность. Фактически, они уже должны знать этот URL-адрес, потому что они сначала переходили на эту страницу, поэтому либо они набрали его, либо щелкнули ссылку, либо были сохранены в закладке или истории просмотра. Важно то, что когда вы обрабатываете запросы на secure_page , вы требуете, чтобы они вошли в систему.

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

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

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

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

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

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

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

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

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

    Два случая:

    Loggin in

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

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

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

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

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

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