From 3a21ef916aba5489c8f3bcf2df492b3988a59e1f Mon Sep 17 00:00:00 2001 From: Egor Deev Date: Fri, 2 Oct 2026 13:24:18 +0000 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=85=D0=BE=D0=B4:=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D1=85=D0=BE=D0=B4=20=D0=BF=D0=BE=20=3Fnext=3D=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BD=D0=B0=20=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D1=8B=20=D1=8D=D1=82=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D1=81=D0=B0=D0=B9=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit После входа приложение перенаправляло на любой адрес из параметра next — ссылкой вида /login?next=https://… можно было увести пользователя на чужой сайт. --- app/routes/auth.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/routes/auth.py b/app/routes/auth.py index a7aa52e..dff6cdf 100644 --- a/app/routes/auth.py +++ b/app/routes/auth.py @@ -1,3 +1,5 @@ +from urllib.parse import urlsplit + from flask import Blueprint, render_template, redirect, url_for, flash, request from flask_login import login_user, logout_user, login_required, current_user from app import db @@ -6,6 +8,13 @@ from app.models.user import User bp = Blueprint('auth', __name__) +def _is_safe_next(target: str) -> bool: + """Переход после входа — только на страницы этого же сайта (защита от открытого редиректа).""" + parts = urlsplit(target) + return (bool(target) and target.startswith('/') and not target.startswith(('//', '/\\')) + and not parts.netloc and not parts.scheme) + + @bp.route('/register', methods=['GET', 'POST']) def register(): if current_user.is_authenticated: @@ -42,8 +51,10 @@ def login(): user = User.query.filter_by(login=login).first() if user and user.check_password(password): login_user(user, remember=bool(request.form.get('remember'))) - next_page = request.args.get('next') - return redirect(next_page or url_for('schedules.profile')) + next_page = request.args.get('next', '') + if not _is_safe_next(next_page): + next_page = url_for('schedules.profile') + return redirect(next_page) flash('Неверный логин или пароль', 'danger') return render_template('auth/login.html')