diff --git a/docker-compose.yml b/docker-compose.yml index 3d39f83..ab88e2f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,9 @@ services: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres + security_opt: + - "no-new-privileges:true" + read_only: true web: build: . image: pygoat/pygoat @@ -20,6 +23,9 @@ services: depends_on: - migration - db + security_opt: + - "no-new-privileges:true" + read_only: true migration: image: pygoat/pygoat command: python pygoat/manage.py migrate --noinput @@ -27,3 +33,6 @@ services: - .:/app depends_on: - db + security_opt: + - "no-new-privileges:true" + read_only: true diff --git a/introduction/apis.py b/introduction/apis.py index 7926708..b22e1c0 100644 --- a/introduction/apis.py +++ b/introduction/apis.py @@ -58,36 +58,44 @@ def ssrf_code_checker(request): @csrf_exempt # @authentication_decorator +import os + def log_function_checker(request): if request.method == 'POST': csrf_token = request.POST.get("csrfmiddlewaretoken") log_code = request.POST.get('log_code') api_code = request.POST.get('api_code') + + # Sanitize user-controlled data before writing to files + log_code = log_code[:1000] # Limit to 1000 characters + api_code = api_code[:1000] # Limit to 1000 characters + dirname = os.path.dirname(__file__) log_filename = os.path.join(dirname, "playground/A9/main.py") api_filename = os.path.join(dirname, "playground/A9/api.py") - f = open(log_filename,"w") - f.write(log_code) - f.close() - f = open(api_filename,"w") - f.write(api_code) - f.close() + + with open(log_filename, "w") as f: + f.write(log_code) + with open(api_filename, "w") as f: + f.write(api_code) + # Clearing the log file before starting the test - f = open('test.log', 'w') - f.write("") - f.close() + with open('test.log', 'w') as f: + f.write("") + url = "http://127.0.0.1:8000/2021/discussion/A9/target" - payload={'csrfmiddlewaretoken': csrf_token } + payload = {'csrfmiddlewaretoken': csrf_token} requests.request("GET", url) requests.request("POST", url) requests.request("PATCH", url, data=payload) requests.request("DELETE", url) - f = open('test.log', 'r') - lines = f.readlines() - f.close() - return JsonResponse({"message":"success", "logs": lines},status = 200) + + with open('test.log', 'r') as f: + lines = f.readlines() + + return JsonResponse({"message": "success", "logs": lines}, status=200) else: - return JsonResponse({"message":"method not allowed"},status = 405) + return JsonResponse({"message": "method not allowed"}, status=405) #a7 codechecking api @csrf_exempt @@ -123,16 +131,21 @@ def A6_disscussion_api(request): return JsonResponse({"message":"failure"},status = 400) @csrf_exempt +import os + def A6_disscussion_api_2(request): if request.method != 'POST': - return JsonResponse({"message":"method not allowed"},status = 405) + return JsonResponse({"message": "method not allowed"}, status=405) try: code = request.POST.get('code') - dirname = os.path.dirname(__file__) - filename = os.path.join(dirname, "playground/A6/utility.py") - f = open(filename,"w") - f.write(code) - f.close() - except: - return JsonResponse({"message":"missing code"},status = 400) - return JsonResponse({"message":"success"},status = 200) \ No newline at end of file + if code: + dirname = os.path.dirname(__file__) + filename = os.path.join(dirname, "playground/A6/utility.py") + with open(filename, "w") as f: + f.write(code) + else: + return JsonResponse({"message": "missing code"}, status=400) + except Exception as e: + return JsonResponse({"message": "error occurred", "error": str(e)}, status=400) + + return JsonResponse({"message": "success"}, status=200) diff --git a/introduction/mitre.py b/introduction/mitre.py index c899c21..f9afaa2 100644 --- a/introduction/mitre.py +++ b/introduction/mitre.py @@ -152,13 +152,19 @@ def mitre_top25(request): return render(request, 'mitre/mitre_top25.html') @authentication_decorator +import hashlib +import os +import jwt +from django.shortcuts import render, redirect +from .models import CSRF_user_tbl + def csrf_lab_login(request): if request.method == 'GET': return render(request, 'mitre/csrf_lab_login.html') elif request.method == 'POST': password = request.POST.get('password') username = request.POST.get('username') - password = md5(password.encode()).hexdigest() + password = hashlib.scrypt(password.encode(), salt=os.urandom(16), n=2**14, r=8, p=1).hex() User = CSRF_user_tbl.objects.filter(username=username, password=password) if User: payload ={ @@ -166,20 +172,25 @@ def csrf_lab_login(request): 'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=300), 'iat': datetime.datetime.utcnow() } - cookie = jwt.encode(payload, 'csrf_vulneribility', algorithm='HS256') + jwt_secret = os.getenv('JWT_SECRET') + cookie = jwt.encode(payload, jwt_secret, algorithm='HS256') response = redirect("/mitre/9/lab/transaction") - response.set_cookie('auth_cookiee', cookie) + response.set_cookie('auth_cookiee', cookie, secure=True, httponly=True, samesite='Lax') return response - else : + else: return redirect('/mitre/9/lab/login') @authentication_decorator @csrf_exempt +import os + +SECRET_KEY = os.getenv('SECRET_KEY') + def csrf_transfer_monei(request): if request.method == 'GET': try: cookie = request.COOKIES['auth_cookiee'] - payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256']) + payload = jwt.decode(cookie, SECRET_KEY, algorithms=['HS256']) username = payload['username'] User = CSRF_user_tbl.objects.filter(username=username) if not User: @@ -188,10 +199,14 @@ def csrf_transfer_monei(request): except: return redirect('/mitre/9/lab/login') +import os + +SECRET_KEY = os.getenv('SECRET_KEY', 'default_secret_key') + def csrf_transfer_monei_api(request,recipent,amount): if request.method == "GET": cookie = request.COOKIES['auth_cookiee'] - payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256']) + payload = jwt.decode(cookie, SECRET_KEY, algorithms=['HS256']) username = payload['username'] User = CSRF_user_tbl.objects.filter(username=username) if not User: @@ -212,10 +227,12 @@ def csrf_transfer_monei_api(request,recipent,amount): # @authentication_decorator @csrf_exempt +import ast + def mitre_lab_25_api(request): if request.method == "POST": expression = request.POST.get('expression') - result = eval(expression) + result = ast.literal_eval(expression) return JsonResponse({'result': result}) else: return redirect('/mitre/25/lab/') @@ -229,8 +246,10 @@ def mitre_lab_25(request): def mitre_lab_17(request): return render(request, 'mitre/mitre_lab_17.html') +import subprocess + def command_out(command): - process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + process = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return process.communicate() diff --git a/introduction/playground/A9/api.py b/introduction/playground/A9/api.py index 35e1bd2..eae79e8 100644 --- a/introduction/playground/A9/api.py +++ b/introduction/playground/A9/api.py @@ -1,10 +1,6 @@ from django.http import JsonResponse -from django.views.decorators.csrf import csrf_exempt - from .main import Log - -@csrf_exempt def log_function_target(request): L = Log(request) if request.method == "GET": @@ -30,4 +26,4 @@ def log_function_target(request): return JsonResponse({"message":"success", "method":"patch"},status = 200) if request.method == "UPDATE": return JsonResponse({"message":"success", "method":"update"},status = 200) - return JsonResponse({"message":"method not allowed"},status = 403) \ No newline at end of file + return JsonResponse({"message":"method not allowed"},status = 403) diff --git a/introduction/playground/A9/archive.py b/introduction/playground/A9/archive.py index c9db8fc..67082e1 100644 --- a/introduction/playground/A9/archive.py +++ b/introduction/playground/A9/archive.py @@ -4,7 +4,6 @@ from .main import Log -@csrf_exempt def log_function_target(request): L = Log(request) if request.method == "GET": diff --git a/introduction/templates/Lab/A9/a9_lab.html b/introduction/templates/Lab/A9/a9_lab.html index 5a70b46..7145c34 100644 --- a/introduction/templates/Lab/A9/a9_lab.html +++ b/introduction/templates/Lab/A9/a9_lab.html @@ -8,6 +8,7 @@
{{otp}}{{email}}{{code}}
{{not_admin}}