Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented possible solution for path traversal #28

Open
wants to merge 5 commits into
base: dev-0.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions app/api/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@

from app.api import api

def render_error(msg, error_header="An error occured!", statusCode=500):
return flask.render_template('error.html', error_header=error_header, error_message=msg), statusCode

def get_valid_subpath(f: str, d: str):
"""
Returns the absolute path of wanted file or directory, but only if it is contained in the given directory.

:param f: File name or directory to retireve the path for.
:type f: str

:param d: Directory, the file should be in.
:type d: str


:return: The valid path to access the file or None.
:rtype: str
"""
file_path = os.path.realpath(f)
common_path = os.path.commonpath((file_path, d))

# a valid sub path must contain the whole parent directory in its own path
if common_path == d:
return file_path

return None

@api.route('/config/<name>', methods=['GET'])
def get_config(name: str):
Expand All @@ -19,7 +44,11 @@ def get_config(name: str):
"""
nginx_path = flask.current_app.config['NGINX_PATH']

with io.open(os.path.join(nginx_path, name), 'r') as f:
path = get_valid_subpath(os.path.join(nginx_path, name), nginx_path)
if path == None:
return render_error(f'Could not read file "{path}".')

with io.open(path, 'r') as f:
_file = f.read()

return flask.render_template('config.html', name=name, file=_file), 200
Expand All @@ -39,7 +68,13 @@ def post_config(name: str):
content = flask.request.get_json()
nginx_path = flask.current_app.config['NGINX_PATH']

with io.open(os.path.join(nginx_path, name), 'w') as f:
config_file = os.path.join(nginx_path, name)

path = get_valid_subpath(config_file, nginx_path)
if path == None:
return flask.make_response({'success': False}), 500

with io.open(config_file, 'w') as f:
f.write(content['file'])

return flask.make_response({'success': True}), 200
Expand All @@ -57,6 +92,9 @@ def get_domains():
sites_available = []
sites_enabled = []

if not os.path.exists(config_path):
error_message = f'The config folder "{config_path}" does not exists.'
return render_error(error_message)
for _ in os.listdir(config_path):

if os.path.isfile(os.path.join(config_path, _)):
Expand Down Expand Up @@ -130,8 +168,12 @@ def post_domain(name: str):
new_domain = flask.render_template('new_domain.j2', name=name)
name = name + '.conf.disabled'

path = get_valid_subpath(os.path.join(config_path, name), config_path)
if path == None:
return flask.jsonify({'success': False, 'error_msg': 'invalid domain path'}), 500

try:
with io.open(os.path.join(config_path, name), 'w') as f:
with io.open(path, 'w') as f:
f.write(new_domain)

response = flask.jsonify({'success': True}), 201
Expand Down
7 changes: 6 additions & 1 deletion app/templates/domains.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
<div class="column">

<div class="ui cards" id="domain_cards">
{% if errorMessage %}
<div>
{{errorMessage}}
Copy link
Owner

@schenkd schenkd Jul 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is functional, but you could enhance it with a message from the semantic framework. Here is a link to the component: Error Messages

</div>
{% endif %}
{% if sites_available %}
{% for domain in sites_available %}
<div class="card">
Expand Down Expand Up @@ -30,4 +35,4 @@
<!-- file content -->
</div>

</div>
</div>
13 changes: 13 additions & 0 deletions app/templates/error.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="column">

<div class="ui negative message">
<i class="close icon"></i>
<div class="header">
{{error_header}}
</div>
<p>
{{error_message}}
</p>
</div>

</div>