CVE-2022-0697 (published 2022-03-06T23:15Z)

Open Redirect in GitHub repository archivy/archivy prior to 1.7.0.

Severity: MEDIUM
CVSS v2 base score: 5.8 (AV:N/AC:M/Au:N/C:P/I:P/A:N)
CVSS v3 base score: 6.1, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-601
cwe_name: URL Redirection to Untrusted Site ('Open Redirect')
description: A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect. This simplifies phishing attacks.
extended_description: An http parameter may contain a URL value and could cause the web application to redirect the request to the specified URL. By modifying the URL value to a malicious site, an attacker may successfully launch a phishing scam and steal user credentials. Because the server name in the modified link is identical to the original site, phishing attempts have a more trustworthy appearance. Whether this issue poses a vulnerability will be subject to the intended behavior of the application. For example, a search engine might intentionally provide redirects to arbitrary URLs.
         

Fix information:
repo_url: https://github.com/archivy/archivy
commit_details: repo_url: https://github.com/archivy/archivy
author: Uzay-G
author_date: 2022-02-24 21:32:40+01:00
msg: fix open redirect
repository: repo_url: https://github.com/archivy/archivy
repo_name: archivy/archivy
description: Archivy is a self-hostable knowledge repository that allows you to learn and retain information in your own personal and extensible wiki.
repo_language: Python
owner: archivy
file_changes: filename: helpers.py
change_type: ModificationType.MODIFY
diff: @@ -5,8 +5,9 @@ import os
 import elasticsearch
 import yaml
 from elasticsearch import Elasticsearch
-from flask import current_app, g
+from flask import current_app, g, request
 from tinydb import TinyDB, Query, operations
+from urllib.parse import urlparse, urljoin
 
 from archivy.config import BaseHooks, Config
 
@@ -230,3 +231,12 @@ def create_plugin_dir(name):
         return True
     except FileExistsError:
         return False
+
+
+def is_safe_redirect_url(target):
+    host_url = urlparse(request.host_url)
+    redirect_url = urlparse(urljoin(request.host_url, target))
+    return (
+        redirect_url.scheme in ("http", "https")
+        and host_url.netloc == redirect_url.netloc
+    )

programming_language: Python
filename: routes.py
change_type: ModificationType.MODIFY
diff: @@ -19,7 +19,7 @@ from werkzeug.security import check_password_hash, generate_password_hash
 
 from archivy.models import DataObj, User
 from archivy import data, app, forms, csrf
-from archivy.helpers import get_db, write_config
+from archivy.helpers import get_db, write_config, is_safe_redirect_url
 from archivy.tags import get_all_tags
 from archivy.search import search, search_frontmatter_tags
 from archivy.config import Config
@@ -264,7 +264,10 @@ def login():
             flash("Login successful!", "success")
 
             next_url = request.args.get("next")
-            return redirect(next_url or "/")
+            if next_url and is_safe_redirect_url(next_url):
+                return redirect(next_url)
+            else:
+                return redirect("/")
 
         flash("Invalid credentials", "error")
         return redirect("/login")

programming_language: Python