diff --git a/src/FlaskRTBCTF/__init__.py b/src/FlaskRTBCTF/__init__.py index ad58ca5..9b3f049 100644 --- a/src/FlaskRTBCTF/__init__.py +++ b/src/FlaskRTBCTF/__init__.py @@ -4,7 +4,7 @@ from flask_login import LoginManager from flask_admin import Admin from flask_mail import Mail -from FlaskRTBCTF.config import Config +from FlaskRTBCTF.config import Config, LOGGING import os db = SQLAlchemy() @@ -26,9 +26,13 @@ def create_app(config_class=Config): # Add model views from FlaskRTBCTF.admin.views import MyModelView from FlaskRTBCTF.models import User, Score, Notification + if LOGGING: + from FlaskRTBCTF.models import Logs admin_manager.add_view(MyModelView(User, db.session)) admin_manager.add_view(MyModelView(Score, db.session)) admin_manager.add_view(MyModelView(Notification, db.session)) + if LOGGING: + admin_manager.add_view(MyModelView(Logs, db.session)) mail.init_app(app) from flask_sslify import SSLify diff --git a/src/FlaskRTBCTF/admin/views.py b/src/FlaskRTBCTF/admin/views.py index 3f223d2..39f180e 100644 --- a/src/FlaskRTBCTF/admin/views.py +++ b/src/FlaskRTBCTF/admin/views.py @@ -27,4 +27,4 @@ def _handle_view(self, name, **kwargs): abort(403) #else: # login - # return redirect(url_for('user.login', next=request.url)) \ No newline at end of file + # return redirect(url_for('user.login', next=request.url)) diff --git a/src/FlaskRTBCTF/config.py b/src/FlaskRTBCTF/config.py index 01e7b06..4d9d71b 100644 --- a/src/FlaskRTBCTF/config.py +++ b/src/FlaskRTBCTF/config.py @@ -61,4 +61,7 @@ class Config: userScore = 10 rootScore = 20 -# NOTE: CHANGE DEFAULT ADMIN CREDENTIALS in create_db.py !!! \ No newline at end of file +# Logging: Set to 'True' to enable Logging in Admin Views + +LOGGING = False +# NOTE: CHANGE DEFAULT ADMIN CREDENTIALS in create_db.py !!! diff --git a/src/FlaskRTBCTF/ctf/routes.py b/src/FlaskRTBCTF/ctf/routes.py index 0a8f912..8265acf 100644 --- a/src/FlaskRTBCTF/ctf/routes.py +++ b/src/FlaskRTBCTF/ctf/routes.py @@ -3,9 +3,11 @@ from flask import Blueprint, render_template, flash, request from flask_login import current_user, login_required from FlaskRTBCTF import db, bcrypt +from FlaskRTBCTF.config import organization, box, userHash, rootHash, userScore, rootScore, LOGGING from FlaskRTBCTF.models import User, Score +if LOGGING: + from FlaskRTBCTF.models import Logs from FlaskRTBCTF.ctf.forms import UserHashForm, RootHashForm -from FlaskRTBCTF.config import organization, box, userHash, rootHash, userScore, rootScore from datetime import datetime ctf = Blueprint('ctf', __name__) @@ -29,6 +31,13 @@ def scoreboard(): @ctf.route("/machine") @login_required def machine(): + user = User.query.get(current_user.id) + if user.visitedMachine is False and user.isAdmin is False: + user.visitedMachine = True + if LOGGING: + log = Logs.query.get(current_user.id) + log.machineVisitTime = datetime.utcnow() + db.session.commit() userHashForm = UserHashForm() rootHashForm = RootHashForm() return render_template('machine.html', userHashForm=userHashForm, @@ -50,7 +59,11 @@ def validateRootHash(): score.rootHash = True score.points += rootScore score.timestamp = datetime.utcnow() - score.rootSubmissionIP = request.access_route[0] + if LOGGING: + log = Logs.query.get(current_user.id) + log.rootSubmissionIP = request.access_route[0] + log.rootSubmissionTime = datetime.utcnow() + log.rootOwnTime = str(log.rootSubmissionTime - log.machineVisitTime) db.session.commit() flash("Congrats! correct system hash.", "success") else: @@ -76,7 +89,11 @@ def validateUserHash(): score.userHash = True score.points += userScore score.timestamp = datetime.utcnow() - score.userSubmissionIP = request.access_route[0] + if LOGGING: + log = Logs.query.get(current_user.id) + log.userSubmissionIP = request.access_route[0] + log.userSubmissionTime = datetime.utcnow() + log.userOwnTime = str(log.userSubmissionTime - log.machineVisitTime) db.session.commit() flash("Congrats! correct user hash.", "success") else: diff --git a/src/FlaskRTBCTF/models.py b/src/FlaskRTBCTF/models.py index 102b9c1..c72516c 100644 --- a/src/FlaskRTBCTF/models.py +++ b/src/FlaskRTBCTF/models.py @@ -1,7 +1,7 @@ ''' Models ''' from flask import current_app -from flask import request +from FlaskRTBCTF.config import LOGGING from FlaskRTBCTF import db, login_manager from flask_login import UserMixin from datetime import datetime @@ -20,7 +20,10 @@ class User(db.Model, UserMixin): password = db.Column(db.String(60), nullable=False) confirmed_at = db.Column(db.DateTime(), default=datetime.utcnow) isAdmin = db.Column(db.Boolean, default=False) + visitedMachine = db.Column(db.Boolean, default=False) score = db.relationship('Score', backref='user', lazy=True, uselist=False) + if LOGGING: + logs = db.relationship('Logs', backref='user', lazy=True, uselist=False) def get_reset_token(self, expires_sec=1800): s = Serializer(current_app.config['SECRET_KEY'], expires_sec) @@ -48,8 +51,7 @@ class Score(db.Model): rootHash = db.Column(db.Boolean, default=False) points = db.Column(db.Integer) timestamp = db.Column(db.DateTime(), default=datetime.utcnow) - rootSubmissionIP = db.Column(db.String) - userSubmissionIP = db.Column(db.String) + def __repr__(self): return f"Score('{self.user_id}', '{self.points}')" @@ -65,3 +67,22 @@ class Notification(db.Model): def __repr__(self): return f"Notif('{self.title}', '{self.body}')" + + +''' Logging Table ''' +if LOGGING: + class Logs(db.Model): + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False, primary_key=True) + accountCreationTime = db.Column(db.DateTime, nullable=False) + machineVisitTime = db.Column(db.DateTime, nullable=True) + userSubmissionTime = db.Column(db.DateTime, nullable=True) + rootSubmissionTime = db.Column(db.DateTime, nullable=True) + userOwnTime = db.Column(db.String, nullable=True) + rootOwnTime = db.Column(db.String, nullable=True) + userSubmissionIP = db.Column(db.String, nullable=True) + rootSubmissionIP = db.Column(db.String, nullable=True) + + def __repr__(self): + return f"Logs('{self.user_id}','{self.machineVisitTime}','{self.userSubmissionTime}'," \ + f"'{self.rootSubmissionTime}','{self.userOwnTime}','{self.rootOwnTime}','{self.userSubmissionIP}," \ + f" '{self.rootSubmissionIP}'" diff --git a/src/FlaskRTBCTF/users/routes.py b/src/FlaskRTBCTF/users/routes.py index 2749ee3..5a15afd 100644 --- a/src/FlaskRTBCTF/users/routes.py +++ b/src/FlaskRTBCTF/users/routes.py @@ -1,11 +1,14 @@ from flask import render_template, url_for, flash, redirect, request, Blueprint from flask_login import login_user, current_user, logout_user, login_required from FlaskRTBCTF import db, bcrypt +from FlaskRTBCTF.config import organization, LOGGING +from datetime import datetime from FlaskRTBCTF.models import User, Score +if LOGGING: + from FlaskRTBCTF.models import Logs from FlaskRTBCTF.users.forms import (RegistrationForm, LoginForm, UpdateAccountForm, RequestResetForm, ResetPasswordForm) from FlaskRTBCTF.users.utils import send_reset_email -from FlaskRTBCTF.config import organization users = Blueprint('users', __name__) @@ -21,8 +24,12 @@ def register(): hashed_password = bcrypt.generate_password_hash( form.password.data).decode('utf-8') user = User(username=form.username.data, - email=form.email.data, password=hashed_password) + email=form.email.data, password=hashed_password, visitedMachine=False) score = Score(user=user, userHash=False, rootHash=False, points=0) + if LOGGING: + log = Logs(user=user, accountCreationTime=datetime.utcnow(), machineVisitTime=None, userSubmissionTime=None, + rootSubmissionTime=None, userSubmissionIP=None, rootSubmissionIP=None) + db.session.add(log) db.session.add(user) db.session.add(score) db.session.commit() diff --git a/src/create_db.py b/src/create_db.py index 32fbde0..00e4c3d 100644 --- a/src/create_db.py +++ b/src/create_db.py @@ -16,7 +16,8 @@ email='admin@admin.com', password=bcrypt.generate_password_hash('admin').decode('utf-8'), confirmed_at=datetime.datetime.now(), - isAdmin = True + isAdmin = True, + visitedMachine = True ) admin_score = Score(user=admin_user, userHash=False, rootHash=False, points=0) db.session.add(admin_user) diff --git a/src/docker-entrypoint.sh b/src/docker-entrypoint.sh index 7514fcc..eedd1f1 100644 --- a/src/docker-entrypoint.sh +++ b/src/docker-entrypoint.sh @@ -2,7 +2,7 @@ WORKERS=4 # change here to the change number of workers -echo "Starting CTFd" +echo "Starting RTB-CTFd" exec gunicorn 'FlaskRTBCTF:create_app()' \ --bind '0.0.0.0:8080' \ --workers $WORKERS \ No newline at end of file diff --git a/src/run.py b/src/run.py index e4a715c..ab1cfcf 100644 --- a/src/run.py +++ b/src/run.py @@ -1,5 +1,6 @@ from FlaskRTBCTF import create_app + app = create_app() if __name__ == '__main__':