Make static folder URL have a high-entropy random path, to avoid filename collisions with files getting shared

This commit is contained in:
Micah Lee 2019-05-22 20:07:35 -07:00
parent 91238366b1
commit 41be429b91
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
13 changed files with 60 additions and 47 deletions

View File

@ -34,7 +34,8 @@ class ReceiveModeWeb(object):
@self.web.app.route("/") @self.web.app.route("/")
def index(): def index():
self.web.add_request(self.web.REQUEST_LOAD, request.path) self.web.add_request(self.web.REQUEST_LOAD, request.path)
r = make_response(render_template('receive.html')) r = make_response(render_template('receive.html',
static_url_path=self.web.static_url_path))
return self.web.add_security_headers(r) return self.web.add_security_headers(r)
@self.web.app.route("/upload", methods=['POST']) @self.web.app.route("/upload", methods=['POST'])
@ -105,10 +106,12 @@ class ReceiveModeWeb(object):
return redirect('/') return redirect('/')
else: else:
if ajax: if ajax:
return json.dumps({"new_body": render_template('thankyou.html')}) return json.dumps({
"new_body": render_template('thankyou.html', static_url_path=self.web.static_url_path)
})
else: else:
# It was the last upload and the timer ran out # It was the last upload and the timer ran out
r = make_response(render_template('thankyou.html')) r = make_response(render_template('thankyou.html'), static_url_path=self.web.static_url_path)
return self.web.add_security_headers(r) return self.web.add_security_headers(r)
@self.web.app.route("/upload-ajax", methods=['POST']) @self.web.app.route("/upload-ajax", methods=['POST'])

View File

@ -55,7 +55,8 @@ class ShareModeWeb(object):
# currently a download # currently a download
deny_download = not self.web.stay_open and self.download_in_progress deny_download = not self.web.stay_open and self.download_in_progress
if deny_download: if deny_download:
r = make_response(render_template('denied.html')) r = make_response(render_template('denied.html'),
static_url_path=self.web.static_url_path)
return self.web.add_security_headers(r) return self.web.add_security_headers(r)
# If download is allowed to continue, serve download page # If download is allowed to continue, serve download page
@ -70,7 +71,8 @@ class ShareModeWeb(object):
filename=os.path.basename(self.download_filename), filename=os.path.basename(self.download_filename),
filesize=self.filesize, filesize=self.filesize,
filesize_human=self.common.human_readable_filesize(self.download_filesize), filesize_human=self.common.human_readable_filesize(self.download_filesize),
is_zipped=self.is_zipped)) is_zipped=self.is_zipped,
static_url_path=self.web.static_url_path))
return self.web.add_security_headers(r) return self.web.add_security_headers(r)
@self.web.app.route("/download") @self.web.app.route("/download")
@ -82,7 +84,8 @@ class ShareModeWeb(object):
# currently a download # currently a download
deny_download = not self.web.stay_open and self.download_in_progress deny_download = not self.web.stay_open and self.download_in_progress
if deny_download: if deny_download:
r = make_response(render_template('denied.html')) r = make_response(render_template('denied.html',
static_url_path=self.web.static_url_path))
return self.web.add_security_headers(r) return self.web.add_security_headers(r)
# Each download has a unique id # Each download has a unique id

View File

@ -51,8 +51,13 @@ class Web(object):
self.common = common self.common = common
self.common.log('Web', '__init__', 'is_gui={}, mode={}'.format(is_gui, mode)) self.common.log('Web', '__init__', 'is_gui={}, mode={}'.format(is_gui, mode))
# The static URL path has a 128-bit random number in it to avoid having name
# collisions with files that might be getting shared
self.static_url_path = '/static_{}'.format(self.common.random_string(16))
# The flask app # The flask app
self.app = Flask(__name__, self.app = Flask(__name__,
static_url_path=self.static_url_path,
static_folder=self.common.get_resource_path('static'), static_folder=self.common.get_resource_path('static'),
template_folder=self.common.get_resource_path('templates')) template_folder=self.common.get_resource_path('templates'))
self.app.secret_key = self.common.random_string(8) self.app.secret_key = self.common.random_string(8)
@ -163,7 +168,8 @@ class Web(object):
""" """
Display instructions for disabling Tor Browser's NoScript XSS setting Display instructions for disabling Tor Browser's NoScript XSS setting
""" """
r = make_response(render_template('receive_noscript_xss.html')) r = make_response(render_template('receive_noscript_xss.html',
static_url_path=self.static_url_path))
return self.add_security_headers(r) return self.add_security_headers(r)
def error401(self): def error401(self):
@ -181,18 +187,18 @@ class Web(object):
self.force_shutdown() self.force_shutdown()
print("Someone has made too many wrong attempts to guess your password, so OnionShare has stopped the server. Start sharing again and send the recipient a new address to share.") print("Someone has made too many wrong attempts to guess your password, so OnionShare has stopped the server. Start sharing again and send the recipient a new address to share.")
r = make_response(render_template('401.html'), 401) r = make_response(render_template('401.html', static_url_path=self.static_url_path), 401)
return self.add_security_headers(r) return self.add_security_headers(r)
def error404(self): def error404(self):
self.add_request(Web.REQUEST_OTHER, request.path) self.add_request(Web.REQUEST_OTHER, request.path)
r = make_response(render_template('404.html'), 404) r = make_response(render_template('404.html', static_url_path=self.static_url_path), 404)
return self.add_security_headers(r) return self.add_security_headers(r)
def error403(self): def error403(self):
self.add_request(Web.REQUEST_OTHER, request.path) self.add_request(Web.REQUEST_OTHER, request.path)
r = make_response(render_template('403.html'), 403) r = make_response(render_template('403.html', static_url_path=self.static_url_path), 403)
return self.add_security_headers(r) return self.add_security_headers(r)
def add_security_headers(self, r): def add_security_headers(self, r):

View File

@ -131,7 +131,8 @@ class WebsiteModeWeb(object):
r = make_response(render_template('listing.html', r = make_response(render_template('listing.html',
path=path, path=path,
files=files, files=files,
dirs=dirs)) dirs=dirs,
static_url_path=self.web.static_url_path))
return self.web.add_security_headers(r) return self.web.add_security_headers(r)
def set_file_info(self, filenames): def set_file_info(self, filenames):

View File

@ -3,14 +3,14 @@
<head> <head>
<title>OnionShare: 401 Unauthorized Access</title> <title>OnionShare: 401 Unauthorized Access</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon" /> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" />
<link rel="stylesheet" rel="subresource" type="text/css" href="/static/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
<body> <body>
<div class="info-wrapper"> <div class="info-wrapper">
<div class="info"> <div class="info">
<p><img class="logo" src="/static/img/logo_large.png" title="OnionShare"></p> <p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
<p class="info-header">401 Unauthorized Access</p> <p class="info-header">401 Unauthorized Access</p>
</div> </div>
</div> </div>

View File

@ -3,14 +3,14 @@
<head> <head>
<title>OnionShare: 403 Forbidden</title> <title>OnionShare: 403 Forbidden</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon" /> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" />
<link rel="stylesheet" rel="subresource" type="text/css" href="/static/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
<body> <body>
<div class="info-wrapper"> <div class="info-wrapper">
<div class="info"> <div class="info">
<p><img class="logo" src="/static/img/logo_large.png" title="OnionShare"></p> <p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
<p class="info-header">You are not allowed to perform that action at this time.</p> <p class="info-header">You are not allowed to perform that action at this time.</p>
</div> </div>
</div> </div>

View File

@ -3,14 +3,14 @@
<head> <head>
<title>OnionShare: 404 Not Found</title> <title>OnionShare: 404 Not Found</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="/static/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
<body> <body>
<div class="info-wrapper"> <div class="info-wrapper">
<div class="info"> <div class="info">
<p><img class="logo" src="/static/img/logo_large.png" title="OnionShare"></p> <p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
<p class="info-header">404 Not Found</p> <p class="info-header">404 Not Found</p>
</div> </div>
</div> </div>

View File

@ -3,7 +3,7 @@
<head> <head>
<title>OnionShare</title> <title>OnionShare</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon" /> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" />
</head> </head>
<body> <body>

View File

@ -2,13 +2,13 @@
<html> <html>
<head> <head>
<title>OnionShare</title> <title>OnionShare</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon" /> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" />
<link href="/static/css/style.css" rel="stylesheet" type="text/css" /> <link href="{{ static_url_path }}/css/style.css" rel="stylesheet" type="text/css" />
</head> </head>
<body> <body>
<header class="clearfix"> <header class="clearfix">
<img class="logo" src="/static/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>OnionShare</h1>
</header> </header>
@ -22,7 +22,7 @@
{% for info in dirs %} {% for info in dirs %}
<tr> <tr>
<td> <td>
<img width="30" height="30" title="" alt="" src="/static/img/web_folder.png" /> <img width="30" height="30" title="" alt="" src="{{ static_url_path }}/img/web_folder.png" />
<a href="{{ info.basename }}"> <a href="{{ info.basename }}">
{{ info.basename }} {{ info.basename }}
</a> </a>
@ -34,7 +34,7 @@
{% for info in files %} {% for info in files %}
<tr> <tr>
<td> <td>
<img width="30" height="30" title="" alt="" src="/static/img/web_file.png" /> <img width="30" height="30" title="" alt="" src="{{ static_url_path }}/img/web_file.png" />
<a href="{{ info.basename }}"> <a href="{{ info.basename }}">
{{ info.basename }} {{ info.basename }}
</a> </a>

View File

@ -2,13 +2,13 @@
<html> <html>
<head> <head>
<title>OnionShare</title> <title>OnionShare</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="/static/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
<body> <body>
<header class="clearfix"> <header class="clearfix">
<img class="logo" src="/static/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>OnionShare</h1>
</header> </header>
@ -19,14 +19,14 @@
--> -->
<div id="noscript"> <div id="noscript">
<p> <p>
<img src="/static/img/warning.png" title="Warning" /><strong>Warning:</strong> Due to a bug in Tor Browser and Firefox, uploads <img src="{{ static_url_path }}/img/warning.png" title="Warning" /><strong>Warning:</strong> Due to a bug in Tor Browser and Firefox, uploads
sometimes never finish. To upload reliably, either set your Tor Browser sometimes never finish. To upload reliably, either set your Tor Browser
<a rel="noreferrer" target="_blank" href="https://tb-manual.torproject.org/en-US/security-slider/">security slider</a> <a rel="noreferrer" target="_blank" href="https://tb-manual.torproject.org/en-US/security-slider/">security slider</a>
to Standard or to Standard or
<a target="_blank" href="/noscript-xss-instructions">turn off your Tor Browser's NoScript XSS setting</a>.</p> <a target="_blank" href="/noscript-xss-instructions">turn off your Tor Browser's NoScript XSS setting</a>.</p>
</div> </div>
<p><img class="logo" src="/static/img/logo_large.png" title="OnionShare"></p> <p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
<p class="upload-header">Send Files</p> <p class="upload-header">Send Files</p>
<p class="upload-description">Select the files you want to send, then click "Send Files"...</p> <p class="upload-description">Select the files you want to send, then click "Send Files"...</p>
@ -51,8 +51,8 @@
</form> </form>
</div> </div>
<script src="/static/js/receive-noscript.js"></script> <script src="{{ static_url_path }}/js/receive-noscript.js"></script>
<script src="/static/js/jquery-3.4.0.min.js"></script> <script src="{{ static_url_path }}/js/jquery-3.4.0.min.js"></script>
<script async src="/static/js/receive.js"></script> <script async src="{{ static_url_path }}/js/receive.js"></script>
</body> </body>
</html> </html>

View File

@ -2,13 +2,13 @@
<html> <html>
<head> <head>
<title>OnionShare</title> <title>OnionShare</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="/static/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
<body> <body>
<header class="clearfix"> <header class="clearfix">
<img class="logo" src="/static/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>OnionShare</h1>
</header> </header>

View File

@ -3,8 +3,8 @@
<head> <head>
<title>OnionShare</title> <title>OnionShare</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="/static/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
<meta name="onionshare-filename" content="{{ filename }}"> <meta name="onionshare-filename" content="{{ filename }}">
<meta name="onionshare-filesize" content="{{ filesize }}"> <meta name="onionshare-filesize" content="{{ filesize }}">
</head> </head>
@ -18,7 +18,7 @@
<li><a class="button" href='/download'>Download Files</a></li> <li><a class="button" href='/download'>Download Files</a></li>
</ul> </ul>
</div> </div>
<img class="logo" src="/static/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>OnionShare</h1>
</header> </header>
@ -31,7 +31,7 @@
{% for info in file_info.dirs %} {% for info in file_info.dirs %}
<tr> <tr>
<td> <td>
<img width="30" height="30" title="" alt="" src="/static/img/web_folder.png" /> <img width="30" height="30" title="" alt="" src="{{ static_url_path }}/img/web_folder.png" />
{{ info.basename }} {{ info.basename }}
</td> </td>
<td>{{ info.size_human }}</td> <td>{{ info.size_human }}</td>
@ -41,7 +41,7 @@
{% for info in file_info.files %} {% for info in file_info.files %}
<tr> <tr>
<td> <td>
<img width="30" height="30" title="" alt="" src="/static/img/web_file.png" /> <img width="30" height="30" title="" alt="" src="{{ static_url_path }}/img/web_file.png" />
{{ info.basename }} {{ info.basename }}
</td> </td>
<td>{{ info.size_human }}</td> <td>{{ info.size_human }}</td>
@ -49,7 +49,7 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<script async src="/static/js/send.js" charset="utf-8"></script> <script async src="{{ static_url_path }}/js/send.js" charset="utf-8"></script>
</body> </body>
</html> </html>

View File

@ -3,19 +3,19 @@
<head> <head>
<title>OnionShare is closed</title> <title>OnionShare is closed</title>
<link href="/static/img/favicon.ico" rel="icon" type="image/x-icon"> <link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon">
<link rel="stylesheet" rel="subresource" type="text/css" href="/static/css/style.css" media="all"> <link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
</head> </head>
<body> <body>
<header class="clearfix"> <header class="clearfix">
<img class="logo" src="/static/img/logo.png" title="OnionShare"> <img class="logo" src="{{ static_url_path }}/img/logo.png" title="OnionShare">
<h1>OnionShare</h1> <h1>OnionShare</h1>
</header> </header>
<div class="info-wrapper"> <div class="info-wrapper">
<div class="info"> <div class="info">
<p><img class="logo" src="/static/img/logo_large.png" title="OnionShare"></p> <p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
<p class="info-header">Thank you for using OnionShare</p> <p class="info-header">Thank you for using OnionShare</p>
<p class="info-description">You may now close this window.</p> <p class="info-description">You may now close this window.</p>
</div> </div>