From 224a938c1895d2b3ac58bafc8c4f66a4f5b9f094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez=20Flores?= Date: Tue, 9 Jan 2024 14:19:43 +0000 Subject: [PATCH] Fixed security issue where the user could access unathorized files by inputting a relative path into the API --- resources/src/server/rest.py | 7 +++++-- resources/tests/test_rest.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/resources/src/server/rest.py b/resources/src/server/rest.py index aedda1f..bb04f8d 100644 --- a/resources/src/server/rest.py +++ b/resources/src/server/rest.py @@ -105,8 +105,11 @@ def calculate(): else: try: decoded_model = base64.b64decode(model).decode('utf-8') - model_path = os.path.join(self.ai_path, f"{decoded_model}.keras") - if not os.path.isfile(model_path): + model_path = os.path.normpath(os.path.join(self.ai_path, f"{decoded_model}.keras")) + if not model_path.startswith(os.path.normpath(self.ai_path)): + logger.logger.error(f"Attempted unauthorized file access: {decoded_model}") + model = 'default' + elif not os.path.isfile(model_path): logger.logger.error(f"Model {decoded_model} does not exist") model = 'default' else: diff --git a/resources/tests/test_rest.py b/resources/tests/test_rest.py index b49ba54..70e7fa6 100644 --- a/resources/tests/test_rest.py +++ b/resources/tests/test_rest.py @@ -68,6 +68,18 @@ def test_calculate_endpoint_invalid_model(self, mock_isfile, mock_execute_model, self.assertEqual(response.status_code, 200) self.assertEqual(response.get_json(), self.output_data) + @patch('druid.client.DruidClient.execute_query') + @patch('ai.shallow_outliers.ShallowOutliers.execute_prediction_model') + @patch('os.path.isfile') + def test_calculate_endpoint_unathorized_model_access(self, mock_isfile, mock_execute_model, mock_query): + mock_execute_model.return_value = self.output_data + mock_query.return_value = {} + mock_isfile.return_value = False + data = {'model':'Li90ZXN0', 'query':'eyJhc2RmIjoiYXNkZiJ9'} + with self.api_server.app.test_client().post('/api/v1/outliers', data=data) as response: + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_json(), self.output_data) + @patch('druid.client.DruidClient.execute_query') @patch('ai.shallow_outliers.ShallowOutliers.execute_prediction_model') @patch('os.path.isfile')