summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfriedli2020-05-08 09:10:18 -0700
committerjfriedli2020-05-08 09:10:18 -0700
commit853ace7d83424f85d903f6ffe2352bf41f86b7ce (patch)
tree91f33ae06272bbeda564b0aabe1baa4aaf8e2d87
parent9157dee69f69eeba521ff0a5f5cc651d3629ae6c (diff)
Resolve "Fuzzing Errors /api/upload"
-rw-r--r--matweb/frontend.py6
-rw-r--r--matweb/rest_api.py10
-rw-r--r--matweb/utils.py2
-rw-r--r--test/test.py12
-rw-r--r--test/test_api.py21
5 files changed, 46 insertions, 5 deletions
diff --git a/matweb/frontend.py b/matweb/frontend.py
index 2e25467..8295f4e 100644
--- a/matweb/frontend.py
+++ b/matweb/frontend.py
@@ -53,8 +53,12 @@ def upload_file():
53 if not uploaded_file.filename: 53 if not uploaded_file.filename:
54 flash('No selected file') 54 flash('No selected file')
55 return redirect(request.url) 55 return redirect(request.url)
56 try:
57 filename, filepath = utils.save_file(uploaded_file, current_app.config['UPLOAD_FOLDER'])
58 except ValueError:
59 flash('Invalid Filename')
60 return redirect(request.url)
56 61
57 filename, filepath = utils.save_file(uploaded_file, current_app.config['UPLOAD_FOLDER'])
58 parser, mime = utils.get_file_parser(filepath) 62 parser, mime = utils.get_file_parser(filepath)
59 63
60 if parser is None: 64 if parser is None:
diff --git a/matweb/rest_api.py b/matweb/rest_api.py
index 4098050..a07d2d2 100644
--- a/matweb/rest_api.py
+++ b/matweb/rest_api.py
@@ -28,11 +28,15 @@ class APIUpload(Resource):
28 args = req_parser.parse_args() 28 args = req_parser.parse_args()
29 try: 29 try:
30 file_data = base64.b64decode(args['file']) 30 file_data = base64.b64decode(args['file'])
31 except binascii.Error as err: 31 except (binascii.Error, ValueError):
32 abort(400, message='Failed decoding file: ' + str(err)) 32 abort(400, message='Failed decoding file')
33 33
34 file = FileStorage(stream=io.BytesIO(file_data), filename=args['file_name']) 34 file = FileStorage(stream=io.BytesIO(file_data), filename=args['file_name'])
35 filename, filepath = utils.save_file(file, self.upload_folder) 35 try:
36 filename, filepath = utils.save_file(file, self.upload_folder)
37 except ValueError:
38 abort(400, message='Invalid Filename')
39
36 parser, mime = utils.get_file_parser(filepath) 40 parser, mime = utils.get_file_parser(filepath)
37 41
38 if parser is None: 42 if parser is None:
diff --git a/matweb/utils.py b/matweb/utils.py
index ec9b99c..20c213d 100644
--- a/matweb/utils.py
+++ b/matweb/utils.py
@@ -65,6 +65,8 @@ def get_supported_extensions():
65 65
66def save_file(file, upload_folder): 66def save_file(file, upload_folder):
67 filename = secure_filename(file.filename) 67 filename = secure_filename(file.filename)
68 if not filename:
69 raise ValueError('Invalid Filename')
68 filepath = os.path.join(upload_folder, filename) 70 filepath = os.path.join(upload_folder, filename)
69 file.save(os.path.join(filepath)) 71 file.save(os.path.join(filepath))
70 return filename, filepath 72 return filename, filepath
diff --git a/test/test.py b/test/test.py
index 2d09662..7431881 100644
--- a/test/test.py
+++ b/test/test.py
@@ -179,6 +179,18 @@ class Mat2WebTestCase(TestCase):
179 self.assertIn(b'.mp2', rv.data) 179 self.assertIn(b'.mp2', rv.data)
180 self.assertEqual(rv.status_code, 200) 180 self.assertEqual(rv.status_code, 200)
181 181
182 def test_get_upload_naughty_input(self):
183 rv = self.client.post(
184 '/',
185 data=dict(
186 file=(io.BytesIO(b"a"), '﷽'),
187 ),
188 follow_redirects=True
189 )
190 self.assertEqual(rv.status_code, 200)
191 self.assertIn(b'Invalid Filename', rv.data)
192
193
182 194
183if __name__ == '__main__': 195if __name__ == '__main__':
184 unittest.main() 196 unittest.main()
diff --git a/test/test_api.py b/test/test_api.py
index 4925d9e..af736af 100644
--- a/test/test_api.py
+++ b/test/test_api.py
@@ -70,7 +70,7 @@ class Mat2APITestCase(unittest.TestCase):
70 70
71 self.assertEqual(request.status_code, 400) 71 self.assertEqual(request.status_code, 400)
72 error = request.get_json()['message'] 72 error = request.get_json()['message']
73 self.assertEqual(error, 'Failed decoding file: Incorrect padding') 73 self.assertEqual(error, 'Failed decoding file')
74 74
75 def test_api_not_supported(self): 75 def test_api_not_supported(self):
76 request = self.app.post('/api/upload', 76 request = self.app.post('/api/upload',
@@ -400,6 +400,25 @@ class Mat2APITestCase(unittest.TestCase):
400 request = app.get(download_link) 400 request = app.get(download_link)
401 self.assertEqual(code, request.status_code) 401 self.assertEqual(code, request.status_code)
402 402
403 def test_upload_naughty_input(self):
404 request = self.app.post('/api/upload',
405 data='{"file_name": "\\\\", '
406 '"file": "\\\\"}',
407 headers={'content-type': 'application/json'}
408 )
409 error_message = request.get_json()['message']
410 self.assertEqual(400, request.status_code)
411 self.assertEqual("Invalid Filename", error_message)
412
413 request = self.app.post('/api/upload',
414 data='{"file_name": "﷽", '
415 '"file": "﷽"}',
416 headers={'content-type': 'application/json'}
417 )
418 error_message = request.get_json()['message']
419 self.assertEqual(400, request.status_code)
420 self.assertEqual("Failed decoding file", error_message)
421
403 422
404if __name__ == '__main__': 423if __name__ == '__main__':
405 unittest.main() 424 unittest.main()