From a729f02ed2e4ca4336c9f863d1593e1d402eff8a Mon Sep 17 00:00:00 2001 From: jkcso Date: Thu, 16 Jan 2025 16:34:30 +0000 Subject: [PATCH] improves the solution in Season-1/Level-3 --- Season-1/Level-3/solution.py | 91 ++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/Season-1/Level-3/solution.py b/Season-1/Level-3/solution.py index 2a2de8c..fff1e55 100644 --- a/Season-1/Level-3/solution.py +++ b/Season-1/Level-3/solution.py @@ -1,34 +1,65 @@ -import os +# Model solution follows -# Example of a secure function that doesn't suffer from path traversal -def safe_path(path): - base_dir = os.path.dirname(os.path.abspath(__file__)) - filepath = os.path.normpath(os.path.join(base_dir, path)) - if base_dir != os.path.commonpath([base_dir, filepath]): - return None - return filepath - -# Following the above, this is the secure version of the respective function on code.py -def get_prof_picture(self, path=None): - # setting a profile picture is optional - if not path: - pass - - # defends against path traversal attacks - if path.startswith('/') or path.startswith('..'): - return None - - # builds path - base_dir = os.path.dirname(os.path.abspath(__file__)) - prof_picture_path = os.path.normpath(os.path.join(base_dir, path)) - if base_dir != os.path.commonpath([base_dir, prof_picture_path]): - return None - - with open(prof_picture_path, 'rb') as pic: - picture = bytearray(pic.read()) - - # assume that image is returned on screen after this - return prof_picture_path +import os +from flask import Flask, request + +### Unrelated to the exercise -- Starts here -- Please ignore +app = Flask(__name__) +@app.route("/") +def source(): + TaxPayer('foo', 'bar').get_tax_form_attachment(request.args["input"]) + TaxPayer('foo', 'bar').get_prof_picture(request.args["input"]) +### Unrelated to the exercise -- Ends here -- Please ignore + +class TaxPayer: + + def __init__(self, username, password): + self.username = username + self.password = password + self.prof_picture = None + self.tax_form_attachment = None + + # returns the path of an optional profile picture that users can set + def get_prof_picture(self, path=None): + # setting a profile picture is optional + if not path: + pass + + # defends against path traversal attacks + if path.startswith('/') or path.startswith('..'): + return None + + # builds path + base_dir = os.path.dirname(os.path.abspath(__file__)) + prof_picture_path = os.path.normpath(os.path.join(base_dir, path)) + if base_dir != os.path.commonpath([base_dir, prof_picture_path]): + return None + + with open(prof_picture_path, 'rb') as pic: + picture = bytearray(pic.read()) + + # assume that image is returned on screen after this + return prof_picture_path + + # returns the path of an attached tax form that every user should submit + def get_tax_form_attachment(self, path=None): + tax_data = None + + # A tax form is required + if not path: + raise Exception("Error: Tax form is required for all users") + + # Validate the path to prevent path traversal attacks + base_dir = os.path.dirname(os.path.abspath(__file__)) + tax_form_path = os.path.normpath(os.path.join(base_dir, path)) + if base_dir != os.path.commonpath([base_dir, tax_form_path]): + return None + + with open(tax_form_path, 'rb') as form: + tax_data = bytearray(form.read()) + + # assume that tax data is returned on screen after this + return tax_form_path # Solution explanation