| 810 | self.assertEqual(os.path.basename(obj.testfile.path), "MiXeD_cAsE.txt") |
| 811 | |
| 812 | def test_filename_traversal_upload(self): |
| 813 | os.makedirs(UPLOAD_TO, exist_ok=True) |
| 814 | tests = [ |
| 815 | "../test.txt", |
| 816 | "../test.txt", |
| 817 | ] |
| 818 | for file_name in tests: |
| 819 | with self.subTest(file_name=file_name): |
| 820 | payload = client.FakePayload() |
| 821 | payload.write( |
| 822 | "\r\n".join( |
| 823 | [ |
| 824 | "--" + client.BOUNDARY, |
| 825 | 'Content-Disposition: form-data; name="my_file"; ' |
| 826 | 'filename="%s";' % file_name, |
| 827 | "Content-Type: text/plain", |
| 828 | "", |
| 829 | "file contents.\r\n", |
| 830 | "\r\n--" + client.BOUNDARY + "--\r\n", |
| 831 | ] |
| 832 | ), |
| 833 | ) |
| 834 | r = { |
| 835 | "CONTENT_LENGTH": len(payload), |
| 836 | "CONTENT_TYPE": client.MULTIPART_CONTENT, |
| 837 | "PATH_INFO": "/upload_traversal/", |
| 838 | "REQUEST_METHOD": "POST", |
| 839 | "wsgi.input": payload, |
| 840 | } |
| 841 | response = self.client.request(**r) |
| 842 | result = response.json() |
| 843 | self.assertEqual(response.status_code, 200) |
| 844 | self.assertEqual(result["file_name"], "test.txt") |
| 845 | self.assertIs( |
| 846 | os.path.exists(os.path.join(MEDIA_ROOT, "test.txt")), |
| 847 | False, |
| 848 | ) |
| 849 | self.assertIs( |
| 850 | os.path.exists(os.path.join(UPLOAD_TO, "test.txt")), |
| 851 | True, |
| 852 | ) |
| 853 | |
| 854 | |
| 855 | @override_settings(MEDIA_ROOT=MEDIA_ROOT) |