diff --git a/src/httpapi/miscpublicapi/endpoints.py b/src/httpapi/miscpublicapi/endpoints.py index 06f481fc..eefb9788 100644 --- a/src/httpapi/miscpublicapi/endpoints.py +++ b/src/httpapi/miscpublicapi/endpoints.py @@ -83,4 +83,4 @@ class PublicEndpoints: In the future this will be done more often than on creation to speed up block sync """ - return upload.accept_upload(request) \ No newline at end of file + return upload.accept_upload(request) diff --git a/src/httpapi/security/client.py b/src/httpapi/security/client.py index b8c04ca4..5bf5d6cc 100644 --- a/src/httpapi/security/client.py +++ b/src/httpapi/security/client.py @@ -4,9 +4,13 @@ Process incoming requests to the client api server to validate that they are legitimate and not DNSR/XSRF or other local adversary """ import hmac + from flask import Blueprint, request, abort, g + from onionrservices import httpheaders from . import pluginwhitelist +import config +import logger """ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +35,11 @@ whitelist_endpoints = [ 'siteapi.siteFile', 'staticfiles.onionrhome', 'themes.getTheme', 'staticfiles.onboarding', 'staticfiles.onboardingIndex'] +remote_safe_whitelist = ['www', 'staticfiles'] + +public_remote_enabled = config.get('ui.public_remote_enabled', False) +public_remote_hostnames = config.get('ui.public_remote_hosts', []) + class ClientAPISecurity: def __init__(self, client_api): @@ -42,10 +51,23 @@ class ClientAPISecurity: @client_api_security_bp.before_app_request def validate_request(): - """Validate request has set password and is the correct hostname""" + """Validate request has set password & is the correct hostname.""" # For the purpose of preventing DNS rebinding attacks - if request.host != '%s:%s' % (client_api.host, client_api.bindPort): - abort(403) + localhost = True + if request.host != '%s:%s' % \ + (client_api.host, client_api.bindPort): + localhost = False + + if not localhost and public_remote_enabled: + if request.host not in public_remote_hostnames: + logger.warn( + f'{request.host} not in {public_remote_hostnames}') + abort(403) + else: + if not localhost: + logger.warn( + f'Possible DNS rebinding attack by {request.host}') + abort(403) # Add shared objects try: @@ -53,11 +75,13 @@ class ClientAPISecurity: except KeyError: g.too_many = None - if request.endpoint in whitelist_endpoints: - return + # Static files for Onionr sites if request.path.startswith('/site/'): return + if request.endpoint in whitelist_endpoints: + return + try: if not hmac.compare_digest( request.headers['token'], client_api.clientToken): diff --git a/static-data/default_config.json b/static-data/default_config.json index 4846991a..89e4a867 100755 --- a/static-data/default_config.json +++ b/static-data/default_config.json @@ -73,6 +73,8 @@ }, "ui": { "animated_background": true, + "public_remote_enabled": false, + "public_remote_hosts": [], "theme": "dark" } } \ No newline at end of file