uploadserver 6.0.2__tar.gz → 6.0.4__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.
- {uploadserver-6.0.2/uploadserver.egg-info → uploadserver-6.0.4}/PKG-INFO +9 -2
- {uploadserver-6.0.2 → uploadserver-6.0.4}/README.md +8 -1
- {uploadserver-6.0.2 → uploadserver-6.0.4}/setup.py +1 -1
- {uploadserver-6.0.2 → uploadserver-6.0.4}/uploadserver/__init__.py +28 -11
- {uploadserver-6.0.2 → uploadserver-6.0.4/uploadserver.egg-info}/PKG-INFO +9 -2
- {uploadserver-6.0.2 → uploadserver-6.0.4}/LICENSE +0 -0
- {uploadserver-6.0.2 → uploadserver-6.0.4}/setup.cfg +0 -0
- {uploadserver-6.0.2 → uploadserver-6.0.4}/uploadserver/__main__.py +0 -0
- {uploadserver-6.0.2 → uploadserver-6.0.4}/uploadserver/cgi.py +0 -0
- {uploadserver-6.0.2 → uploadserver-6.0.4}/uploadserver.egg-info/SOURCES.txt +0 -0
- {uploadserver-6.0.2 → uploadserver-6.0.4}/uploadserver.egg-info/dependency_links.txt +0 -0
- {uploadserver-6.0.2 → uploadserver-6.0.4}/uploadserver.egg-info/entry_points.txt +0 -0
- {uploadserver-6.0.2 → uploadserver-6.0.4}/uploadserver.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uploadserver
|
|
3
|
-
Version: 6.0.
|
|
3
|
+
Version: 6.0.4
|
|
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
|
|
|
220
|
-
Thanks to
|
|
225
|
+
Thanks to 0xLordMahesh for reporting the timing side channel and DoS vulnerabilities patched in 6.0.2 and 6.0.3.
|
|
226
|
+
|
|
227
|
+
Thanks to SimarMugattarov, theo543, poshul, and OnkarRuikar 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
|
|
|
197
|
-
Thanks to
|
|
202
|
+
Thanks to 0xLordMahesh for reporting the timing side channel and DoS vulnerabilities patched in 6.0.2 and 6.0.3.
|
|
203
|
+
|
|
204
|
+
Thanks to SimarMugattarov, theo543, poshul, and OnkarRuikar for minor updates.
|
|
@@ -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
|
|
@@ -29,6 +29,9 @@ def get_upload_page(theme: str) -> bytes:
|
|
|
29
29
|
</head>
|
|
30
30
|
<body>
|
|
31
31
|
<h1>File Upload</h1>
|
|
32
|
+
<hr />
|
|
33
|
+
<a href="/">File Download</a> (back to download page)
|
|
34
|
+
<hr />
|
|
32
35
|
<form action="upload" method="POST" enctype="multipart/form-data">
|
|
33
36
|
<input name="files" type="file" multiple />
|
|
34
37
|
<br />
|
|
@@ -37,6 +40,7 @@ def get_upload_page(theme: str) -> bytes:
|
|
|
37
40
|
</form>
|
|
38
41
|
<p id="task"></p>
|
|
39
42
|
<p id="status"></p>
|
|
43
|
+
<hr />
|
|
40
44
|
</body>
|
|
41
45
|
<script>
|
|
42
46
|
document.getElementsByTagName('form')[0].addEventListener('submit', async e => {
|
|
@@ -83,7 +87,7 @@ def get_directory_head_injection(theme: str) -> bytes:
|
|
|
83
87
|
''', 'utf-8')
|
|
84
88
|
|
|
85
89
|
DIRECTORY_BODY_INJECTION = b'''<!-- Injected by uploadserver -->
|
|
86
|
-
<a href="/upload">File
|
|
90
|
+
<a href="/upload">File Upload</a>
|
|
87
91
|
(provided by uploadserver, all files go to server root)
|
|
88
92
|
<hr>
|
|
89
93
|
<!-- End injection by uploadserver -->
|
|
@@ -168,7 +172,7 @@ def receive_upload(handler: http.server.BaseHTTPRequestHandler,
|
|
|
168
172
|
|
|
169
173
|
# True return type is tuple[bool, str | None], but Python 3.9 doesn't support |
|
|
170
174
|
def check_http_authentication_header(
|
|
171
|
-
handler: http.server.BaseHTTPRequestHandler, auth:
|
|
175
|
+
handler: http.server.BaseHTTPRequestHandler, auth: tuple[bytes, bytes],
|
|
172
176
|
) -> tuple[bool, str]:
|
|
173
177
|
auth_header = handler.headers.get('Authorization')
|
|
174
178
|
if auth_header is None:
|
|
@@ -187,9 +191,11 @@ handler: http.server.BaseHTTPRequestHandler, auth: str,
|
|
|
187
191
|
return (False, 'Credentials incorrectly formatted')
|
|
188
192
|
|
|
189
193
|
http_username, http_password = http_username_password.split(':', 1)
|
|
190
|
-
args_username, args_password = auth
|
|
191
|
-
if
|
|
192
|
-
|
|
194
|
+
args_username, args_password = auth
|
|
195
|
+
if not hmac.compare_digest(bytes(http_username, 'utf8'), args_username):
|
|
196
|
+
return (False, 'Bad username')
|
|
197
|
+
if not hmac.compare_digest(bytes(http_password, 'utf8'), args_password):
|
|
198
|
+
return (False, 'Bad password')
|
|
193
199
|
|
|
194
200
|
return (True, None)
|
|
195
201
|
|
|
@@ -206,12 +212,12 @@ def check_http_authentication(handler: http.server.BaseHTTPRequestHandler
|
|
|
206
212
|
return True
|
|
207
213
|
|
|
208
214
|
# If only --basic-auth is supplied, it's used for all requests
|
|
209
|
-
valid, message = check_http_authentication_header(handler,
|
|
215
|
+
valid, message = check_http_authentication_header(handler, basic_auth)
|
|
210
216
|
else:
|
|
211
217
|
# If --basic-auth-upload is supplied, it's always required for /upload
|
|
212
218
|
if handler.path == '/upload':
|
|
213
219
|
valid, message = check_http_authentication_header(handler,
|
|
214
|
-
|
|
220
|
+
basic_auth_upload)
|
|
215
221
|
else:
|
|
216
222
|
# For paths outside /upload, no auth is required when --basic-auth
|
|
217
223
|
# is not supplied
|
|
@@ -221,10 +227,12 @@ def check_http_authentication(handler: http.server.BaseHTTPRequestHandler
|
|
|
221
227
|
# For paths outise /upload, if both auths are supplied both are
|
|
222
228
|
# accepted
|
|
223
229
|
else:
|
|
224
|
-
valid, message = check_http_authentication_header(handler,
|
|
230
|
+
valid, message = check_http_authentication_header(handler,
|
|
231
|
+
basic_auth)
|
|
225
232
|
|
|
226
233
|
if not valid:
|
|
227
|
-
valid, message = check_http_authentication_header(handler,
|
|
234
|
+
valid, message = check_http_authentication_header(handler,
|
|
235
|
+
basic_auth_upload)
|
|
228
236
|
|
|
229
237
|
if not valid:
|
|
230
238
|
handler.log_message('Request rejected (%s)', message)
|
|
@@ -422,7 +430,7 @@ def serve_forever():
|
|
|
422
430
|
)
|
|
423
431
|
|
|
424
432
|
def main():
|
|
425
|
-
global args
|
|
433
|
+
global args, basic_auth, basic_auth_upload
|
|
426
434
|
|
|
427
435
|
parser = argparse.ArgumentParser()
|
|
428
436
|
parser.add_argument('port', type=int, default=8000, nargs='?',
|
|
@@ -463,4 +471,13 @@ def main():
|
|
|
463
471
|
'argument.'
|
|
464
472
|
)
|
|
465
473
|
|
|
474
|
+
# Cache bytes() conversions of auth values, to prevent leaking information
|
|
475
|
+
# via timing (issue #53)
|
|
476
|
+
if args.basic_auth:
|
|
477
|
+
username, password = args.basic_auth.split(':', 1)
|
|
478
|
+
basic_auth = (bytes(username, 'utf8'), bytes(password, 'utf8'))
|
|
479
|
+
if args.basic_auth_upload:
|
|
480
|
+
username, password = args.basic_auth_upload.split(':', 1)
|
|
481
|
+
basic_auth_upload = (bytes(username, 'utf8'), bytes(password, 'utf8'))
|
|
482
|
+
|
|
466
483
|
serve_forever()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uploadserver
|
|
3
|
-
Version: 6.0.
|
|
3
|
+
Version: 6.0.4
|
|
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
|
|
|
220
|
-
Thanks to
|
|
225
|
+
Thanks to 0xLordMahesh for reporting the timing side channel and DoS vulnerabilities patched in 6.0.2 and 6.0.3.
|
|
226
|
+
|
|
227
|
+
Thanks to SimarMugattarov, theo543, poshul, and OnkarRuikar for minor updates.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|