aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2022-07-09 12:06:32 +0200
committerDaniel Schadt <kingdread@gmx.de>2022-07-09 12:06:32 +0200
commit13d4b0cf3cd3ea544fd8ff504cf2c58420b8e2d8 (patch)
treef4562896b8bf1b3761ea100bbe0849c51e75e1ed
parent56e4457de416a3fe16592983dabfee16075c8892 (diff)
downloadfietsboek-13d4b0cf3cd3ea544fd8ff504cf2c58420b8e2d8.tar.gz
fietsboek-13d4b0cf3cd3ea544fd8ff504cf2c58420b8e2d8.tar.bz2
fietsboek-13d4b0cf3cd3ea544fd8ff504cf2c58420b8e2d8.zip
add CSRF protection for actions that modify data
-rw-r--r--fietsboek/__init__.py3
-rw-r--r--fietsboek/templates/admin.jinja23
-rw-r--r--fietsboek/templates/details.jinja22
-rw-r--r--fietsboek/templates/edit.jinja22
-rw-r--r--fietsboek/templates/finish_upload.jinja27
-rw-r--r--fietsboek/templates/profile.jinja26
-rw-r--r--fietsboek/templates/upload.jinja22
-rw-r--r--fietsboek/templates/util.jinja24
-rw-r--r--fietsboek/views/upload.py2
9 files changed, 29 insertions, 2 deletions
diff --git a/fietsboek/__init__.py b/fietsboek/__init__.py
index 6ed9028..4a28dd4 100644
--- a/fietsboek/__init__.py
+++ b/fietsboek/__init__.py
@@ -4,6 +4,7 @@ For more information, see the README or the included documentation.
"""
from pyramid.config import Configurator
from pyramid.session import SignedCookieSessionFactory
+from pyramid.csrf import CookieCSRFStoragePolicy
from pyramid.settings import asbool, aslist
from pyramid.i18n import default_locale_negotiator
@@ -59,6 +60,8 @@ def main(global_config, **settings):
config.add_translation_dirs('fietsboek:locale/')
config.set_session_factory(my_session_factory)
config.set_security_policy(SecurityPolicy())
+ config.set_csrf_storage_policy(CookieCSRFStoragePolicy())
+ config.set_default_csrf_options(require_csrf=True)
config.set_locale_negotiator(locale_negotiator)
jinja2_env = config.get_jinja2_environment()
diff --git a/fietsboek/templates/admin.jinja2 b/fietsboek/templates/admin.jinja2
index 47c1832..3201d8d 100644
--- a/fietsboek/templates/admin.jinja2
+++ b/fietsboek/templates/admin.jinja2
@@ -18,12 +18,14 @@
<div class="mb-3">
<input class="form-control" type="file" name="badge-image">
</div>
+ {{ util.hidden_csrf_input() }}
<div class="mb-3">
<button class="btn btn-primary">{{ _("page.admin.badge.edit") }}</button>
</div>
</form>
<form method="POST" action="{{ request.route_path('admin-badge-delete') }}">
<input type="hidden" name="badge-delete-id" value="{{ badge.id }}">
+ {{ util.hidden_csrf_input() }}
<button class="btn btn-danger"><i class="bi bi-trash"></i> {{ _("page.admin.badge.delete_badge") }}</button>
</form>
</span>
@@ -39,6 +41,7 @@
<label for="badge-image" class="form-label">{{ _("page.admin.badges.badge_image") }}</label>
<input class="form-control" type="file" name="badge-image">
</div>
+ {{ util.hidden_csrf_input() }}
<button type="submit" class="btn btn-primary">{{ _("page.admin.badges.add_badge") }}</button>
</form>
</div>
diff --git a/fietsboek/templates/details.jinja2 b/fietsboek/templates/details.jinja2
index 741c488..f83ecb1 100644
--- a/fietsboek/templates/details.jinja2
+++ b/fietsboek/templates/details.jinja2
@@ -23,6 +23,7 @@
</div>
<div class="modal-footer">
<form method="POST" action="{{ request.route_url('invalidate-share', track_id=track.id) }}">
+ {{ util.hidden_csrf_input() }}
<button type="submit" class="btn btn-warning">{{ _("page.details.sharelink.invalidate") }}</button>
</form>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ _("page.details.sharelink.close") }}</button>
@@ -144,6 +145,7 @@
<div class="card-footer text-muted">
<button type="submit" class="btn btn-success"><i class="bi bi-pen"></i> {{ _("page.details.comments.new.submit") }}</button>
</div>
+ {{ util.hidden_csrf_input() }}
</form>
</div>
{% endif %}
diff --git a/fietsboek/templates/edit.jinja2 b/fietsboek/templates/edit.jinja2
index 9d48cf1..6053509 100644
--- a/fietsboek/templates/edit.jinja2
+++ b/fietsboek/templates/edit.jinja2
@@ -1,6 +1,7 @@
{% extends "layout.jinja2" %}
{% import "edit_form.jinja2" as edit_form %}
+{% import "util.jinja2" as util with context %}
{% block content %}
<div class="container">
@@ -10,6 +11,7 @@
</div>
<form method="POST">
{{ edit_form.edit_track(track.title, track.date_raw, track.date_tz or 0, track.visibility, track.description, track.text_tags(), badges, track.tagged_people) }}
+ {{ util.hidden_csrf_input() }}
<div class="btn-group" role="group">
<button type="submit" class="btn btn-primary"><i class="bi bi-save"></i> {{ _("page.edit.form.submit") }}</button>
<a href="{{ request.route_url('details', track_id=track.id) }}" class="btn btn-secondary"><i class="bi bi-x-circle"></i> {{ _("page.edit.form.cancel") }}</a>
diff --git a/fietsboek/templates/finish_upload.jinja2 b/fietsboek/templates/finish_upload.jinja2
index 66ba926..58c67d4 100644
--- a/fietsboek/templates/finish_upload.jinja2
+++ b/fietsboek/templates/finish_upload.jinja2
@@ -1,6 +1,7 @@
{% extends "layout.jinja2" %}
{% import "edit_form.jinja2" as edit_form %}
+{% import "util.jinja2" as util with context %}
{% block content %}
<div class="container">
@@ -10,10 +11,14 @@
</div>
<form method="POST">
{{ edit_form.edit_track(upload_title, upload_date, upload_date_tz, upload_visibility, upload_description, upload_tags, badges, upload_tagged_people) }}
+ {{ util.hidden_csrf_input() }}
<div class="btn-group" role="group">
<button type="submit" class="btn btn-primary">{{ _("page.upload.form.submit") }}</button>
- <a href="{{ request.route_url('cancel-upload', upload_id=preview_id) }}" class="btn btn-danger">{{ _("page.upload.form.cancel") }}</a>
+ <button type="submit" class="btn btn-danger" form="cancelForm">{{ _("page.upload.form.cancel") }}</button>
</div>
</form>
+ <form id="cancelForm" method="POST" action="{{ request.route_url('cancel-upload', upload_id=preview_id) }}">
+ {{ util.hidden_csrf_input() }}
+ </form>
</div>
{% endblock %}
diff --git a/fietsboek/templates/profile.jinja2 b/fietsboek/templates/profile.jinja2
index d8722ef..8b1c748 100644
--- a/fietsboek/templates/profile.jinja2
+++ b/fietsboek/templates/profile.jinja2
@@ -1,5 +1,7 @@
{% extends "layout.jinja2" %}
+{% import "util.jinja2" as util with context %}
+
{% block content %}
<div class="container">
<h1>{{ _("page.my_profile.title") }}</h1>
@@ -27,6 +29,7 @@
</div>
<label for="repeatPassword">{{ _("page.my_profile.personal_data.repeat_password") }}</label>
</div>
+ {{ util.hidden_csrf_input() }}
<button type="submit" class="btn btn-primary"><i class="bi bi-save"></i> {{ _("page.my_profile.personal_data.save") }}</button>
</form>
@@ -39,6 +42,7 @@
<li class="list-group-item d-flex align-items-center">
<form action="{{ request.route_url('delete-friend') }}" method="POST">
<input type="hidden" name="friend-id" value="{{ friend.id }}">
+ {{ util.hidden_csrf_input() }}
<button type="submit" class="btn btn-danger"><i class="bi bi-trash"></i> {{ _("page.my_profile.unfriend") }}</button>
</form>
<span class="ms-3">{{ friend.name }} ({{ friend.email }})</span>
@@ -48,6 +52,7 @@
<li class="list-group-item list-group-item-success d-flex align-items-center">
<form action="{{ request.route_url('accept-friend') }}" method="POST">
<input type="hidden" name="request-id" value="{{ friend_request.id }}">
+ {{ util.hidden_csrf_input() }}
<button type="submit" class="btn btn-success"><i class="bi bi-check"></i> {{ _("page.my_profile.accept_friend") }}</button>
</form>
<span class="ms-3">{{ friend_request.sender.name }} ({{ friend_request.sender.email }})</span>
@@ -60,6 +65,7 @@
<div class="my-3">
<form action="{{ request.route_url('add-friend') }}" method="POST">
+ {{ util.hidden_csrf_input() }}
<div class="row align-items-center">
<div class="col-lg-5">
<div class="form-floating">
diff --git a/fietsboek/templates/upload.jinja2 b/fietsboek/templates/upload.jinja2
index b3b4ddc..6406e91 100644
--- a/fietsboek/templates/upload.jinja2
+++ b/fietsboek/templates/upload.jinja2
@@ -1,4 +1,5 @@
{% extends "layout.jinja2" %}
+{% import "util.jinja2" as util with context %}
{% block content %}
<div class="container">
@@ -8,6 +9,7 @@
<label for="uploadFile" class="form-label">{{ _("page.upload.form.gpx") }}</label>
<input class="form-control" type="file" id="uploadFile" name="gpx">
</div>
+ {{ util.hidden_csrf_input() }}
<button type="submit" class="btn btn-primary"><i class="bi bi-upload"></i> {{ _("page.upload.form.submit") }}</button>
</form>
</div>
diff --git a/fietsboek/templates/util.jinja2 b/fietsboek/templates/util.jinja2
index d334473..7b39477 100644
--- a/fietsboek/templates/util.jinja2
+++ b/fietsboek/templates/util.jinja2
@@ -1,3 +1,7 @@
{% macro render_badge(badge) -%}
<div class="badge-container"><img src="{{ request.route_url('badge', badge_id=badge.id) }}" data-bs-toggle="tooltip" title="{{ badge.title }}"></div>
{%- endmacro %}
+
+{% macro hidden_csrf_input() %}
+<input type="hidden" name="csrf_token" value="{{ get_csrf_token() }}">
+{% endmacro %}
diff --git a/fietsboek/views/upload.py b/fietsboek/views/upload.py
index 9e38069..4db0cd6 100644
--- a/fietsboek/views/upload.py
+++ b/fietsboek/views/upload.py
@@ -173,7 +173,7 @@ def do_finish_upload(request):
return HTTPFound(request.route_url('details', track_id=track.id))
-@view_config(route_name='cancel-upload', permission='upload.finish')
+@view_config(route_name='cancel-upload', permission='upload.finish', request_method="POST")
def cancel_upload(request):
"""Cancels the upload and clears the temporary data.