Profile pictures are now handled by the application to mitigate possible directory traversals

to other sub-directories of the static directory (Admins/Staff with the right to edit user
accounts were able to set a path like ../static/favicon.png for the profile picture - this
isn't a "i'm in, now i have root access and can hack your mom"-vulnerability, but better fix
it before it evolves to one. or a dragon. it's too late for this crap.)
This commit is contained in:
W13R 2022-11-02 21:55:36 +01:00
parent 86ea7c0000
commit 9f270c12b4
8 changed files with 34 additions and 4 deletions

View file

@ -69,7 +69,7 @@
<ul class="userlist">
{% for user_ in user_list %}
<li class="userlistButton button" data-username="{{ user_.username }}">
<img src="{% static 'profilepictures/'|add:user_.profile_picture_filename %}">
<img src="{{ '/profilepictures?name='|add:user_.profile_picture_filename }}">
<div>
{% if user_.first_name %}

View file

@ -3,7 +3,7 @@
<div class="userPanel">
<div class="userInfo">
<img src="{% static 'profilepictures/'|add:user.profile_picture_filename %}">
<img src="{{ '/profilepictures?name='|add:user.profile_picture_filename }}">
<span>
{% if user.first_name != "" %}
{% translate "User" %}: {{ user.first_name }} {{ user.last_name }} ({{ user.username }})

View file

@ -16,9 +16,10 @@ urlpatterns = [
path('accounts/password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
path('accounts/password_change_done/', views.redirect_home, name='password_change_done'),
path('admin/', adminSite.urls),
# custom-handled resources
path('profilepictures', views.profile_pictures),
# API #
path('api/order-drink', views.api_order_drink),
path('api/deposit', views.api_deposit),
path('api/supply', views.api_supply)
#path('api/get-statistics', views.api_get_statistics)
]

View file

@ -1,12 +1,16 @@
import json
import sys
from pathlib import Path
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth import get_user_model
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm
from django.http.response import HttpResponseRedirect
from django.http.response import FileResponse
from django.http.response import HttpResponse
from django.shortcuts import render
@ -20,6 +24,9 @@ from .models import Drink
from .models import Order
from .models import RegisterTransaction
#
profile_pictures_path = Path(settings.PROFILE_PICTURES).resolve()
# login view
@ -112,6 +119,23 @@ def redirect_home(request):
return HttpResponseRedirect("/")
# Custom-Handled Resources
def profile_pictures(request):
if not "name" in request.GET:
return HttpResponse(b"", status=400)
print(request.GET["name"])
ppic_filepath = Path(profile_pictures_path / request.GET["name"]).resolve()
try:
ppic_filepath.relative_to(profile_pictures_path)
except:
return HttpResponse("No.", status=403)
if ppic_filepath.is_file():
return FileResponse(ppic_filepath.open('rb'))
else:
return FileResponse(b"", status=404)
# API for XHR requests #
@login_required

View file

@ -175,3 +175,5 @@ try:
CURRENCY_SUFFIX = os.environ["CURRENCY_SUFFIX"]
except KeyError:
CURRENCY_SUFFIX = "$"
PROFILE_PICTURES = os.environ["PROFILE_PICTURES"]