uploadserver 6.0.2__tar.gz → 6.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uploadserver
3
- Version: 6.0.2
3
+ Version: 6.0.3
4
4
  Summary: Python's http.server extended to include a file upload page
5
5
  Home-page: https://github.com/Densaugeo/uploadserver
6
6
  Author: Densaugeo
@@ -203,6 +203,11 @@ options:
203
203
  - File field in upload form renamed from `file_1` to `files`, to reflect support for multiple file upload. Scripts using cURL will need to be upadted with the new field name.
204
204
  - Successful uploads now respond with 204 No Content instead of 200 OK, so that cURL will not default to printing the upload page at the terminal.
205
205
 
206
+ ## Security Issues
207
+
208
+ - Patched in `6.0.3`: Timing side channel. Introduced in `1.0.0`. Unpatched versions using the `--basic-auth`, `--basic-auth-upload`, or `--token` options are vulnerable to revealing password information through response timing.
209
+ - Patched in `6.0.2`: DoS vulnerability. Introduced in `4.1.0`. Unpatched versions using the `--basic-auth` or `--basic-auth-upload` options generate stack traces in response to certain requests, which could be used to pollute logs or exhaust storage.
210
+
206
211
  ## Acknowledgements
207
212
 
208
213
  Much of `main()` was copied from Python's `http.server`.
@@ -217,4 +222,6 @@ Thanks to shuangye for finding an easy way to handle large file uploads, and imp
217
222
 
218
223
  Thanks to abbbe for adding HTTP basic auth (has now replaced the token option).
219
224
 
225
+ Thanks to 0xLordMahesh for reporting the timing side channel and DoS vulnerabilities patched in 6.0.2 and 6.0.3.
226
+
220
227
  Thanks to SimarMugattarov, theo543, and poshul for minor updates.
@@ -180,6 +180,11 @@ options:
180
180
  - File field in upload form renamed from `file_1` to `files`, to reflect support for multiple file upload. Scripts using cURL will need to be upadted with the new field name.
181
181
  - Successful uploads now respond with 204 No Content instead of 200 OK, so that cURL will not default to printing the upload page at the terminal.
182
182
 
183
+ ## Security Issues
184
+
185
+ - Patched in `6.0.3`: Timing side channel. Introduced in `1.0.0`. Unpatched versions using the `--basic-auth`, `--basic-auth-upload`, or `--token` options are vulnerable to revealing password information through response timing.
186
+ - Patched in `6.0.2`: DoS vulnerability. Introduced in `4.1.0`. Unpatched versions using the `--basic-auth` or `--basic-auth-upload` options generate stack traces in response to certain requests, which could be used to pollute logs or exhaust storage.
187
+
183
188
  ## Acknowledgements
184
189
 
185
190
  Much of `main()` was copied from Python's `http.server`.
@@ -194,4 +199,6 @@ Thanks to shuangye for finding an easy way to handle large file uploads, and imp
194
199
 
195
200
  Thanks to abbbe for adding HTTP basic auth (has now replaced the token option).
196
201
 
202
+ Thanks to 0xLordMahesh for reporting the timing side channel and DoS vulnerabilities patched in 6.0.2 and 6.0.3.
203
+
197
204
  Thanks to SimarMugattarov, theo543, and poshul for minor updates.
@@ -5,7 +5,7 @@ with open('README.md', 'r') as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name='uploadserver',
8
- version='6.0.2',
8
+ version='6.0.3',
9
9
  author='Densaugeo',
10
10
  author_email='author@example.com',
11
11
  description='Python\'s http.server extended to include a file upload page',
@@ -1,5 +1,5 @@
1
1
  import http.server, http, pathlib, sys, argparse, ssl, os, builtins, tempfile
2
- import ipaddress
2
+ import ipaddress, hmac
3
3
  import base64, binascii, functools, contextlib
4
4
 
5
5
  # Does not seem to do be used, but leaving this import out causes uploadserver
@@ -168,7 +168,7 @@ def receive_upload(handler: http.server.BaseHTTPRequestHandler,
168
168
 
169
169
  # True return type is tuple[bool, str | None], but Python 3.9 doesn't support |
170
170
  def check_http_authentication_header(
171
- handler: http.server.BaseHTTPRequestHandler, auth: str,
171
+ handler: http.server.BaseHTTPRequestHandler, auth: tuple[bytes, bytes],
172
172
  ) -> tuple[bool, str]:
173
173
  auth_header = handler.headers.get('Authorization')
174
174
  if auth_header is None:
@@ -187,9 +187,11 @@ handler: http.server.BaseHTTPRequestHandler, auth: str,
187
187
  return (False, 'Credentials incorrectly formatted')
188
188
 
189
189
  http_username, http_password = http_username_password.split(':', 1)
190
- args_username, args_password = auth.split(':', 1)
191
- if http_username != args_username: return (False, 'Bad username')
192
- if http_password != args_password: return (False, 'Bad password')
190
+ args_username, args_password = auth
191
+ if not hmac.compare_digest(bytes(http_username, 'utf8'), args_username):
192
+ return (False, 'Bad username')
193
+ if not hmac.compare_digest(bytes(http_password, 'utf8'), args_password):
194
+ return (False, 'Bad password')
193
195
 
194
196
  return (True, None)
195
197
 
@@ -206,12 +208,12 @@ def check_http_authentication(handler: http.server.BaseHTTPRequestHandler
206
208
  return True
207
209
 
208
210
  # If only --basic-auth is supplied, it's used for all requests
209
- valid, message = check_http_authentication_header(handler, args.basic_auth)
211
+ valid, message = check_http_authentication_header(handler, basic_auth)
210
212
  else:
211
213
  # If --basic-auth-upload is supplied, it's always required for /upload
212
214
  if handler.path == '/upload':
213
215
  valid, message = check_http_authentication_header(handler,
214
- args.basic_auth_upload)
216
+ basic_auth_upload)
215
217
  else:
216
218
  # For paths outside /upload, no auth is required when --basic-auth
217
219
  # is not supplied
@@ -221,10 +223,12 @@ def check_http_authentication(handler: http.server.BaseHTTPRequestHandler
221
223
  # For paths outise /upload, if both auths are supplied both are
222
224
  # accepted
223
225
  else:
224
- valid, message = check_http_authentication_header(handler, args.basic_auth)
226
+ valid, message = check_http_authentication_header(handler,
227
+ basic_auth)
225
228
 
226
229
  if not valid:
227
- valid, message = check_http_authentication_header(handler, args.basic_auth_upload)
230
+ valid, message = check_http_authentication_header(handler,
231
+ basic_auth_upload)
228
232
 
229
233
  if not valid:
230
234
  handler.log_message('Request rejected (%s)', message)
@@ -422,7 +426,7 @@ def serve_forever():
422
426
  )
423
427
 
424
428
  def main():
425
- global args
429
+ global args, basic_auth, basic_auth_upload
426
430
 
427
431
  parser = argparse.ArgumentParser()
428
432
  parser.add_argument('port', type=int, default=8000, nargs='?',
@@ -463,4 +467,13 @@ def main():
463
467
  'argument.'
464
468
  )
465
469
 
470
+ # Cache bytes() conversions of auth values, to prevent leaking information
471
+ # via timing (issue #53)
472
+ if args.basic_auth:
473
+ username, password = args.basic_auth.split(':', 1)
474
+ basic_auth = (bytes(username, 'utf8'), bytes(password, 'utf8'))
475
+ if args.basic_auth_upload:
476
+ username, password = args.basic_auth_upload.split(':', 1)
477
+ basic_auth_upload = (bytes(username, 'utf8'), bytes(password, 'utf8'))
478
+
466
479
  serve_forever()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uploadserver
3
- Version: 6.0.2
3
+ Version: 6.0.3
4
4
  Summary: Python's http.server extended to include a file upload page
5
5
  Home-page: https://github.com/Densaugeo/uploadserver
6
6
  Author: Densaugeo
@@ -203,6 +203,11 @@ options:
203
203
  - File field in upload form renamed from `file_1` to `files`, to reflect support for multiple file upload. Scripts using cURL will need to be upadted with the new field name.
204
204
  - Successful uploads now respond with 204 No Content instead of 200 OK, so that cURL will not default to printing the upload page at the terminal.
205
205
 
206
+ ## Security Issues
207
+
208
+ - Patched in `6.0.3`: Timing side channel. Introduced in `1.0.0`. Unpatched versions using the `--basic-auth`, `--basic-auth-upload`, or `--token` options are vulnerable to revealing password information through response timing.
209
+ - Patched in `6.0.2`: DoS vulnerability. Introduced in `4.1.0`. Unpatched versions using the `--basic-auth` or `--basic-auth-upload` options generate stack traces in response to certain requests, which could be used to pollute logs or exhaust storage.
210
+
206
211
  ## Acknowledgements
207
212
 
208
213
  Much of `main()` was copied from Python's `http.server`.
@@ -217,4 +222,6 @@ Thanks to shuangye for finding an easy way to handle large file uploads, and imp
217
222
 
218
223
  Thanks to abbbe for adding HTTP basic auth (has now replaced the token option).
219
224
 
225
+ Thanks to 0xLordMahesh for reporting the timing side channel and DoS vulnerabilities patched in 6.0.2 and 6.0.3.
226
+
220
227
  Thanks to SimarMugattarov, theo543, and poshul for minor updates.
File without changes
File without changes