update
This commit is contained in:
commit
5f4edf7792
12 changed files with 10631 additions and 61 deletions
|
@ -16,6 +16,10 @@ If you have any issues during installation, file an issue.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
####reCAPTCHA
|
||||||
|
Site Key: *6Lc4xhMTAAAAAIaiF3yEWGbHRaGgMg4FHor61p1G*
|
||||||
|
Secret Key: *6Lc4xhMTAAAAACFaG2NyuKoMdZQtSa_1LI76BCEu*
|
||||||
|
|
||||||
**Resources** : Flask, MySQL
|
**Resources** : Flask, MySQL
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,59 @@ import utils
|
||||||
db = SQLAlchemy()
|
db = SQLAlchemy()
|
||||||
|
|
||||||
class Users(db.Model):
|
class Users(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
uid = db.Column(db.Integer, primary_key=True)
|
||||||
name = db.Column(db.String(64))
|
tid = db.Column(db.Integer)
|
||||||
username = db.Column(db.String(64), unique=True)
|
name = db.Column(db.String(64))
|
||||||
username_lower = db.Column(db.String(64), unique=True)
|
username = db.Column(db.String(64), unique=True)
|
||||||
email = db.Column(db.String(64), unique=True)
|
username_lower = db.Column(db.String(64), unique=True)
|
||||||
password = db.Column(db.String(128))
|
email = db.Column(db.String(64), unique=True)
|
||||||
admin = db.Column(db.Boolean)
|
password = db.Column(db.String(128))
|
||||||
|
admin = db.Column(db.Boolean)
|
||||||
|
|
||||||
def __init__(self, name, username, email, password):
|
def __init__(self, name, username, email, password):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.username = username
|
self.username = username
|
||||||
self.username_lower = username.lower()
|
self.username_lower = username.lower()
|
||||||
self.email = email.lower()
|
self.email = email.lower()
|
||||||
self.password = utils.hash_password(password)
|
self.password = utils.hash_password(password)
|
||||||
|
|
||||||
|
class Teams(db.Model):
|
||||||
|
tid = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(64), unique=True)
|
||||||
|
join_code = db.Column(db.String(128), unique=True)
|
||||||
|
school = db.Column(db.Text)
|
||||||
|
size = db.Column(db.Integer)
|
||||||
|
score = db.Column(db.Integer)
|
||||||
|
observer = db.Column(db.Boolean)
|
||||||
|
owner = db.Column(db.Integer)
|
||||||
|
|
||||||
|
def __init__(self, name, school):
|
||||||
|
self.name = name
|
||||||
|
self.school = school
|
||||||
|
|
||||||
|
class Problems(db.Model):
|
||||||
|
pid = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String(128))
|
||||||
|
description = db.Column(db.Text)
|
||||||
|
hint = db.Column(db.Text)
|
||||||
|
flag = db.Column(db.Text)
|
||||||
|
disabled = db.Column(db.Boolean)
|
||||||
|
value = db.Column(db.Integer)
|
||||||
|
solves = db.Column(db.Integer)
|
||||||
|
|
||||||
|
def __init__(self, name, description, hint, flag, value):
|
||||||
|
self.name = name
|
||||||
|
self.description = description
|
||||||
|
self.hint = hint
|
||||||
|
self.flag = flag
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
class Solves(db.Model):
|
||||||
|
sid = db.Column(db.Integer, primary_key=True)
|
||||||
|
pid = db.Column(db.Integer)
|
||||||
|
tid = db.Column(db.Integer)
|
||||||
|
date = db.Column(db.Integer, default=utils.get_time_since_epoch())
|
||||||
|
|
||||||
|
def __init__(self, pid, tid):
|
||||||
|
self.pid = pid
|
||||||
|
self.tid = tid
|
||||||
|
|
|
@ -1,9 +1,61 @@
|
||||||
from flask import Blueprint
|
from flask import Blueprint, session, request
|
||||||
|
from flask import current_app as app
|
||||||
|
|
||||||
|
from models import db, Users
|
||||||
from utils import api_wrapper
|
from utils import api_wrapper
|
||||||
|
|
||||||
|
import utils
|
||||||
|
|
||||||
blueprint = Blueprint("user", __name__)
|
blueprint = Blueprint("user", __name__)
|
||||||
|
|
||||||
@blueprint.route("/register", methods=["POST"])
|
@blueprint.route("/register", methods=["POST"])
|
||||||
@api_wrapper
|
@api_wrapper
|
||||||
def user_register():
|
def user_register():
|
||||||
return { "success": 0, "message": "Registration is not open yet." }
|
name = request.form["name"]
|
||||||
|
username = request.form["username"]
|
||||||
|
password = request.form["password"]
|
||||||
|
password_confirm = request.form["password_confirm"]
|
||||||
|
email = request.form["email"]
|
||||||
|
|
||||||
|
username_exists = Users.query.add_columns("name", "uid").filter_by(username=username).first()
|
||||||
|
email_exists = Users.query.add_columns("name", "uid").filter_by(email=email).first()
|
||||||
|
|
||||||
|
if password != password_confirm:
|
||||||
|
return { "success": 0, "message": "Passwords do not match." }
|
||||||
|
if len(password) > 128:
|
||||||
|
return { "success": 0, "message": "Password is too long." }
|
||||||
|
if len(password) == 0:
|
||||||
|
return { "success": 0, "message": "Password is too short." }
|
||||||
|
if len(username) > 64:
|
||||||
|
return { "success": 0, "message": "Username is too long." }
|
||||||
|
if username_exists:
|
||||||
|
return { "success": 0, "message": "Username is already taken." }
|
||||||
|
if email_exists:
|
||||||
|
return { "success": 0, "message": "Email has already been used." }
|
||||||
|
|
||||||
|
add_user(name, username, email, password)
|
||||||
|
|
||||||
|
return { "success": 1, "message": "Success!" }
|
||||||
|
|
||||||
|
@blueprint.route("/logout", methods=["POST"])
|
||||||
|
@api_wrapper
|
||||||
|
def user_logout():
|
||||||
|
session.clear()
|
||||||
|
|
||||||
|
@blueprint.route("/login", methods=["POST"])
|
||||||
|
@api_wrapper
|
||||||
|
def user_login():
|
||||||
|
username = request.form["username"]
|
||||||
|
password = request.form["password"]
|
||||||
|
user = Users.query.filter_by(username=username).first()
|
||||||
|
if utils.check_password(user.password, password):
|
||||||
|
session["username"] = username
|
||||||
|
session["admin"] = user.admin
|
||||||
|
return { "success": 1, "message": "Success!" }
|
||||||
|
else:
|
||||||
|
return { "success": 0, "message": "Invalid credentials." }
|
||||||
|
|
||||||
|
def add_user(name, username, email, password):
|
||||||
|
user = Users(name, username, email, password)
|
||||||
|
db.session.add(user)
|
||||||
|
db.session.commit()
|
||||||
|
|
|
@ -40,4 +40,4 @@ def api_wrapper(f):
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
web_result = { "success": 0, "message": "Something went wrong! Please notify us about this immediately.", error: traceback.format_exc() }
|
web_result = { "success": 0, "message": "Something went wrong! Please notify us about this immediately.", error: traceback.format_exc() }
|
||||||
return json.dumps(web_result), response, { "Content-Type": "application/json; charset=utf-8" }
|
return json.dumps(web_result), response, { "Content-Type": "application/json; charset=utf-8" }
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
|
@ -6,32 +6,39 @@ import json
|
||||||
import api
|
import api
|
||||||
|
|
||||||
from api.api import api as api_blueprint
|
from api.api import api as api_blueprint
|
||||||
|
from api.user import blueprint as user_blueprint
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
from api.models import db
|
||||||
|
db.init_app(app)
|
||||||
|
db.create_all()
|
||||||
|
|
||||||
app.secret_key = config.SECRET
|
app.secret_key = config.SECRET
|
||||||
|
app.config["SQLALCHEMY_DATABASE_URI"] = config.SQLALCHEMY_DATABASE_URI
|
||||||
|
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = config.SQLALCHEMY_TRACK_MODIFICATIONS
|
||||||
app.register_blueprint(api_blueprint)
|
app.register_blueprint(api_blueprint)
|
||||||
|
app.register_blueprint(user_blueprint, url_prefix="/api/user")
|
||||||
|
|
||||||
@app.route("/api")
|
@app.route("/api")
|
||||||
def api_main():
|
def api_main():
|
||||||
return json.dumps({ "success": 1, "message": "The API is online." })
|
return json.dumps({ "success": 1, "message": "The API is online." })
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
parser = ArgumentParser(description="EasyCTF Server Configuration")
|
parser = ArgumentParser(description="EasyCTF Server Configuration")
|
||||||
parser.add_argument("-d", "--debug", action="store_true", help="Run the server in debug mode.", default=False)
|
parser.add_argument("-d", "--debug", action="store_true", help="Run the server in debug mode.", default=False)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
keyword_args, _ = dict(args._get_kwargs()), args._get_args()
|
keyword_args, _ = dict(args._get_kwargs()), args._get_args()
|
||||||
|
|
||||||
app.debug = keyword_args["debug"]
|
|
||||||
|
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:i_hate_passwords@localhost/easyctf"
|
|
||||||
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
|
||||||
|
|
||||||
from api.models import db
|
|
||||||
db.init_app(app)
|
|
||||||
db.create_all()
|
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
app.register_blueprint(api.admin.blueprint, url_prefix="/api/admin")
|
app.register_blueprint(api.admin.blueprint, url_prefix="/api/admin")
|
||||||
app.register_blueprint(api.user.blueprint, url_prefix="/api/user")
|
app.register_blueprint(api.user.blueprint, url_prefix="/api/user")
|
||||||
|
|
||||||
app.run(host="0.0.0.0", port=8000)
|
app.run(host="0.0.0.0", port=8000)
|
||||||
|
=======
|
||||||
|
app.debug = keyword_args["debug"]
|
||||||
|
|
||||||
|
app.run(host="0.0.0.0", port=8000)
|
||||||
|
>>>>>>> 6e538e221f28f239512f5c52a7d73ccb0f27576c
|
||||||
|
|
|
@ -10,5 +10,9 @@ with open(".secret_key", "a+") as secret:
|
||||||
key = secret.read()
|
key = secret.read()
|
||||||
|
|
||||||
SECRET = key
|
SECRET = key
|
||||||
|
|
||||||
|
SQLALCHEMY_DATABASE_URI = "mysql://root:i_hate_passwords@localhost/easyctf"
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
|
||||||
CTF_BEGIN = 0 # To be used later
|
CTF_BEGIN = 0 # To be used later
|
||||||
CTF_END = 0 # To be used later
|
CTF_END = 0 # To be used later
|
||||||
|
|
|
@ -3,9 +3,35 @@
|
||||||
<head>
|
<head>
|
||||||
<title>About</title>
|
<title>About</title>
|
||||||
<script src="js/semantic.min.js"></script>
|
<script src="js/semantic.min.js"></script>
|
||||||
|
<script src="js/jquery-1.11.3.js"></script>
|
||||||
<link type="text/css" rel="stylesheet" href="css/semantic.min.css">
|
<link type="text/css" rel="stylesheet" href="css/semantic.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="background-color: #EEEEEE;">
|
||||||
<h1>EasyCTF is Fun!</h1>
|
<div class="ui inverted menu" style="margin: -0.1em; background-color: #FA6900;">
|
||||||
|
<a class="item" href="./">Home</a>
|
||||||
|
<a class="item" href="./about.html">About</a>
|
||||||
|
<a class="item" href="./register.html">Register</a>
|
||||||
|
<div class="right menu">
|
||||||
|
<a class="item" href="./login.html">Login</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<center style="margin-left: 10em; margin-right: 10em;">
|
||||||
|
<h1 style="color: #69D2E7; font-size: 75px;">About EasyCTF</h1>
|
||||||
|
<hr>
|
||||||
|
<br>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2 style="font-size: 2.5em;">Why Capture the Flag?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>No, we're not running around in a gym, tagging other players. <b>Capture the flag</b> contests, or CTFs for short, are intense cybersecurity contests where participants try to capture a piece of information. To do this, they must use skills to capture a <i>virtual</i> flag, usually taking the form of a string, like this: <code>flag{this_is_a_flag}</code>. There are two common types of CTF competitions: <b>jeopardy</b>, and <b>attack-defense</b>.</p>
|
||||||
|
<p>CTFs are different from the hacking you may hear from the news. While hacking is commonly associated with stealing and destruction, CTFs are all about learning and community.</p>
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h2 style="font-size: 2.5em;">EasyCTF</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>EasyCTF is a CTF that's tailored for the high school level. Started by high school students, it was created with a passion for learning. The following events have passed, but the site will remain online for historical purposes.</p>
|
||||||
|
</div>
|
||||||
|
</center>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,4 +1,21 @@
|
||||||
marquee {
|
h1 {
|
||||||
background-color: black;
|
font-size: 75px;
|
||||||
color:white;
|
}
|
||||||
|
::-webkit-input-placeholder {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
:-moz-placeholder { /* Firefox 18- */
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-placeholder { /* Firefox 19+ */
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
:-ms-input-placeholder {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
.intro {
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,31 +25,26 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="background-color: #EEEEEE;">
|
||||||
<div class="ui fixed inverted menu">
|
<div class="ui inverted menu" style="background-color:#FA6900;">
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
<a href="#" class="header item">
|
<a href="#" class="header item">
|
||||||
<img class="logo" src="assets/images/logo.png"> EasyCTF
|
<img class="logo" src="http://placehold.it/40x40">
|
||||||
|
EasyCTF
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="item">Home</a>
|
<a class="item" href="./">Home</a>
|
||||||
<div class="ui simple dropdown item">
|
<a class="item" href="./about.html">About</a>
|
||||||
Dropdown <i class="dropdown icon"></i>
|
<a class="item" href="./register.html">Register</a>
|
||||||
<div class="menu">
|
<div class="right menu">
|
||||||
<a class="item" href="#">Link Item</a>
|
<a class="item" href="./login.html">Login</a>
|
||||||
<a class="item" href="#">Link Item</a>
|
|
||||||
<div class="divider"></div>
|
|
||||||
<div class="header">Header Item</div>
|
|
||||||
<div class="item">
|
|
||||||
<i class="dropdown icon"></i> Sub Menu
|
|
||||||
<div class="menu">
|
|
||||||
<a class="item" href="#">Link Item</a>
|
|
||||||
<a class="item" href="#">Link Item</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a class="item" href="#">Link Item</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="intro">
|
||||||
|
<center>
|
||||||
|
<h1 style="margin-bottom:-0.4em; font-size:75px; color:#69D2E7;">EasyCTF</h1>
|
||||||
|
<h2 style="color:#A7DBDB;">Coming 2016</h2>
|
||||||
|
</center>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
10351
web/js/jquery-1.11.3.js
vendored
Normal file
10351
web/js/jquery-1.11.3.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,30 @@
|
||||||
<script src="js/semantic.min.js"></script>
|
<script src="js/semantic.min.js"></script>
|
||||||
<link type="text/css" rel="stylesheet" href="css/semantic.min.css">
|
<link type="text/css" rel="stylesheet" href="css/semantic.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="background-color: #EEEEEE;">
|
||||||
<h1>Please Login to EasyCTF</h1>
|
<div class="ui inverted menu" style="margin: -0.1em; background-color: #FA6900;">
|
||||||
|
<a class="item" href="./">Home</a>
|
||||||
|
<a class="item" href="./about.html">About</a>
|
||||||
|
<a class="item" href="./register.html">Register</a>
|
||||||
|
<div class="right menu">
|
||||||
|
<a class="item" href="./login.html">Login</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<center>
|
||||||
|
<h1 style="color: #69D2E7; font-size: 75px;">Login</h1>
|
||||||
|
<hr style="margin-left: 10em; margin-right: 10em;">
|
||||||
|
<br>
|
||||||
|
<div class="ui input">
|
||||||
|
<input type="text" placeholder="Username" style="width:50em;">
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<div class="ui input">
|
||||||
|
<input type="password" placeholder="Password" style="width:50em;">
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<button class="ui primary button" style="width:25em">
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
</center>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4,8 +4,57 @@
|
||||||
<title>Register</title>
|
<title>Register</title>
|
||||||
<script src="js/semantic.min.js"></script>
|
<script src="js/semantic.min.js"></script>
|
||||||
<link type="text/css" rel="stylesheet" href="css/semantic.min.css">
|
<link type="text/css" rel="stylesheet" href="css/semantic.min.css">
|
||||||
|
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="background-color: #EEEEEE;">
|
||||||
<h1>Please Register for EasyCTF</h1>
|
<div class="ui inverted menu" style="margin: -0.1em; background-color: #FA6900;">
|
||||||
|
<a class="item" href="./">Home</a>
|
||||||
|
<a class="item" href="./about.html">About</a>
|
||||||
|
<a class="item" href="./register.html">Register</a>
|
||||||
|
<div class="right menu">
|
||||||
|
<a class="item" href="./login.html">Login</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<center>
|
||||||
|
<h1 style="color: #69D2E7; font-size: 75px;">Register Yourself</h1>
|
||||||
|
<hr style="margin-left: 10em; margin-right: 10em;">
|
||||||
|
<br>
|
||||||
|
<div class="ui input">
|
||||||
|
<input type="text" placeholder="Name" id="name" style="width:50em;">
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<select name="gender" class="ui dropdown" id="select" style="width: 50em;">
|
||||||
|
<option value="1">US Middle/High School Student</option>
|
||||||
|
<option value="2">US Middle/High School Teacher</option>
|
||||||
|
<option value="3">Non-US/Non-Student/Observer</option>
|
||||||
|
</select>
|
||||||
|
<br><br>
|
||||||
|
<div class="ui input">
|
||||||
|
<input type="text" placeholder="Username" style="width:50em;">
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<div class="ui input">
|
||||||
|
<input type="email" placeholder="Email" style="width:50em;">
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<div class="ui input">
|
||||||
|
<input type="password" placeholder="Password" style="width:50em;">
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<div class="ui input">
|
||||||
|
<input type="password" placeholder="Confirm Password" style="width:50em;">
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
<div class="g-recaptcha" data-sitekey="6Lc4xhMTAAAAAIaiF3yEWGbHRaGgMg4FHor61p1G"></div>
|
||||||
|
<br><br>
|
||||||
|
<button class="ui primary button" style="width:25em">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</center>
|
||||||
</body>
|
</body>
|
||||||
|
<script>
|
||||||
|
$('#select')
|
||||||
|
.dropdown()
|
||||||
|
;
|
||||||
|
</script>
|
||||||
<html>
|
<html>
|
||||||
|
|
Loading…
Reference in a new issue