added url check
This commit is contained in:
@@ -41,6 +41,7 @@ from .utils import (
|
|||||||
get_course,
|
get_course,
|
||||||
token_required,
|
token_required,
|
||||||
get_cached_deck_info,
|
get_cached_deck_info,
|
||||||
|
is_safe_url
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -131,6 +132,10 @@ def set_cookie(token):
|
|||||||
current_app.logger.debug("next_url not present redirecting to index")
|
current_app.logger.debug("next_url not present redirecting to index")
|
||||||
next_url = url_for("main.index")
|
next_url = url_for("main.index")
|
||||||
|
|
||||||
|
if not is_safe_url(next_url):
|
||||||
|
current_app.logger.warning(f"Blocked unsafe redirect attempt to: {next_url}")
|
||||||
|
return abort(400)
|
||||||
|
|
||||||
resp = make_response(redirect(next_url))
|
resp = make_response(redirect(next_url))
|
||||||
resp.set_cookie(
|
resp.set_cookie(
|
||||||
"access_token", serialize_token(token), httponly=True, samesite="Lax", path="/"
|
"access_token", serialize_token(token), httponly=True, samesite="Lax", path="/"
|
||||||
@@ -260,6 +265,10 @@ def admin_login():
|
|||||||
|
|
||||||
next_page = request.args.get("next")
|
next_page = request.args.get("next")
|
||||||
|
|
||||||
|
if next_page and not is_safe_url(next_page):
|
||||||
|
current_app.logger.warning(f"Blocked unsafe redirect attempt to: {next_page}")
|
||||||
|
return abort(400)
|
||||||
|
|
||||||
if next_page:
|
if next_page:
|
||||||
session["next_url"] = next_page
|
session["next_url"] = next_page
|
||||||
|
|
||||||
|
|||||||
11
app/utils.py
11
app/utils.py
@@ -6,6 +6,7 @@ from typing import cast
|
|||||||
from itsdangerous import BadSignature, URLSafeSerializer
|
from itsdangerous import BadSignature, URLSafeSerializer
|
||||||
from xkcdpass import xkcd_password
|
from xkcdpass import xkcd_password
|
||||||
from functools import wraps, lru_cache
|
from functools import wraps, lru_cache
|
||||||
|
from urllib.parse import urlparse, urljoin
|
||||||
|
|
||||||
from .models import Deck, InfoBanner, Token, db, Course
|
from .models import Deck, InfoBanner, Token, db, Course
|
||||||
|
|
||||||
@@ -209,3 +210,13 @@ def get_cached_deck_info(token_id, course_folder, deck_slug):
|
|||||||
"deck_name": deck_obj.name,
|
"deck_name": deck_obj.name,
|
||||||
"index_file": deck_obj.index_file
|
"index_file": deck_obj.index_file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def is_safe_url(target):
|
||||||
|
"""
|
||||||
|
Ensures that a redirect target will lead to the same server.
|
||||||
|
Handles both relative paths ('/admin') and absolute URLs ('https://yourdomain.com/admin').
|
||||||
|
"""
|
||||||
|
ref_url = urlparse(request.host_url)
|
||||||
|
test_url = urlparse(urljoin(request.host_url, target))
|
||||||
|
|
||||||
|
return test_url.scheme in ('http', 'https') and ref_url.netloc == test_url.netloc
|
||||||
|
|||||||
Reference in New Issue
Block a user