Fix security issues

This commit is contained in:
Andrew 2021-11-30 14:37:45 -05:00
parent b996f7e7e7
commit 33ab2583da
4 changed files with 173 additions and 17 deletions

View File

@ -12,12 +12,14 @@ import os
import shutil
import html
import re
from app.classes.models.users import helper_users
from app.classes.shared.console import console
from app.classes.shared.main_models import Users, installer
from app.classes.web.base_handler import BaseHandler
from app.classes.shared.helpers import helper
from app.classes.shared.server import ServerOutBuf
from app.classes.models.server_permissions import Enum_Permissions_Server
logger = logging.getLogger(__name__)
@ -133,6 +135,20 @@ class AjaxHandler(BaseHandler):
@tornado.web.authenticated
def post(self, page):
user_data = json.loads(self.get_secure_cookie("user_data"))
server_id = self.get_argument('id', None)
exec_user_id = user_data['user_id']
exec_user = helper_users.get_user(exec_user_id)
permissions = {
'Commands': Enum_Permissions_Server.Commands,
'Terminal': Enum_Permissions_Server.Terminal,
'Logs': Enum_Permissions_Server.Logs,
'Schedule': Enum_Permissions_Server.Schedule,
'Backup': Enum_Permissions_Server.Backup,
'Files': Enum_Permissions_Server.Files,
'Config': Enum_Permissions_Server.Config,
'Players': Enum_Permissions_Server.Players,
}
user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id)
error = bleach.clean(self.get_argument('error', "WTF Error!"))
page_data = {
@ -157,6 +173,10 @@ class AjaxHandler(BaseHandler):
self.controller.management.add_to_audit_log(user_data['user_id'], "Sent command to {} terminal: {}".format(self.controller.servers.get_server_friendly_name(server_id), command), server_id, self.get_remote_ip())
elif page == "create_file":
if not permissions['Files'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Files")
return
file_parent = helper.get_os_understandable_path(self.get_body_argument('file_parent', default=None, strip=True))
file_name = self.get_body_argument('file_name', default=None, strip=True)
file_path = os.path.join(file_parent, file_name)
@ -176,6 +196,10 @@ class AjaxHandler(BaseHandler):
file_object.close()
elif page == "create_dir":
if not permissions['Files'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Files")
return
dir_parent = helper.get_os_understandable_path(self.get_body_argument('dir_parent', default=None, strip=True))
dir_name = self.get_body_argument('dir_name', default=None, strip=True)
dir_path = os.path.join(dir_parent, dir_name)
@ -193,6 +217,10 @@ class AjaxHandler(BaseHandler):
os.mkdir(dir_path)
elif page == "unzip_file":
if not permissions['Files'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Files")
return
server_id = self.get_argument('id', None)
path = helper.get_os_understandable_path(self.get_argument('path', None))
helper.unzipFile(path)
@ -200,6 +228,10 @@ class AjaxHandler(BaseHandler):
return
elif page == "kill":
if not permissions['Commands'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Commands")
return
server_id = self.get_argument('id', None)
svr = self.controller.get_server_obj(server_id)
try:
@ -213,6 +245,10 @@ class AjaxHandler(BaseHandler):
svr.agree_eula(user_data['user_id'])
elif page == "restore_backup":
if not permissions['Backup'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Backups")
return
server_id = bleach.clean(self.get_argument('id', None))
zip_name = bleach.clean(self.get_argument('zip_file', None))
svr_obj = self.controller.servers.get_server_obj(server_id)
@ -229,7 +265,51 @@ class AjaxHandler(BaseHandler):
@tornado.web.authenticated
def delete(self, page):
user_data = json.loads(self.get_secure_cookie("user_data"))
server_id = self.get_argument('id', None)
exec_user_id = user_data['user_id']
exec_user = helper_users.get_user(exec_user_id)
permissions = {
'Commands': Enum_Permissions_Server.Commands,
'Terminal': Enum_Permissions_Server.Terminal,
'Logs': Enum_Permissions_Server.Logs,
'Schedule': Enum_Permissions_Server.Schedule,
'Backup': Enum_Permissions_Server.Backup,
'Files': Enum_Permissions_Server.Files,
'Config': Enum_Permissions_Server.Config,
'Players': Enum_Permissions_Server.Players,
}
user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id)
if page == "del_file":
if not permissions['Files'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Files")
return
file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True))
server_id = self.get_argument('id', None)
console.warning("delete {} for server {}".format(file_path, server_id))
if not self.check_server_id(server_id, 'del_file'):
return
else: server_id = bleach.clean(server_id)
server_info = self.controller.servers.get_server_data_by_id(server_id)
if not (helper.in_path(helper.get_os_understandable_path(server_info['path']), file_path) \
or helper.in_path(helper.get_os_understandable_path(server_info['backup_path']), file_path)) \
or not helper.check_file_exists(os.path.abspath(file_path)):
logger.warning("Invalid path in del_file ajax call ({})".format(file_path))
console.warning("Invalid path in del_file ajax call ({})".format(file_path))
return
# Delete the file
os.remove(file_path)
if page == "del_backup":
if not permissions['Backup'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Backups")
return
file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True))
server_id = self.get_argument('id', None)
@ -251,6 +331,10 @@ class AjaxHandler(BaseHandler):
os.remove(file_path)
elif page == "del_dir":
if not permissions['Files'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Files")
return
dir_path = helper.get_os_understandable_path(self.get_body_argument('dir_path', default=None, strip=True))
server_id = self.get_argument('id', None)
@ -271,12 +355,20 @@ class AjaxHandler(BaseHandler):
shutil.rmtree(dir_path) # Removes also when there are contents
elif page == "delete_server":
if not permissions['Config'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Config")
return
server_id = self.get_argument('id', None)
logger.info(
"Removing server from panel for server: {}".format(self.controller.servers.get_server_friendly_name(server_id)))
self.controller.remove_server(server_id, False)
elif page == "delete_server_files":
if not permissions['Config'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Config")
return
server_id = self.get_argument('id', None)
logger.info(
"Removing server and all associated files for server: {}".format(self.controller.servers.get_server_friendly_name(server_id)))
@ -284,7 +376,26 @@ class AjaxHandler(BaseHandler):
@tornado.web.authenticated
def put(self, page):
user_data = json.loads(self.get_secure_cookie("user_data"))
server_id = self.get_argument('id', None)
exec_user_id = user_data['user_id']
exec_user = helper_users.get_user(exec_user_id)
permissions = {
'Commands': Enum_Permissions_Server.Commands,
'Terminal': Enum_Permissions_Server.Terminal,
'Logs': Enum_Permissions_Server.Logs,
'Schedule': Enum_Permissions_Server.Schedule,
'Backup': Enum_Permissions_Server.Backup,
'Files': Enum_Permissions_Server.Files,
'Config': Enum_Permissions_Server.Config,
'Players': Enum_Permissions_Server.Players,
}
user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id)
if page == "save_file":
if not permissions['Files'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Files")
return
file_contents = self.get_body_argument('file_contents', default=None, strip=True)
file_path = helper.get_os_understandable_path(self.get_body_argument('file_path', default=None, strip=True))
server_id = self.get_argument('id', None)
@ -303,6 +414,10 @@ class AjaxHandler(BaseHandler):
file_object.write(file_contents)
elif page == "rename_item":
if not permissions['Files'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Files")
return
item_path = helper.get_os_understandable_path(self.get_body_argument('item_path', default=None, strip=True))
new_item_name = self.get_body_argument('new_item_name', default=None, strip=True)
server_id = self.get_argument('id', None)

View File

@ -213,39 +213,45 @@ class PanelHandler(BaseHandler):
'Players': Enum_Permissions_Server.Players,
}
page_data['user_permissions'] = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id)
user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id)
if subpage == 'term':
if not page_data['permissions']['Terminal'] in page_data['user_permissions']:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Terminal")
return
if subpage == 'logs':
if not page_data['permissions']['Logs'] in page_data['user_permissions']:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Logs")
self.redirect("/panel/error?error=Unauthorized access to Logs")
return
if subpage == 'tasks':
if not page_data['permissions']['Schedule'] in page_data['user_permissions']:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access To Scheduled Tasks")
return
page_data['']
if subpage == 'config':
if not page_data['permissions']['Config'] in page_data['user_permissions']:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access Server Config")
return
if subpage == 'files':
if not page_data['permissions']['Files'] in page_data['user_permissions']:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access Files")
return
if subpage == "backup":
if not page_data['permissions']['Backup'] in page_data['user_permissions']:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Backups")
return
server_info = self.controller.servers.get_server_data_by_id(server_id)
page_data['backup_config'] = self.controller.management.get_backup_config(server_id)
self.controller.refresh_server_settings(server_id)
@ -647,7 +653,18 @@ class PanelHandler(BaseHandler):
exec_user_data = json.loads(self.get_secure_cookie("user_data"))
exec_user_id = exec_user_data['user_id']
exec_user = self.controller.users.get_user_by_id(exec_user_id)
server_id = self.get_argument('id', None)
permissions = {
'Commands': Enum_Permissions_Server.Commands,
'Terminal': Enum_Permissions_Server.Terminal,
'Logs': Enum_Permissions_Server.Logs,
'Schedule': Enum_Permissions_Server.Schedule,
'Backup': Enum_Permissions_Server.Backup,
'Files': Enum_Permissions_Server.Files,
'Config': Enum_Permissions_Server.Config,
'Players': Enum_Permissions_Server.Players,
}
user_perms = self.controller.server_perms.get_server_permissions_foruser(exec_user_id, server_id)
exec_user_role = set()
if exec_user['superuser'] == 1:
defined_servers = self.controller.list_defined_servers()
@ -661,17 +678,26 @@ class PanelHandler(BaseHandler):
exec_user_role.add(role['role_name'])
if page == 'server_detail':
if not permissions['Config'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access to Config")
return
server_id = self.get_argument('id', None)
server_name = self.get_argument('server_name', None)
server_path = self.get_argument('server_path', None)
log_path = self.get_argument('log_path', None)
executable = self.get_argument('executable', None)
execution_command = self.get_argument('execution_command', None)
server_obj = self.controller.servers.get_server_obj(server_id)
if exec_user['superuser']:
server_path = self.get_argument('server_path', None)
log_path = self.get_argument('log_path', None)
executable = self.get_argument('executable', None)
execution_command = self.get_argument('execution_command', None)
server_ip = self.get_argument('server_ip', None)
server_port = self.get_argument('server_port', None)
executable_update_url = self.get_argument('executable_update_url', None)
else:
execution_command = server_obj.execution_command
executable = server_obj.executable
stop_command = self.get_argument('stop_command', None)
auto_start_delay = self.get_argument('auto_start_delay', '10')
server_ip = self.get_argument('server_ip', None)
server_port = self.get_argument('server_port', None)
executable_update_url = self.get_argument('executable_update_url', None)
auto_start = int(float(self.get_argument('auto_start', '0')))
crash_detection = int(float(self.get_argument('crash_detection', '0')))
logs_delete_after = int(float(self.get_argument('logs_delete_after', '0')))
@ -705,10 +731,19 @@ class PanelHandler(BaseHandler):
if helper.validate_traversal(helper.get_servers_root_dir(), executable):
server_obj.executable = executable
server_obj.execution_command = execution_command
server_obj.stop_command = stop_command
server_obj.server_ip = server_ip
server_obj.server_port = server_port
server_obj.executable_update_url = executable_update_url
else:
server_obj.path = server_obj.path
server_obj.log_path = server_obj.log_path
server_obj.executable = server_obj.executable
print(server_obj.execution_command)
server_obj.execution_command = server_obj.execution_command
server_obj.server_ip = server_obj.server_ip
server_obj.server_port = server_obj.server_port
server_obj.executable_update_url = server_obj.executable_update_url
server_obj.stop_command = stop_command
server_obj.auto_start_delay = auto_start_delay
server_obj.auto_start = auto_start
server_obj.crash_detection = crash_detection
@ -727,15 +762,20 @@ class PanelHandler(BaseHandler):
if page == "server_backup":
logger.debug(self.request.arguments)
server_id = self.get_argument('id', None)
backup_path = bleach.clean(self.get_argument('backup_path', None))
server_obj = self.controller.servers.get_server_obj(server_id)
if exec_user['superuser']:
backup_path = bleach.clean(self.get_argument('backup_path', None))
else:
backup_path = server_obj.backup_path
max_backups = bleach.clean(self.get_argument('max_backups', None))
try:
enabled = int(float(bleach.clean(self.get_argument('auto_enabled'), '0')))
except Exception as e:
enabled = '0'
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: not superuser")
if not permissions['Backup'] in user_perms:
if not exec_user['superuser']:
self.redirect("/panel/error?error=Unauthorized access: User not authorized")
return
elif server_id is None:
self.redirect("/panel/error?error=Invalid Server ID")

View File

@ -157,7 +157,7 @@
$.ajax({
type: "DELETE",
headers: {'X-XSRFToken': token},
url: '/ajax/del_file?server_id='+id,
url: '/ajax/del_backup?server_id='+id,
data: {
file_path: filename,
id: id

View File

@ -144,9 +144,10 @@ if __name__ == '__main__':
console.info("Checking Internet/Port Service. This may take a minute.")
if not helper.check_internet():
console.error("We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited.")
console.warning("We have detected the machine running Crafty has no connection to the internet. Client connections to the server may be limited.")
elif not helper.check_port(helper.get_setting('https_port')):
console.error("We have detected Crafty's port, {} may not be open on the host network or a firewall is blocking it. Remote client connections to Crafty may be limited.".format(helper.get_setting('https_port')))
console.warning("We have detected Crafty's port, {} may not be open on the host network or a firewall is blocking it. Remote client connections to Crafty may be limited.".format(helper.get_setting('https_port')))
console.help("If you are not forwarding ports from your public IP or your router does not support hairpin NAT you can safely disregard the previous message.")
Crafty = MainPrompt(tasks_manager, migration_manager)