Когда вам нужно использовать iri_to_uri после использования url_has_allowed_host_and_scheme в Django? - PullRequest
0 голосов
/ 24 февраля 2020

В примечаниях к выпуску Django 3.0 этот комментарий содержит около url_has_allowed_host_and_scheme:

Чтобы избежать путаницы в отношении эффективной области действия, частная внутренняя утилита is_safe_url() переименовано в url_has_allowed_host_and_scheme(). То, что URL имеет разрешенный хост и схему, в целом не означает, что это «безопасно». Например, он все еще может быть указан неверно. Убедитесь, что вы также используете iri_to_uri() для компонента пути ненадежных URL.

Я понимаю, для чего предназначена url_has_allowed_host_and_scheme. Возьмите общий вариант использования параметра запроса next, например: http://example.com/foobar?next=http%3A%2F%2Fexample2.com%2Fhello. Вы можете запрограммировать представление, которое обрабатывает этот путь, для перенаправления на URL, предоставленный параметром next, в данном случае: http://example2.com/hello. Если URL-адрес не проверен, это уязвимость «открытого перенаправления». Злоумышленники могут воспользоваться преимуществами открытого перенаправления, чтобы скрыть вредоносные URL-адреса за URL-адресом, который выглядит заслуживающим доверия.

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

Мой вопрос касается iri_to_uri. Документация подразумевает, что вам также необходимо использовать эту функцию. Когда мне нужно его использовать?

1 Ответ

0 голосов
/ 24 февраля 2020

Вот как вы бы реализовали безопасное перенаправление:

from django.utils.http import url_has_allowed_host_and_scheme
from django.utils.encoding import iri_to_uri
from django.shortcuts import redirect

def example_view(request):
    if url_has_allowed_host_and_scheme(request.GET['next'], None):
        url = iri_to_uri(request.GET['next'])
        return redirect(url)
    else:
        raise

Часть iri_to_uri необходима для того, чтобы убедиться, что URL-адрес конечного результата указан правильно. Например:

Первая строка в HTTP-запросе должна быть в таком формате:

GET /caf%C3%A9/ HTTP/1.0

URL должен быть экранирован, так как он нарушил бы протокол HTTP, если бы он содержал что-то вроде пробелов.

Если честно, я все еще не совсем уверен, зачем нужен iri_to_uri, потому что утилиты Django, такие как redirect, будут автоматически при необходимости экранируйте URL-адрес, прежде чем он попадет в провод в HTTP-запросе.

...