diff --git a/cybersecprojkt/cybersecprojkt/__init__.py b/cybersecprojkt/cybersecprojkt/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/cybersecprojkt/cybersecprojkt/asgi.py b/cybersecprojkt/cybersecprojkt/asgi.py new file mode 100644 index 0000000000000000000000000000000000000000..0ccea71fdc2462aef03ac0cb61a2e218a80d28ef --- /dev/null +++ b/cybersecprojkt/cybersecprojkt/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for cybersecprojkt project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cybersecprojkt.settings') + +application = get_asgi_application() diff --git a/cybersecprojkt/cybersecprojkt/settings.py b/cybersecprojkt/cybersecprojkt/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..b16c847131750aea19e73c77c1f9572e1e45d084 --- /dev/null +++ b/cybersecprojkt/cybersecprojkt/settings.py @@ -0,0 +1,124 @@ +""" +Django settings for cybersecprojkt project. + +Generated by 'django-admin startproject' using Django 4.1.3. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-h2m@ma@c_5_&ubm7nqy9c%6z%8@_#69^y8jn#+(r2lz)__b$3)' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'messaging.apps.MessagingConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'cybersecprojkt.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': ['messaging/templates/pages'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'cybersecprojkt.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/cybersecprojkt/cybersecprojkt/urls.py b/cybersecprojkt/cybersecprojkt/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..959da7b001fd5cc3e18de32f52aed5916ed64fdd --- /dev/null +++ b/cybersecprojkt/cybersecprojkt/urls.py @@ -0,0 +1,23 @@ +"""cybersecprojkt URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from xml.etree.ElementInclude import include +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('messaging.urls')) +] diff --git a/cybersecprojkt/cybersecprojkt/wsgi.py b/cybersecprojkt/cybersecprojkt/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..4b50f72d3143611ba17b6a035f0bc4b9f21561f8 --- /dev/null +++ b/cybersecprojkt/cybersecprojkt/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for cybersecprojkt project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cybersecprojkt.settings') + +application = get_wsgi_application() diff --git a/cybersecprojkt/manage.py b/cybersecprojkt/manage.py new file mode 100755 index 0000000000000000000000000000000000000000..d54ff1eeb8bb053cfa5ab081df55b8f604b4332b --- /dev/null +++ b/cybersecprojkt/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cybersecprojkt.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/cybersecprojkt/messaging/__init__.py b/cybersecprojkt/messaging/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/cybersecprojkt/messaging/admin.py b/cybersecprojkt/messaging/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/cybersecprojkt/messaging/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/cybersecprojkt/messaging/apps.py b/cybersecprojkt/messaging/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..a1b00c566c8b5d0cee82c778ad54d6a4b207c46c --- /dev/null +++ b/cybersecprojkt/messaging/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MessagingConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'messaging' diff --git a/cybersecprojkt/messaging/migrations/__init__.py b/cybersecprojkt/messaging/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/cybersecprojkt/messaging/models.py b/cybersecprojkt/messaging/models.py new file mode 100644 index 0000000000000000000000000000000000000000..9a4e959682e787a41461dc0ee5ef709671a74249 --- /dev/null +++ b/cybersecprojkt/messaging/models.py @@ -0,0 +1,12 @@ +from django.db import models + +# Create your models here. +class Messager(models.Model): + name = models.TextField() + passwrd = models.TextField() + +class Message(models.Model): + frm = models.ForeignKey(Messager, on_delete=models.CASCADE, related_name='source') + to = models.ForeignKey(Messager, on_delete=models.CASCADE, related_name='target') + content = models.TextField() + time = models.DateTimeField(auto_now_add=True) diff --git a/cybersecprojkt/messaging/templates/pages/addmessage.html b/cybersecprojkt/messaging/templates/pages/addmessage.html new file mode 100644 index 0000000000000000000000000000000000000000..04af1de220c385809507a2d01ceead8fa057cc10 --- /dev/null +++ b/cybersecprojkt/messaging/templates/pages/addmessage.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <head> + <title>Send message</title> + </head> + + <body> + <form action='/addmessageconfirm/' method="POST" enctype="multipart/form-data"> + {% csrf_token %} + To: + <select name="to"> + {% for user in users %} + <option value="{{user.name}}">{{user.name}}</option> + {% endfor %} + </select><br/> + + <textarea name="content" cols="40" rows="10"></textarea><br/> + <input type="hidden" name="from" value="{{writter.name}}"> + <input type="submit" value="Send"/> + </form> + </body> \ No newline at end of file diff --git a/cybersecprojkt/messaging/templates/pages/index.html b/cybersecprojkt/messaging/templates/pages/index.html new file mode 100644 index 0000000000000000000000000000000000000000..d01369d692aff949a642c34d3b00bbfd45d8d343 --- /dev/null +++ b/cybersecprojkt/messaging/templates/pages/index.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <title>Main page</title> + </head> + + <body> + <form action='/register/' method="GET"> + {% csrf_token %} + <input type="submit" value="Register"/> + </form></br> + <form action='/login/' method="GET"> + {% csrf_token %} + <input type="submit" value="Login"/> + </form> + </body> \ No newline at end of file diff --git a/cybersecprojkt/messaging/templates/pages/login.html b/cybersecprojkt/messaging/templates/pages/login.html new file mode 100644 index 0000000000000000000000000000000000000000..4520cf9656b3c1b052c9a9e9bfe479c421d45f82 --- /dev/null +++ b/cybersecprojkt/messaging/templates/pages/login.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <head> + <title>Login</title> + </head> + + <body> + Login</br> + {{message}} + <form action='/loginconfirm/' method="POST"> + {% csrf_token %} + <input type="text" name="name">username</br> + <input type="password" name="passwrd">password</br> + <input type="submit" value="Login"/> + </form> + </body> \ No newline at end of file diff --git a/cybersecprojkt/messaging/templates/pages/messages.html b/cybersecprojkt/messaging/templates/pages/messages.html new file mode 100644 index 0000000000000000000000000000000000000000..c661fa99e84864710e61349c4e90e25dcf965f9f --- /dev/null +++ b/cybersecprojkt/messaging/templates/pages/messages.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> + <head> + <title>Messages</title> + </head> + + <body> + <form action='/addmessage/' method="GET"> + {% csrf_token %} + <input type="submit" value="Send a message"/></br> + </form></br> + <form action='/logout/' method="GET"> + {% csrf_token %} + <input type="submit" value="Logout"/></br> + </form></br> + <form action='/search/' method="POST"> + {% csrf_token %} + search for specific message content</br> + <input type="text" name="content"></br> + <input type="submit" value="search"/></br> + </form> + </br> + <h2>Messages for you</h2></br> + {% for msg in for_user %} + + <i>From {{msg.frm.name}} to {{msg.to.name}}</i></br> + {{msg.content|safe}} + </br> + </br> + + {% endfor %} + <h2>Messages from you</h2></br> + {% for msge in from_user %} + + <i>From {{msge.frm.name}} to {{msge.to.name}}</i></br> + {{msge.content|safe}} + </br> + </br> + + {% endfor %} + </body> \ No newline at end of file diff --git a/cybersecprojkt/messaging/templates/pages/register.html b/cybersecprojkt/messaging/templates/pages/register.html new file mode 100644 index 0000000000000000000000000000000000000000..1a09db60c5c08c8ed1ecdcac94b05f11f17f6ac3 --- /dev/null +++ b/cybersecprojkt/messaging/templates/pages/register.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> + <head> + <title>Register</title> + </head> + + <body> + Register</br> + <form action='/registerconfirm/' method="POST"> + {% csrf_token %} + <input type="text" name="name">username</br> + <input type="password" name="passwrd">password</br> + <input type="submit" value="Register"/> + </form> + </body> \ No newline at end of file diff --git a/cybersecprojkt/messaging/templates/pages/specific.html b/cybersecprojkt/messaging/templates/pages/specific.html new file mode 100644 index 0000000000000000000000000000000000000000..de1eb6ebcb03bb75c5fc8719c04de75f781119ac --- /dev/null +++ b/cybersecprojkt/messaging/templates/pages/specific.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <title>Specific messages</title> + </head> + + <body> + <a href="/">Back to main page</a> + <ul> + {% for re in results %} + <li>{{re}}</li> + {% endfor %} + </ul> + </body> \ No newline at end of file diff --git a/cybersecprojkt/messaging/tests.py b/cybersecprojkt/messaging/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/cybersecprojkt/messaging/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/cybersecprojkt/messaging/urls.py b/cybersecprojkt/messaging/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..42145a05600714d6f7735f1a93ca2fa6a2862194 --- /dev/null +++ b/cybersecprojkt/messaging/urls.py @@ -0,0 +1,16 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path('', views.indexview, name='index'), + path('register/', views.registerview, name="register"), + path('registerconfirm/', views.registerconfirmview, name="registerconfirm"), + path('login/', views.loginview, name="login"), + path('loginconfirm/', views.loginconfirmview, name="loginconfirm"), + path('messages/<int:uid>/', views.messagesview, name="messages"), + path('addmessage/', views.addmessageview, name="addmessage"), + path('addmessageconfirm/', views.addmessageconfirmview, name="addmessageconfirm"), + path('search/', views.searchspecificview, name="search"), + path('logout/', views.logoutview, name="logout"), +] \ No newline at end of file diff --git a/cybersecprojkt/messaging/views.py b/cybersecprojkt/messaging/views.py new file mode 100644 index 0000000000000000000000000000000000000000..494f273b13c93c3d438bec94399d045a7a306179 --- /dev/null +++ b/cybersecprojkt/messaging/views.py @@ -0,0 +1,138 @@ +from django.http import HttpResponse +from django.shortcuts import render, redirect +from string import ascii_lowercase +from .models import Messager, Message +import sqlite3 +import os +#from werkzeug.security import generate_password_hash, check_password_hash + +# Create your views here. +def indexview(request): + if 'name' not in request.session: + return render(request, 'index.html') + else: + user = Messager.objects.get(name=request.session['name']) + i = user.id + address = "/messages/"+str(i)+"/" + return redirect(address) + +def registerview(request): + if 'name' not in request.session: + return render(request, 'register.html') + else: + user = Messager.objects.get(name=request.session['name']) + i = user.id + address = "/messages/"+str(i)+"/" + return redirect(address) + +def registerconfirmview(request): + namn = request.POST.get("name") + initial_password = request.POST.get("passwrd") + char_list = [*initial_password] + for i in char_list: + if i not in ascii_lowercase: + return HttpResponse("Only lower case letters in the password, please.") + for k in range(0, len(char_list)): + for j in range(0, len(ascii_lowercase)): + if char_list[k] == ascii_lowercase[j]: + if j == len(ascii_lowercase)-1: + char_list[k] = ascii_lowercase[0] + else: + char_list[k] = ascii_lowercase[j+1] + break + #Using the Caesar cipher to encrypt the password, which is not secure + #-> Broken authentification + st = "" + password = st.join(char_list) + #password = generate_password_hash(initial_password) + Messager.objects.create(name=namn, passwrd=password) + return redirect('/') + +def loginview(request): + if 'name' not in request.session: + return render(request, 'login.html', {'message': ""}) + else: + user = Messager.objects.get(name=request.session['name']) + i = user.id + address = "/messages/"+str(i)+"/" + return redirect(address) + +def loginconfirmview(request): + namn = request.POST.get("name") + password = request.POST.get("passwrd") + try: + char_list = [*password] + for k in range(0, len(char_list)): + for j in range(0, len(ascii_lowercase)): + if char_list[k] == ascii_lowercase[j]: + if j == len(ascii_lowercase)-1: + char_list[k] = ascii_lowercase[0] + else: + char_list[k] = ascii_lowercase[j+1] + break + st = "" + decoded_password = st.join(char_list) + profil = Messager.objects.get(name=namn, passwrd=decoded_password) + #profil = Messager.objects.get(name=namn) + #if not check_password_hash(profil.passwrd, password): + # return render(request, 'login.html', {'message': "Incorrect username or password"}) + request.session['name'] = profil.name + i = profil.id + address = "/messages/"+str(i)+"/" + return redirect(address) + except: + return render(request, 'login.html', {'message': "Incorrect username or password"}) + +def messagesview(request, uid): + user = Messager.objects.get(id=uid) + for_user = Message.objects.filter(to=user) + from_user = Message.objects.filter(frm=user) + #Broken access control + #Data expossure + #if (request.session['name'] != user.name) or 'name' not in request.session: + # return redirect('/') + return render(request, 'messages.html', {'for_user': for_user, 'from_user': from_user}) + +def searchspecificview(request): + content = request.POST.get("content") + path = "../db.sqlite3" + thisdir = os.path.dirname(__file__) + dbname = os.path.join(thisdir, path) + conn = sqlite3.connect(dbname) + cursor = conn.cursor() + response = cursor.execute("SELECT content FROM messaging_message WHERE content LIKE '%%%s%%'" % (content)).fetchall() + print(cursor.fetchall()) + #Injection + results = [r[0] for r in response] + #messages = List(Message.objects.all()) + #results = [] + #for m in messages: + # if content in m.content: + # results.append(m.content) + return render(request, 'specific.html', {'results': results}) + +def addmessageview(request): + if 'name' not in request.session: + return redirect('/login/') + writter = Messager.objects.get(name=request.session['name']) + users = Messager.objects.exclude(name=request.session['name']) + return render(request, 'addmessage.html', {'users': users, 'writter': writter}) + +def addmessageconfirmview(request): + if 'name' not in request.session: + return redirect('/') + else: + to = request.POST.get("to") + frm = request.POST.get("from") + sender = Messager.objects.get(name=frm) + receive = Messager.objects.get(name=to) + content = request.POST.get("content") + #if ("<" in content) or (">" in content) or ("/" in content): + # return HttpResponse("No html, please") + Message.objects.create(frm=sender, to=receive, content=content) + #XSS + return redirect("/") + +def logoutview(request): + del request.session['name'] + return redirect('/') \ No newline at end of file