Skip to content

Commit

Permalink
performance boost with meinheld and flask-minify, fixes, admin can no…
Browse files Browse the repository at this point in the history
…w change user password (#76)
  • Loading branch information
eshaan7 authored Jul 12, 2020
1 parent 1f5634e commit 7119491
Show file tree
Hide file tree
Showing 29 changed files with 168 additions and 93 deletions.
9 changes: 8 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,11 @@ venv/
.vscode/
*.db
.idea/
.github/
.github/
.lgtm.yml
Procfile
app.json
setup.cfg
runtime.txt
migrations/
*.test.py
17 changes: 17 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
##### RTB-CTF-Framework environment variables configuration #####

# Generate a psuedo-random secret with: ..
#... python3 -c "print(__import__('secrets').token_hex(16))"
SECRET_KEY=DontForgetToChangeMe
# If serving over HTTPS, mark this True for added security
SSL_ENABLED=False
# about 2 x number of CPU cores
WORKERS=4
# Choose a strong password for administrator!
ADMIN_PASS=admin
# These values should be the same as specified in .env_postgres
DB_USER=user
DB_PASSWORD=password
DB_NAME=rtbctf
# Don't change
DB_PORT=5432
5 changes: 5 additions & 0 deletions .env_postgres
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Please choose a strong password !!

POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_DB=rtbctf
File renamed without changes.
File renamed without changes.
35 changes: 24 additions & 11 deletions INSTALLATION.md → .github/INSTALLATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

### Requirements

* Tested on `Python 3.8.2`
* Tested on `Python 3.8.3`
* Python Packages: [`src/requirements.txt`](src/requirements.txt).
* OS Packages: PostgreSQL version 11 or greater, `libpq-dev`, `python3-dev` packages. Please refer [here](https://tutorials.technology/solved_errors/9-Error-pg_config-executable-not-found.html).

### Build locally and run
### Build locally and run (Development)

1. Git clone the repo and `cd ` into it

Expand All @@ -22,20 +22,33 @@ $ source venv/bin/activate
$ cd src/
```

3. With `virtual environment` activated, install requirements, init db and run !
3. With `virtual environment` activated, install requirements, init db,

```bash
[venv]$ pip install -r requirements.txt
[venv]$ python create_db.py # Only required on first run
[venv]$ python run.py
[venv]$ chmod +x init_db.sh && ./init_db.sh # Only required on first run
```

> Warning: If you make any change to [`config.py`](https://github.com/abs0lut3pwn4g3/RTB-CTF-Framework/blob/master/src/FlaskRTBCTF/config.py) logging/config class/score settings. It's highly recommended to create a new DB instance.
4. Now we can run our application,

### Docker
- For development server,

> Note: The Docker support is not tested for production yet. It's recommended to use Heroku for production.
```bash
[venv]$ python run.py
```

```bash
$ docker-compose up
```
- Production server

```bash
[venv]$ ./runserver.sh
```

### Docker (Production)

1. Define certain environment variables present in files `.env` and `.env_postgres`.

2. After having configured these environment variables, just execute,

```bash
$ docker-compose up
```
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
__pycache__/
venv/
migrations/
*.pyc
.vscode/
*.db
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM python:3.8.2-alpine3.11
FROM python:3.8.3-alpine3.12

MAINTAINER [email protected]
LABEL maintainer="[email protected]"

# Env
RUN export DATABASE_URL="postgres://${DB_USER}:${DB_PASSWORD}@postgres:${DB_PORT}/${DB_NAME}" \
Expand All @@ -16,8 +16,8 @@ RUN adduser --shell /sbin/login www-data -DH
# Install RTB-CTF-Framework
WORKDIR /usr/src/app
COPY src ./
RUN pip install --no-cache-dir -r requirements.txt \
&& chown -R www-data ./
RUN chown -R www-data ./
RUN pip install --no-cache-dir -r requirements.txt

USER www-data

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The 100 second elevator-pitch is that: A Capture The Flag framework; one that is

## Build locally

Please see [INSTALLATION.md](INSTALLATION.md).
Please see [INSTALLATION.md](.github/INSTALLATION.md).

## Host a customized CTF with Heroku for free in under a minute

Expand Down Expand Up @@ -83,7 +83,7 @@ The main purpose of this project is to serve as a scoring engine and CTF manager

- [#rtb-ctf-framework on slack](https://rtb-ctf-framework.slack.com)

Please refer to [CONTRIBUTING.md](CONTRIBUTING.md)
Please refer to [CONTRIBUTING.md](.github/CONTRIBUTING.md)


## Live Demo
Expand Down
2 changes: 1 addition & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@
}
},
"scripts": {
"postdeploy": "python3 src/create_db.py"
"postdeploy": "bash src/init_db.sh"
}
}
20 changes: 5 additions & 15 deletions docker-compose-for-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,8 @@ services:
restart: unless-stopped
expose:
- "8000"
environment:
- DEBUG=False
- SECRET_KEY=changeme
- DB_USER=eshaan
- DB_PASSWORD=eshaan
- DB_NAME=rtbctf
- DB_PORT=5432
- WORKERS=4
- ADMIN_PASS=admin
env_file:
- .env
depends_on:
- postgres
- redis
Expand All @@ -26,18 +19,15 @@ services:
restart: unless-stopped
expose:
- "5432"
environment:
- POSTGRES_USER=eshaan
- POSTGRES_PASSWORD=eshaan
- POSTGRES_DB=rtbctf
env_file:
- .env_postgres

redis:
image: redis:6.0-rc4-alpine
image: redis:alpine3.12
container_name: rtb_redis
restart: unless-stopped
expose:
- "6379"


nginx:
image: library/nginx:1.16.1-alpine
Expand Down
20 changes: 5 additions & 15 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,8 @@ services:
restart: unless-stopped
expose:
- "8000"
environment:
- DEBUG=False
- SSL_ENABLED=False
- DB_USER=eshaan
- DB_PASSWORD=eshaan
- DB_NAME=rtbctf
- DB_PORT=5432
- WORKERS=4
- ADMIN_PASS=admin
env_file:
- .env
depends_on:
- postgres
- redis
Expand All @@ -25,18 +18,15 @@ services:
restart: unless-stopped
expose:
- "5432"
environment:
- POSTGRES_USER=eshaan
- POSTGRES_PASSWORD=eshaan
- POSTGRES_DB=rtbctf
env_file:
- .env_postgres

redis:
image: redis:6.0-rc4-alpine
image: redis:alpine3.12
container_name: rtb_redis
restart: unless-stopped
expose:
- "6379"


nginx:
image: library/nginx:1.16.1-alpine
Expand Down
14 changes: 13 additions & 1 deletion src/FlaskRTBCTF/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
mail,
inject_app_context,
inject_security_headers,
static_minify,
migrate,
)
from FlaskRTBCTF.users.routes import users
from FlaskRTBCTF.ctf.routes import ctf
Expand All @@ -20,7 +22,15 @@

_blueprints = (users, ctf, main)

_extensions = (db, bcrypt, cache, login_manager, admin_manager, mail)
_extensions = (
db,
bcrypt,
cache,
login_manager,
admin_manager,
mail,
static_minify,
)


def create_app(config_class=Config):
Expand All @@ -32,6 +42,8 @@ def create_app(config_class=Config):
for _ext in _extensions:
_ext.init_app(app)

migrate.init_app(app, db)

for _bp in _blueprints:
app.register_blueprint(_bp)

Expand Down
12 changes: 10 additions & 2 deletions src/FlaskRTBCTF/admin/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,16 @@ def _handle_view(self, name, **kwargs):


class UserAdminView(BaseModelView):
column_exclude_list = ("password",)
form_exclude_list = ("password",)
column_exclude_list = ("password", "_password")
column_details_exclude_list = column_exclude_list
column_descriptions = {
"_password": """
you can change the password here manually,
it will be automatically hashed on save
""",
"isAdmin": "Think twice before checking this field.",
}
form_columns = ("username", "email", "isAdmin", "password")
column_searchable_list = ("username", "email")

@expose("/new/")
Expand Down
4 changes: 1 addition & 3 deletions src/FlaskRTBCTF/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import os
import secrets

# Flask related Configurations
# Note: DO NOT FORGET TO CHANGE 'SECRET_KEY' !


class Config:
DEBUG = False # Turn DEBUG OFF before deployment
SECRET_KEY = secrets.token_hex(16)
SECRET_KEY = os.environ.get("SECRET_KEY", "you-will-never-guess")
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL") or "sqlite:///site.db"
# For local use, one can simply use SQLlite with: 'sqlite:///site.db'
# For deployment on Heroku use: `os.environ.get('DATABASE_URL')`
Expand Down
16 changes: 6 additions & 10 deletions src/FlaskRTBCTF/templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
<h1 class="display-5">Welcome to {{ settings.ctf_name }}</h1>
{% if current_user.is_authenticated %}
<p class="lead">
If you owned the box then you can submit the hashes
<a class="red-underlined-link" href="{{ url_for('ctf.machines') }}">here</a>.
Read the rules and have fun!
</p>
{% else %}
<p class="lead">You need to <a class="red-underlined-link" href="{{ url_for('users.login') }}">login</a> first.</p>
Expand All @@ -22,17 +21,14 @@ <h2 class="title-heading">Rules</h2>
<hr/>
<ul>
<li>Running time:
<code>{{ RunningTime['from'].strftime("%Y-%m-%d %I:%M %p") }}</code>
<code>{{ RunningTime['from'].strftime("%Y-%m-%d %I:%M %p") }}</code>
to
<code>{{ RunningTime['to'].strftime("%Y-%m-%d %I:%M %p") }}</code>
(All times in <code>UTC</code>)
<code>{{ RunningTime['to'].strftime("%Y-%m-%d %I:%M %p") }}</code>
(All times in <code>UTC</code>)
</li>
<li>Needless to say: no bruteforcing (you'll never guess, anyway)</li>
<li>Automated vulnerability scanners will get you nowhere (we know 'cause we made the box)</li>
<li>Attacking this CTF infrastructure website is unnecessary. There are no hints.
This website is for the sole purpose of registration, hash submission and management.</li>
<li>We have tested the machine multiple, I repeat multiple times so if you are receiving a status code of 404 or 301.
Figure it out yourself!</li>
<li>Automated vulnerability scanners will get you nowhere.</li>
<li>Attacking this CTF infrastructure website is unnecessary. There are no hints.</li>
<li>Have fun! :)</li>
</ul>
</div>
Expand Down
14 changes: 12 additions & 2 deletions src/FlaskRTBCTF/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

from flask import current_app
from flask_login import UserMixin
from sqlalchemy.ext.hybrid import hybrid_property

from ..ctf.models import UserChallenge, Challenge, UserMachine, Machine
from ..utils.models import db
from ..utils.cache import cache
from ..utils.bcrypt import bcrypt
from ..utils.login_manager import login_manager


Expand All @@ -22,10 +24,18 @@ class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True, index=True)
username = db.Column(db.String(24), unique=True, nullable=False)
email = db.Column(db.String(88), unique=True, nullable=False)
password = db.Column(db.String(64), nullable=False)
_password = db.Column(db.String(64), nullable=False)
isAdmin = db.Column(db.Boolean, default=False)
logs = db.relationship("Logs", backref="user", lazy=True, uselist=False)

@hybrid_property
def password(self):
return self._password

@password.setter
def password(self, pwd):
self._password = bcrypt.generate_password_hash(pwd).decode("utf-8")

def get_reset_token(self, expires_sec=1800):
s = Serializer(current_app.config["SECRET_KEY"], expires_sec)
return s.dumps({"user_id": self.id}).decode("utf-8")
Expand Down Expand Up @@ -94,4 +104,4 @@ class Logs(db.Model):
rootSubmissionIP = db.Column(db.String, nullable=True)

def __repr__(self):
return f"Logs('{self.user_id}','{self.visitedMachine}')"
return f"Logs('{self.user_id}', vistedMachine: '{self.visitedMachine}')"
10 changes: 6 additions & 4 deletions src/FlaskRTBCTF/users/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ def register():
form = RegistrationForm()

if form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(form.password.data).decode(
"utf-8"
)
# 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
username=form.username.data,
email=form.email.data,
password=form.password.data,
)
log = Logs(
user=user,
Expand Down
2 changes: 2 additions & 0 deletions src/FlaskRTBCTF/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@
from .login_manager import login_manager, admin_only
from .mail import mail, send_reset_email
from .models import db
from .minify import static_minify
from .migrate import migrate
Loading

0 comments on commit 7119491

Please sign in to comment.