def admin_pages(route): if request.method == 'GET' and request.args.get('mode') == 'create': return render_template('admin/editor.html') if route and request.method == 'GET': page = Pages.query.filter_by(route=route).first() return render_template('admin/editor.html', page=page) if route and request.method == 'POST': page = Pages.query.filter_by(route=route).first() errors = [] html = request.form['html'] route = request.form['route'] if not route: errors.append('Missing URL route') if errors: page = Pages(html, "") return render_template('/admin/editor.html', page=page) if page: page.route = route page.html = html db.session.commit() return redirect(url_for('admin.admin_pages')) page = Pages(route, html) db.session.add(page) db.session.commit() return redirect(url_for('admin.admin_pages')) pages = Pages.query.all() return render_template('admin/pages.html', routes=pages, css=get_config('css'))
def setup(): # with app.app_context(): # admin = Teams.query.filter_by(admin=True).first() if not utils.is_setup(): if not session.get('nonce'): session['nonce'] = utils.sha512(os.urandom(10)) if request.method == 'POST': ctf_name = request.form['ctf_name'] ctf_name = utils.set_config('ctf_name', ctf_name) # CSS css = utils.set_config('start', '') # Admin user name = request.form['name'] email = request.form['email'] password = request.form['password'] admin = Teams(name, email, password) admin.admin = True admin.banned = True # Index page page = Pages('index', """<div class="container main-container"> <img class="logo" src="themes/treehacks/static/img/logo.png" /> <h3 class="text-center"> <p>A cool CTF platform from <a href="https://ctfd.io">ctfd.io</a></p> <p>Follow us on social media:</p> <a href="https://twitter.com/ctfdio"><i class="fa fa-twitter fa-2x" aria-hidden="true"></i></a> <a href="https://facebook.com/ctfdio"><i class="fa fa-facebook-official fa-2x" aria-hidden="true"></i></a> <a href="https://github.com/ctfd"><i class="fa fa-github fa-2x" aria-hidden="true"></i></a> </h3> <br> <h4 class="text-center"> <a href="admin">Click here</a> to login and setup your CTF </h4> </div>""".format(request.script_root)) # max attempts per challenge max_tries = utils.set_config('max_tries', 0) # Start time start = utils.set_config('start', None) end = utils.set_config('end', None) freeze = utils.set_config('freeze', None) # Challenges cannot be viewed by unregistered users view_challenges_unregistered = utils.set_config('view_challenges_unregistered', None) # Allow/Disallow registration prevent_registration = utils.set_config('prevent_registration', None) # Verify emails verify_emails = utils.set_config('verify_emails', None) mail_server = utils.set_config('mail_server', None) mail_port = utils.set_config('mail_port', None) mail_tls = utils.set_config('mail_tls', None) mail_ssl = utils.set_config('mail_ssl', None) mail_username = utils.set_config('mail_username', None) mail_password = utils.set_config('mail_password', None) mail_useauth = utils.set_config('mail_useauth', None) setup = utils.set_config('setup', True) db.session.add(page) db.session.add(admin) db.session.commit() session['username'] = admin.name session['id'] = admin.id session['admin'] = admin.admin session['nonce'] = utils.sha512(os.urandom(10)) db.session.close() app.setup = False with app.app_context(): cache.clear() return redirect(url_for('views.static_html')) return render_template('setup.html', nonce=session.get('nonce')) return redirect(url_for('views.static_html'))
def setup(): # with app.app_context(): # admin = Teams.query.filter_by(admin=True).first() if not utils.is_setup(): if not session.get('nonce'): session['nonce'] = utils.sha512(os.urandom(10)) if request.method == 'POST': ctf_name = request.form['ctf_name'] ctf_name = utils.set_config('ctf_name', ctf_name) # CSS css = utils.set_config('start', '') # Admin user name = request.form['name'] email = request.form['email'] password = request.form['password'] admin = Teams(name, email, password) admin.admin = True admin.banned = True # Index page page = Pages( 'index', """<div class="container main-container"> <img class="logo" src="{0}/static/original/img/logo.png" /> <h3 class="text-center"> Welcome to a cool CTF framework written by <a href="https://github.com/ColdHeat">Kevin Chung</a> of <a href="https://github.com/isislab">@isislab</a> </h3> <h4 class="text-center"> <a href="{0}/admin">Click here</a> to login and setup your CTF </h4> </div>""".format(request.script_root)) # max attempts per challenge max_tries = utils.set_config('max_tries', 0) # Start time start = utils.set_config('start', None) end = utils.set_config('end', None) freeze = utils.set_config('freeze', None) # Challenges cannot be viewed by unregistered users view_challenges_unregistered = utils.set_config( 'view_challenges_unregistered', None) # Allow/Disallow registration prevent_registration = utils.set_config('prevent_registration', None) # Verify emails verify_emails = utils.set_config('verify_emails', None) mail_server = utils.set_config('mail_server', None) mail_port = utils.set_config('mail_port', None) mail_tls = utils.set_config('mail_tls', None) mail_ssl = utils.set_config('mail_ssl', None) mail_username = utils.set_config('mail_username', None) mail_password = utils.set_config('mail_password', None) setup = utils.set_config('setup', True) db.session.add(page) db.session.add(admin) db.session.commit() session['username'] = admin.name session['id'] = admin.id session['admin'] = admin.admin session['nonce'] = utils.sha512(os.urandom(10)) db.session.close() app.setup = False with app.app_context(): cache.clear() return redirect(url_for('views.static_html')) return render_template('setup.html', nonce=session.get('nonce')) return redirect(url_for('views.static_html'))
def import_ctf(backup, segments=None, erase=False): side_db = dataset.connect(get_config('SQLALCHEMY_DATABASE_URI')) if segments is None: segments = ['challenges', 'teams', 'both', 'metadata'] if not zipfile.is_zipfile(backup): raise TypeError backup = zipfile.ZipFile(backup) groups = { 'challenges': [ 'challenges', 'files', 'tags', 'keys', 'hints', ], 'teams': [ 'teams', 'tracking', 'awards', ], 'both': [ 'solves', 'wrong_keys', 'unlocks', ], 'metadata': [ 'alembic_version', 'config', 'pages', 'containers', ] } # Need special handling of metadata if 'metadata' in segments: meta = groups['metadata'] segments.remove('metadata') meta.remove('alembic_version') for item in meta: table = side_db[item] path = "db/{}.json".format(item) data = backup.open(path).read() # Some JSON files will be empty if data: if item == 'config': saved = json.loads(data) for entry in saved['results']: key = entry['key'] value = entry['value'] set_config(key, value) elif item == 'pages': saved = json.loads(data) for entry in saved['results']: route = entry['route'] html = entry['html'] page = Pages.query.filter_by(route=route).first() if page: page.html = html else: page = Pages(route, html) db.session.add(page) db.session.commit() elif item == 'containers': saved = json.loads(data) for entry in saved['results']: name = entry['name'] buildfile = entry['buildfile'] container = Containers.query.filter_by(name=name).first() if container: container.buildfile = buildfile else: container = Containers(name, buildfile) db.session.add(container) db.session.commit() for segment in segments: group = groups[segment] for item in group: table = side_db[item] path = "db/{}.json".format(item) data = backup.open(path).read() if data: saved = json.loads(data) for entry in saved['results']: entry_id = entry.pop('id', None) table.insert(entry) else: continue # Extracting files files = [f for f in backup.namelist() if f.startswith('uploads/')] upload_folder = app.config.get('UPLOAD_FOLDER') for f in files: filename = f.split(os.sep, 1) if len(filename) < 2: # just an empty uploads directory (e.g. uploads/) continue filename = filename[1] # Get the second entry in the list (the actual filename) full_path = os.path.join(upload_folder, filename) dirname = os.path.dirname(full_path) # Create any parent directories for the file if not os.path.exists(dirname): os.makedirs(dirname) source = backup.open(f) target = file(full_path, "wb") with source, target: shutil.copyfileobj(source, target)
def import_ctf(backup, segments=None, erase=False): side_db = dataset.connect(get_app_config('SQLALCHEMY_DATABASE_URI')) if segments is None: segments = ['challenges', 'teams', 'both', 'metadata'] if not zipfile.is_zipfile(backup): raise TypeError backup = zipfile.ZipFile(backup) groups = { 'challenges': [ 'challenges', 'files', 'tags', 'keys', 'hints', ], 'teams': [ 'teams', 'tracking', 'awards', ], 'both': [ 'solves', 'wrong_keys', 'unlocks', ], 'metadata': [ 'alembic_version', 'config', 'pages', ] } # Need special handling of metadata if 'metadata' in segments: meta = groups['metadata'] segments.remove('metadata') meta.remove('alembic_version') for item in meta: table = side_db[item] path = "db/{}.json".format(item) data = backup.open(path).read() # Some JSON files will be empty if data: if item == 'config': saved = json.loads(data) for entry in saved['results']: key = entry['key'] value = entry['value'] set_config(key, value) elif item == 'pages': saved = json.loads(data) for entry in saved['results']: # Support migration c12d2a1b0926_add_draft_and_title_to_pages route = entry['route'] title = entry.get('title', route.title()) html = entry['html'] draft = entry.get('draft', False) auth_required = entry.get('auth_required', False) page = Pages.query.filter_by(route=route).first() if page: page.html = html else: page = Pages(title, route, html, draft=draft, auth_required=auth_required) db.session.add(page) db.session.commit() teams_base = db.session.query(db.func.max(Teams.id)).scalar() or 0 chals_base = db.session.query(db.func.max(Challenges.id)).scalar() or 0 for segment in segments: group = groups[segment] for item in group: table = side_db[item] path = "db/{}.json".format(item) data = backup.open(path).read() if data: saved = json.loads(data) for entry in saved['results']: entry_id = entry.pop('id', None) # This is a hack to get SQlite to properly accept datetime values from dataset # See Issue #246 if get_app_config('SQLALCHEMY_DATABASE_URI').startswith( 'sqlite'): for k, v in entry.items(): if isinstance(v, six.string_types): match = re.match( r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d", v) if match: entry[k] = datetime.datetime.strptime( v, '%Y-%m-%dT%H:%M:%S.%f') continue match = re.match( r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}", v) if match: entry[k] = datetime.datetime.strptime( v, '%Y-%m-%dT%H:%M:%S') continue for k, v in entry.items(): if k == 'chal' or k == 'chalid': entry[k] += chals_base if k == 'team' or k == 'teamid': entry[k] += teams_base if item == 'teams': table.insert_ignore(entry, ['email']) elif item == 'keys': # Support migration 2539d8b5082e_rename_key_type_to_type key_type = entry.get('key_type', None) if key_type is not None: entry['type'] = key_type del entry['key_type'] table.insert(entry) else: table.insert(entry) else: continue # Extracting files files = [f for f in backup.namelist() if f.startswith('uploads/')] upload_folder = app.config.get('UPLOAD_FOLDER') for f in files: filename = f.split(os.sep, 1) if len(filename ) < 2: # just an empty uploads directory (e.g. uploads/) continue filename = filename[ 1] # Get the second entry in the list (the actual filename) full_path = os.path.join(upload_folder, filename) dirname = os.path.dirname(full_path) # Create any parent directories for the file if not os.path.exists(dirname): os.makedirs(dirname) source = backup.open(f) target = open(full_path, "wb") with source, target: shutil.copyfileobj(source, target)
def setup(): # with app.app_context(): # admin = Teams.query.filter_by(admin=True).first() if not utils.is_setup(): if not session.get('nonce'): session['nonce'] = utils.sha512(os.urandom(10)) if request.method == 'POST': ctf_name = request.form['ctf_name'] ctf_name = utils.set_config('ctf_name', ctf_name) # CSS css = utils.set_config('start', '') # Admin user name = request.form['name'] email = request.form['email'] password = request.form['password'] admin = Teams(name, email, password) admin.admin = True admin.banned = True # Index page index = """<div class="row"> <style> .col-container:after { content: ""; display: table; clear: both; } .col { float: left; } .clearfix::after { content: ""; display: table; clear: both; } .footer-nav{ float: left; } .logo{ float: right; } .footer-nav, .footer-nav li{ display: inline; } </style> <div class="col-md-6 offset-md-3"> <h1 class="text-center" style="padding-top: 10vh; font-size: 50px;"> <b>Haaukins</b> </h1> <p class="text-center"> A platform for Cyber Security Exercises </p> <p class="text-center"> Founded by <a href="http://danishcybersecurityclusters.dk/">Danish Cyber Security Clusters</a> and supported by </p> <a href="https://www.industriensfond.dk/"> <img class="w-100 mx-auto d-block" style="max-width: 300px; padding: 3vh 0 4vh 0;" src="/themes/core/static/img/logo_industrienfond.jpg"> </a> <p class="text-center"> <p class="text-center"> Developed at <a href="http://es.aau.dk/">Aalborg University</a> (Department of Electronic Systems) by: </p> <div class="col-container" style="margin-top: 40px;"> <div class="col" style="width: 40%"> <img src="/themes/core/static/img/haaukins_logo_blue240px.png" style="margin-left: 20px; max-width: 170px;"> </div> <div class="col" style="width: 60%; font-size:14px;"> <p><a href="https://mrturkmen.com">Ahmet Turkmen</a> (Research Assistant)</p> <p><a href="https://github.com/eyJhb">Gian Marco Mennecozzi</a> (Research Assistant)</p> <p><a href="https://github.com/kdhageman">Kaspar Hageman</a> (Ph.D. Student)</p> <p><a href="https://github.com/tpanum">Thomas Kobber Panum</a> (Ph.D. Student)</p> <p><a href="https://github.com/eyJhb">Johan Hempel Bengtson</a> (Student Helper)</p> </div> </div> </p> <div class="card-deck py-4"> <div class="card"> <div class="card-body"> <h5 class="card-title">Tips and tricks</h5> <div class="card-text"> Stuck at a certain challenge? Or do you just want to know more about a certain topic? </div> </div> <div class="card-footer"> <a href="https://aau-network-security.github.io/tips-and-tricks/" target="_blank">Vist the tips & tricks page</a> </div> </div> <div class="card"> <div class="card-body"> <h5 class="card-title">Survey</h5> <p>You can help us improve the platform by taking our survey to let us know about your experiences!</p> </div> <div class="card-footer"> <a href="https://www.survey-xact.dk/LinkCollector?key=KDRVSTDJJN15" target="_blank">Fill out the survey here</a> </div> </div> </div> <p class="text-center"> Feel free to join our local Facebook Group: </p> <p class="text-center"> <a href="https://www.facebook.com/groups/957517617737780"><i class="fab fa-facebook" aria-hidden="true"></i> AAU Hackers & Friends</a> </p> <div class="container"> <footer> <ul class="footer-nav"> <li><a href="https://eadania.dk/"> <img src="/themes/core/static/img/da-90.png" style= "width:90px; height:75px;" ></a></li> <li><a href="https://www.dtu.dk/"><img src="/themes/core/static/img/dtu-90.png" style= "width:90px; height:75px;"></a></li> <li><a href="https://kea.dk/"> <img src="/themes/core/static/img/kea-90.jpg" style= "width:90px; height:75px;" ></a></li> <li><a href="https://happy42.dk/"> <img src="/themes/core/static/img/happy-90.png" style= "width:90px; height:75px;" ></a></li> <li><a href="https://www.eaaa.dk/"><img src="/themes/core/static/img/eaa-90.png" style= "width:90px; height:75px;"></a></li> </ul> </footer> </div> </div> </div>""" page = Pages(title=None, route='index', html=index, draft=False) # max attempts per challenge max_tries = utils.set_config('max_tries', 0) # Start time start = utils.set_config('start', None) end = utils.set_config('end', None) freeze = utils.set_config('freeze', None) # Challenges cannot be viewed by unregistered users view_challenges_unregistered = utils.set_config( 'view_challenges_unregistered', None) # Allow/Disallow registration prevent_registration = utils.set_config('prevent_registration', None) # Verify emails verify_emails = utils.set_config('verify_emails', None) mail_server = utils.set_config('mail_server', None) mail_port = utils.set_config('mail_port', None) mail_tls = utils.set_config('mail_tls', None) mail_ssl = utils.set_config('mail_ssl', None) mail_username = utils.set_config('mail_username', None) mail_password = utils.set_config('mail_password', None) mail_useauth = utils.set_config('mail_useauth', None) setup = utils.set_config('setup', True) db.session.add(page) db.session.add(admin) db.session.commit() session['username'] = admin.name session['id'] = admin.id session['admin'] = admin.admin session['nonce'] = utils.sha512(os.urandom(10)) db.session.close() app.setup = False with app.app_context(): cache.clear() return redirect(url_for('views.static_html')) return render_template('setup.html', nonce=session.get('nonce')) return redirect(url_for('views.static_html'))
def setup(): # with app.app_context(): # admin = Teams.query.filter_by(admin=True).first() if not is_setup(): if not session.get('nonce'): session['nonce'] = sha512(os.urandom(10)) if request.method == 'POST': ctf_name = request.form['ctf_name'] ctf_name = set_config('ctf_name', ctf_name) ## CSS css = set_config('start', '') ## Admin user name = request.form['name'] email = request.form['email'] password = request.form['password'] admin = Teams(name, email, password) admin.admin = True admin.banned = True ## Index page page = Pages( 'index', """<div class="container main-container"> <img class="logo" src="{0}/static/original/img/logo.jpg" /> <h3 class="text-center"> Welcome to pogTeam's recruiting CTF! Keep in touch through our IRC chan ##pogTeam (freenode) or our <a href="https://t.me/pogTeamPublico">Telegram chan</a>! </h3> <h4 class="text-center"> <a href="{0}/admin">Click here</a> to login and setup your CTF </h4> </div>""".format(request.script_root)) #max attempts per challenge max_tries = set_config("max_tries", 0) ## Start time start = set_config('start', None) end = set_config('end', None) ## Challenges cannot be viewed by unregistered users view_challenges_unregistered = set_config( 'view_challenges_unregistered', None) ## Allow/Disallow registration prevent_registration = set_config('prevent_registration', None) ## Verify emails verify_emails = set_config('verify_emails', None) mail_server = set_config('mail_server', None) mail_port = set_config('mail_port', None) mail_tls = set_config('mail_tls', None) mail_ssl = set_config('mail_ssl', None) mail_username = set_config('mail_username', None) mail_password = set_config('mail_password', None) setup = set_config('setup', True) db.session.add(page) db.session.add(admin) db.session.commit() db.session.close() app.setup = False with app.app_context(): cache.clear() return redirect(url_for('views.static_html')) return render_template('setup.html', nonce=session.get('nonce')) return redirect(url_for('views.static_html'))
def setup(): if not config.is_setup(): if not session.get('nonce'): session['nonce'] = generate_nonce() if request.method == 'POST': ctf_name = request.form['ctf_name'] set_config('ctf_name', ctf_name) # CSS set_config('start', '') # Admin user name = request.form['name'] email = request.form['email'] password = request.form['password'] admin = Admins(name=name, email=email, password=password, type='admin', hidden=True) user_mode = request.form['user_mode'] set_config('user_mode', user_mode) # Index page index = """<div class="row"> <div class="col-md-6 offset-md-3"> <img class="w-100 mx-auto d-block" style="max-width: 500px;padding: 50px;padding-top: 14vh;" src="themes/core/static/img/uioctf_logo.png" /> <h3 class="text-center"> <p>A cool CTF platform from <a href="https://ctfd.io">ctfd.io</a></p> <p>Follow us on social media:</p> <a href="https://twitter.com/ctfdio"><i class="fab fa-twitter fa-2x" aria-hidden="true"></i></a> <a href="https://facebook.com/ctfdio"><i class="fab fa-facebook fa-2x" aria-hidden="true"></i></a> <a href="https://github.com/ctfd"><i class="fab fa-github fa-2x" aria-hidden="true"></i></a> </h3> <br> <h4 class="text-center"> <a href="admin">Click here</a> to login and setup your CTF </h4> </div> </div>""".format(request.script_root) page = Pages(title=None, route='index', content=index, draft=False) # Visibility set_config('challenge_visibility', 'private') set_config('registration_visibility', 'public') set_config('score_visibility', 'public') set_config('account_visibility', 'public') # Start time set_config('start', None) set_config('end', None) set_config('freeze', None) # Verify emails set_config('verify_emails', None) set_config('mail_server', None) set_config('mail_port', None) set_config('mail_tls', None) set_config('mail_ssl', None) set_config('mail_username', None) set_config('mail_password', None) set_config('mail_useauth', None) setup = set_config('setup', True) try: db.session.add(admin) db.session.commit() except IntegrityError: db.session.rollback() try: db.session.add(page) db.session.commit() except IntegrityError: db.session.rollback() login_user(admin) db.session.close() app.setup = False with app.app_context(): cache.clear() return redirect(url_for('views.static_html')) return render_template('setup.html', nonce=session.get('nonce')) return redirect(url_for('views.static_html'))
def setup(): errors = get_errors() if not config.is_setup(): if not session.get("nonce"): session["nonce"] = generate_nonce() if request.method == "POST": # General ctf_name = request.form.get("ctf_name") ctf_description = request.form.get("ctf_description") user_mode = request.form.get("user_mode", USERS_MODE) set_config("ctf_name", ctf_name) set_config("ctf_description", ctf_description) set_config("user_mode", user_mode) # Style ctf_logo = request.files.get("ctf_logo") if ctf_logo: f = upload_file(file=ctf_logo) set_config("ctf_logo", f.location) ctf_small_icon = request.files.get("ctf_small_icon") if ctf_small_icon: f = upload_file(file=ctf_small_icon) set_config("ctf_small_icon", f.location) theme = request.form.get("ctf_theme", DEFAULT_THEME) set_config("ctf_theme", theme) theme_color = request.form.get("theme_color") theme_header = get_config("theme_header") if theme_color and bool(theme_header) is False: # Uses {{ and }} to insert curly braces while using the format method css = ( '<style id="theme-color">\n' ":root {{--theme-color: {theme_color};}}\n" ".navbar{{background-color: var(--theme-color) !important;}}\n" ".jumbotron{{background-color: var(--theme-color) !important;}}\n" "</style>\n" ).format(theme_color=theme_color) set_config("theme_header", css) # DateTime start = request.form.get("start") end = request.form.get("end") set_config("start", start) set_config("end", end) set_config("freeze", None) # Administration name = request.form["name"] email = request.form["email"] password = request.form["password"] name_len = len(name) == 0 names = Users.query.add_columns("name", "id").filter_by(name=name).first() emails = ( Users.query.add_columns("email", "id").filter_by(email=email).first() ) pass_short = len(password) == 0 pass_long = len(password) > 128 valid_email = validators.validate_email(request.form["email"]) team_name_email_check = validators.validate_email(name) if not valid_email: errors.append("Please enter a valid email address") if names: errors.append("That user name is already taken") if team_name_email_check is True: errors.append("Your user name cannot be an email address") if emails: errors.append("That email has already been used") if pass_short: errors.append("Pick a longer password") if pass_long: errors.append("Pick a shorter password") if name_len: errors.append("Pick a longer user name") if len(errors) > 0: return render_template( "setup.html", errors=errors, name=name, email=email, password=password, state=serialize(generate_nonce()), ) admin = Admins( name=name, email=email, password=password, type="admin", hidden=True ) # Create an empty index page page = Pages(title=None, route="index", content="", draft=False) # Upload banner default_ctf_banner_location = url_for("views.themes", path="img/logo.png") ctf_banner = request.files.get("ctf_banner") if ctf_banner: f = upload_file(file=ctf_banner, page_id=page.id) default_ctf_banner_location = url_for("views.files", path=f.location) # Splice in our banner index = f"""<div class="row"> <div class="col-md-6 offset-md-3"> <img class="w-100 mx-auto d-block" style="max-width: 500px;padding: 50px;padding-top: 14vh;" src="{default_ctf_banner_location}" /> <h3 class="text-center"> <p>A cool CTF platform from <a href="https://ctfd.io">ctfd.io</a></p> <p>Follow us on social media:</p> <a href="https://twitter.com/ctfdio"><i class="fab fa-twitter fa-2x" aria-hidden="true"></i></a> <a href="https://facebook.com/ctfdio"><i class="fab fa-facebook fa-2x" aria-hidden="true"></i></a> <a href="https://github.com/ctfd"><i class="fab fa-github fa-2x" aria-hidden="true"></i></a> </h3> <br> <h4 class="text-center"> <a href="admin">Click here</a> to login and setup your CTF </h4> </div> </div>""" page.content = index # Visibility set_config( ConfigTypes.CHALLENGE_VISIBILITY, ChallengeVisibilityTypes.PRIVATE ) set_config( ConfigTypes.REGISTRATION_VISIBILITY, RegistrationVisibilityTypes.PUBLIC ) set_config(ConfigTypes.SCORE_VISIBILITY, ScoreVisibilityTypes.PUBLIC) set_config(ConfigTypes.ACCOUNT_VISIBILITY, AccountVisibilityTypes.PUBLIC) # Verify emails set_config("verify_emails", None) set_config("mail_server", None) set_config("mail_port", None) set_config("mail_tls", None) set_config("mail_ssl", None) set_config("mail_username", None) set_config("mail_password", None) set_config("mail_useauth", None) # Set up default emails set_config("verification_email_subject", DEFAULT_VERIFICATION_EMAIL_SUBJECT) set_config("verification_email_body", DEFAULT_VERIFICATION_EMAIL_BODY) set_config( "successful_registration_email_subject", DEFAULT_SUCCESSFUL_REGISTRATION_EMAIL_SUBJECT, ) set_config( "successful_registration_email_body", DEFAULT_SUCCESSFUL_REGISTRATION_EMAIL_BODY, ) set_config( "user_creation_email_subject", DEFAULT_USER_CREATION_EMAIL_SUBJECT ) set_config("user_creation_email_body", DEFAULT_USER_CREATION_EMAIL_BODY) set_config("password_reset_subject", DEFAULT_PASSWORD_RESET_SUBJECT) set_config("password_reset_body", DEFAULT_PASSWORD_RESET_BODY) set_config( "password_change_alert_subject", "Password Change Confirmation for {ctf_name}", ) set_config( "password_change_alert_body", ( "Your password for {ctf_name} has been changed.\n\n" "If you didn't request a password change you can reset your password here: {url}" ), ) set_config("setup", True) try: db.session.add(admin) db.session.commit() except IntegrityError: db.session.rollback() try: db.session.add(page) db.session.commit() except IntegrityError: db.session.rollback() login_user(admin) db.session.close() with app.app_context(): cache.clear() return redirect(url_for("views.static_html")) try: return render_template("setup.html", state=serialize(generate_nonce())) except TemplateNotFound: # Set theme to default and try again set_config("ctf_theme", DEFAULT_THEME) return render_template("setup.html", state=serialize(generate_nonce())) return redirect(url_for("views.static_html"))
def setup(): # with app.app_context(): # admin = Teams.query.filter_by(admin=True).first() if not utils.is_setup(): if not session.get('nonce'): session['nonce'] = utils.sha512(os.urandom(10)) if request.method == 'POST': ctf_name = request.form['ctf_name'] ctf_name = utils.set_config('ctf_name', ctf_name) # CSS css = utils.set_config('start', '') # Admin user name = request.form['name'] email = request.form['email'] password = request.form['password'] admin = Teams(name, email, password) admin.admin = True admin.banned = True # Index page index = """<div class="row"> <div class="intro"> <img width=30 src="themes/arg/static/img/logo.png" /> <br> <br> <p> the console will set you free </p> <script> console_message('ef98fe223e630bbb82dd9c41323e3290') </script> <br> </div> </div>""".format(request.script_root) page = Pages(title=None, route='index', html=index, draft=False) # max attempts per challenge max_tries = utils.set_config('max_tries', 0) # Start time start = utils.set_config('start', None) end = utils.set_config('end', None) freeze = utils.set_config('freeze', None) # Challenges cannot be viewed by unregistered users view_challenges_unregistered = utils.set_config( 'view_challenges_unregistered', None) # Allow/Disallow registration prevent_registration = utils.set_config('prevent_registration', None) # Verify emails verify_emails = utils.set_config('verify_emails', None) mail_server = utils.set_config('mail_server', None) mail_port = utils.set_config('mail_port', None) mail_tls = utils.set_config('mail_tls', None) mail_ssl = utils.set_config('mail_ssl', None) mail_username = utils.set_config('mail_username', None) mail_password = utils.set_config('mail_password', None) mail_useauth = utils.set_config('mail_useauth', None) setup = utils.set_config('setup', True) db.session.add(page) db.session.add(admin) db.session.commit() session['username'] = admin.name session['id'] = admin.id session['admin'] = admin.admin session['nonce'] = utils.sha512(os.urandom(10)) db.session.close() app.setup = False with app.app_context(): cache.clear() return redirect(url_for('views.static_html')) return render_template('setup.html', nonce=session.get('nonce')) return redirect(url_for('views.static_html'))
def admin_pages_view(): page_id = request.args.get('id') page_op = request.args.get('operation') if request.method == 'GET' and page_op == 'preview': page = Pages.query.filter_by(id=page_id).first_or_404() return render_template('page.html', content=markdown(page.html)) if request.method == 'GET' and page_op == 'create': return render_template('admin/editor.html') if page_id and request.method == 'GET': page = Pages.query.filter_by(id=page_id).first() return render_template('admin/editor.html', page=page) if request.method == 'POST': page_form_id = request.form.get('id') title = request.form['title'] html = request.form['html'] route = request.form['route'].lstrip('/') auth_required = 'auth_required' in request.form if page_op == 'preview': page = Pages(title, route, html, draft=False) return render_template('page.html', content=markdown(page.html)) page = Pages.query.filter_by(id=page_form_id).first() errors = [] if not route: errors.append('Missing URL route') if errors: page = Pages(title, html, route) return render_template('/admin/editor.html', page=page) if page: page.title = title page.route = route page.html = html page.auth_required = auth_required if page_op == 'publish': page.draft = False db.session.commit() data = { 'result': 'success', 'operation': page_op, 'page': { 'id': page.id, 'route': page.route, 'title': page.title } } db.session.close() cache.clear() return jsonify(data) if page_op == 'publish': page = Pages(title, route, html, draft=False, auth_required=auth_required) elif page_op == 'save': page = Pages(title, route, html, auth_required=auth_required) db.session.add(page) db.session.commit() data = { 'result': 'success', 'operation': page_op, 'page': { 'id': page.id, 'route': page.route, 'title': page.title } } db.session.close() cache.clear() return jsonify(data) pages = Pages.query.all() return render_template('admin/pages.html', pages=pages)
def load(app): shell = Blueprint('shell', __name__, template_folder='shell-templates') app.register_blueprint(shell, url_prefix='/shell') page = Pages('shell', """ """) auth = Blueprint('auth', __name__) shellexists = Pages.query.filter_by(route='shell').first() if not shellexists: db.session.add(page) db.session.commit() @app.route('/shell', methods=['GET']) def shell_view(): if not authed(): return redirect(url_for('auth.login', next=request.path)) return render_template('shell.html', root=request.script_root) @app.route('/register', methods=['POST', 'GET']) def register(): if not can_register(): return redirect(url_for('auth.login')) if request.method == 'POST': errors = [] name = request.form['name'] email = request.form['email'] password = request.form['password'] name_len = len(name) < 2 names = Teams.query.add_columns('name', 'id').filter_by(name=name).first() emails = Teams.query.add_columns( 'email', 'id').filter_by(email=email).first() pass_short = len(password) == 0 pass_long = len(password) > 32 valid_email = re.match( r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", request.form['email']) if not valid_email: errors.append("That email doesn't look right") if names: errors.append('That team name is already taken') if emails: errors.append('That email has already been used') if pass_short: errors.append('Pick a longer password') if pass_long: errors.append('Pick a shorter password') if name_len: errors.append('Pick a longer team name') if len(errors) > 0: return render_template('register.html', errors=errors, name=request.form['name'], email=request.form['email'], password=request.form['password']) else: with app.app_context(): team = Teams(name, email.lower(), password) db.session.add(team) db.session.commit() db.session.flush() shell = xmlrpclib.ServerProxy('http://*****:*****@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email) password = request.form['password'].strip() pass_short = len(password) == 0 pass_long = len(password) > 32 if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append( "Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if not get_config('prevent_name_change' ) and names and name != session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if not get_config('prevent_name_change') and name_len: errors.append('Pick a longer team name') if website.strip() and not validate_url(website): errors.append("That doesn't look like a valid URL") if pass_short: errors.append('Pick a longer password') if pass_long: errors.append('Pick a shorter password') if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if not get_config('prevent_name_change'): team.name = name if team.email != email.lower(): team.email = email.lower() if get_config('verify_emails'): team.verified = False session['username'] = team.name if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) password = request.form['password'].strip() team.website = website team.affiliation = affiliation team.country = country name = team.name if password: shell = xmlrpclib.ServerProxy('http://localhost:8000', allow_none=True) shell.change_user(name, password) db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = get_config('prevent_name_change') confirm_email = get_config( 'verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login')) app.view_functions['auth.reset_password'] = reset_password app.view_functions['auth.register'] = register app.view_functions['views.profile'] = profile
def load_bp(admin_route, base_route, plugin_dir='.'): @writeups_bp.route(f"{base_route}/assets/<path:path>", methods=["GET"]) def assets(path: str): return send_from_directory(f"{plugin_dir}/assets", path) @writeups_bp.route(admin_route, methods=["POST"]) @admins_only def update_config(): form = request.form.to_dict() del form['nonce'] challenges = defaultdict(lambda: {}) for k, v in form.items(): match = re.match(r'(?P<id>\d+)-(?P<prop>[a-zA-Z0-9-_]+)', k) if match: challenges[int(match.group('id'))][match.group('prop')] = v else: print(f"Unrecognized form key {k}") for challenge_id, props in challenges.items(): challenge = Challenges.query.get(challenge_id) if 'accepting_wu' in props: if not challenge.writeup_challenge: challenge.writeup_challenge = WriteUpChallenges( name=f"Write-Up for {challenge.name}", description='', category='Write-Ups') challenge.writeup_challenge.value = props.get('wu_value', 5) challenge.writeup_challenge.solve_req = 'vis_before_solve' not in props submit_str = f"\n\n[Submit a write-up]({url_for('writeups.edit_writeup', challenge_id=challenge.id)}) for this challenge (+{challenge.writeup_challenge.value} pts.) or [view others']({url_for('writeups.writeups', challenge=challenge.id)}) write-ups." submit_re = r'\[Submit a write-up]\(.+\) for this challenge \(\+\d+ pts\.\) or \[view others\']\(.+\) write-ups\.' if not re.search(submit_re, challenge.description): challenge.description += submit_str else: challenge.description = re.sub(submit_re, submit_str, challenge.description) elif challenge.writeup_challenge: db.session.delete(challenge.writeup_challenge) db.session.commit() return get_config() @writeups_bp.route(admin_route, methods=["GET"]) @admins_only def get_config(): challenges = db.session.query(Challenges).filter( Challenges.type != 'writeup').all() submissions = (db.session.query(Submissions).join( WriteUpChallenges, Submissions.challenge_id == WriteUpChallenges.id)).all() rows = [] for challenge in challenges: rows.append({ 'id': challenge.id, 'name': challenge.name, 'value': challenge.value, 'accepting_wu': bool(challenge.writeup_challenge), 'wu_value': challenge.writeup_challenge.value if challenge.writeup_challenge else 0, 'solve_req': challenge.writeup_challenge.solve_req if challenge.writeup_challenge else True }) return render_template("writeups_admin.html", challenges=rows, writeups=submissions) @writeups_bp.route(base_route, methods=["GET"]) @during_ctf_time_only @authed_only def writeups(): user = get_current_user() page = db.session.query(Pages).filter( Pages.route == base_route).one_or_none() if user.type == 'admin': visible_writeups = (db.session.query(Submissions).join( WriteUpChallenges, Submissions.challenge_id == WriteUpChallenges.id)) else: solves_ids = [s.challenge_id for s in user.team.solves] if user.team else [] visible_writeups = (db.session.query(Submissions).join( WriteUpChallenges, Submissions.challenge_id == WriteUpChallenges.id).filter( WriteUpChallenges.for_id.in_(solves_ids) | ~WriteUpChallenges.solve_req | (Submissions.user_id == user.id))) if 'challenge' in request.args: visible_writeups = visible_writeups.filter( WriteUpChallenges.for_id == request.args['challenge']) visible_writeups = visible_writeups.all() return render_template("writeups.html", writeups=visible_writeups, page_content=page.content if page else '') @writeups_bp.route(f"{base_route}/<int:writeup_id>", methods=["GET"]) @during_ctf_time_only @authed_only def view_writeup(writeup_id: int): user = get_current_user() writeup = db.session.query(Submissions).get(writeup_id) error = {} content = '' editable = False if writeup.challenge.type != 'writeup': return redirect(url_for('writeups.writeups')) challenge = (db.session.query(Challenges).filter( Challenges.type != 'writeup').filter( Challenges.writeup_challenge == writeup.challenge).one_or_none()) if not challenge or not challenge.writeup_challenge: return redirect(url_for('writeups.writeups')) if (user.type == 'admin' or not challenge.writeup_challenge.solve_req or challenge.id in (s.challenge_id for s in user.team.solves) or writeup.user.id == user.id): content = cmarkgfm.github_flavored_markdown_to_html( writeup.provided, options=cmarkgfmOptions.CMARK_OPT_SAFE) if writeup.user.id == user.id or user.type == 'admin': editable = True else: error = { 'heading': '403', 'msg': 'Sorry, you must solve this challenge before viewing write-ups for it' } return render_template("view_writeup.html", challenge=challenge, content=content, error=error, user=writeup.user, editable=editable) @writeups_bp.route(f"{base_route}/<int:challenge_id>/edit", methods=["GET", "POST"]) @during_ctf_time_only @authed_only def edit_writeup(challenge_id: int): user = get_current_user() challenge = (db.session.query(Challenges).filter( Challenges.id == challenge_id).filter( Challenges.type != 'writeup').one_or_none()) if not challenge or not challenge.writeup_challenge: return redirect(url_for('writeups.writeups')) solves = [s.challenge_id for s in user.team.solves ] if user.team else [s.challenge_id for s in user.solves] if challenge.id not in solves: return render_template( "edit_writeup.html", challenge=challenge, error={ 'heading': '403', 'msg': 'Sorry, you must solve the challenge before submitting a write-up' }) writeup = (db.session.query(Submissions).filter( Submissions.challenge_id == challenge.writeup_challenge.id).filter( Submissions.user_id == user.id).one_or_none()) if not writeup: team_wu_solve = (db.session.query(Solves).filter( Solves.challenge_id == challenge.writeup_challenge.id).filter( Solves.team_id == user.team.id).one_or_none()) if team_wu_solve: writeup = Duplicate( challenge=challenge.writeup_challenge, user=user, team=user.team, ip=request.remote_addr, provided='', ) else: writeup = Solves( challenge=challenge.writeup_challenge, user=user, team=user.team, ip=request.remote_addr, provided='', ) db.session.add(writeup) db.session.flush() if request.method == 'POST': writeup.provided = request.form.to_dict().get('content', '') res = redirect( url_for('writeups.view_writeup', writeup_id=writeup.id)) db.session.commit() return res elif request.method == 'GET': return render_template("edit_writeup.html", challenge=challenge, writeup=writeup) # Add the Write-Ups page to pages so it appears in the nav bar if not db.session.query(Pages).filter( Pages.route == base_route).one_or_none(): with open(f"{plugin_dir}/assets/writeups_default.html", 'r') as fd: db.session.add( Pages(title='Write-Ups', route=base_route, content=fd.read(), draft=False, hidden=False, auth_required=True)) db.session.commit() return writeups_bp
def load(app): # register_plugin_assets_directory(app, base_path='/plugins/ctfd-shell-plugin/assets/') app.db.create_all() shellexists = Pages.query.filter_by(route='shell').first() if not shellexists: title = 'Shell' route = 'shell' html = """<style> #shell-container { width: calc(100vw - 20px); padding: 0 0 0 0; } #shell-help { text-align: center; height:75px; margin: 0 0 0 0; border-radius: 5px; } #shell { height: calc(100vh - 200px); width: 100%; } </style> <div id="shell-container" class="container shell-container"> <div id="shell-help" class="alert alert-info alert-dismissable"> <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a> <p>Use the username and password you registered with to log in.</p> <p>You may also log in over ssh on port 2222</p> </div> <div class> <iframe id="shell" src="https://192.168.1.1/shell/" id="gadget0" name="gadget0" frameborder="1"></iframe> </div> </div> """ page = Pages(title, route, html, draft=False, auth_required=True) db.session.add(page) db.session.commit() connection = pika.BlockingConnection( pika.ConnectionParameters('localhost')) channel = connection.channel() channel.queue_declare(queue='shell_queue', durable=True) def new_register(): logger = logging.getLogger('regs') if not utils.can_register(): return redirect(url_for('auth.login')) if request.method == 'POST': errors = [] name = request.form['name'] email = request.form['email'] password = request.form['password'] name_len = len(name) == 0 names = Teams.query.add_columns('name', 'id').filter_by(name=name).first() emails = Teams.query.add_columns( 'email', 'id').filter_by(email=email).first() pass_short = len(password) == 0 pass_long = len(password) > 128 valid_email = utils.check_email_format(request.form['email']) team_name_email_check = utils.check_email_format(name) if not valid_email: errors.append("Please enter a valid email address") if names: errors.append('That team name is already taken') if team_name_email_check is True: errors.append('Your team name cannot be an email address') if emails: errors.append('That email has already been used') if pass_short: errors.append('Pick a longer password') if pass_long: errors.append('Pick a shorter password') if name_len: errors.append('Pick a longer team name') if len(errors) > 0: return render_template('register.html', errors=errors, name=request.form['name'], email=request.form['email'], password=request.form['password']) else: with app.app_context(): team = Teams(name, email.lower(), password) db.session.add(team) db.session.commit() db.session.flush() message = json.dumps(["add", name, password]) channel.basic_publish( exchange='', routing_key='shell_queue', body=message, properties=pika.BasicProperties( delivery_mode=2, # make message persistent )) session['username'] = team.name session['id'] = team.id session['admin'] = team.admin session['nonce'] = utils.sha512(os.urandom(10)) if utils.can_send_mail() and utils.get_config( 'verify_emails' ): # Confirming users is enabled and we can send email. logger = logging.getLogger('regs') logger.warn( "[{date}] {ip} - {username} registered (UNCONFIRMED) with {email}" .format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=request.form['name'].encode('utf-8'), email=request.form['email'].encode('utf-8'))) utils.verify_email(team.email) db.session.close() return redirect(url_for('auth.confirm_user')) else: # Don't care about confirming users if utils.can_send_mail( ): # We want to notify the user that they have registered. utils.sendmail( request.form['email'], "You've successfully registered for {}".format( utils.get_config('ctf_name'))) logger.warn( "[{date}] {ip} - {username} registered with {email}".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=request.form['name'].encode('utf-8'), email=request.form['email'].encode('utf-8'))) db.session.close() return redirect(url_for('challenges.challenges_view')) else: return render_template('register.html') def new_profile(data=None): logger = logging.getLogger('logins') if data is not None: try: s = TimedSerializer(app.config['SECRET_KEY']) name = s.loads(utils.base64decode(data, urldecode=True), max_age=1800) except BadTimeSignature: return render_template('reset_password.html', errors=['Your link has expired']) except (BadSignature, TypeError, base64.binascii.Error): return render_template('reset_password.html', errors=['Your reset token is invalid']) if request.method == "GET": return render_template('reset_password.html', mode='set') if request.method == "POST": team = Teams.query.filter_by(name=name).first_or_404() team.password = bcrypt_sha256.encrypt( request.form['password'].strip()) db.session.commit() logger.warn( "[{date}] {ip} - successful password reset for {username}" .format(date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=team.name.encode('utf-8'))) password = request.form['password'].strip() if password: message = json.dumps(["change", name, password]) channel.basic_publish( exchange='', routing_key='shell_queue', body=message, properties=pika.BasicProperties( delivery_mode=2, # make message persistent )) db.session.close() return redirect(url_for('auth.login')) if request.method == 'POST': email = request.form['email'].strip() team = Teams.query.filter_by(email=email).first() errors = [] if utils.can_send_mail() is False: return render_template( 'reset_password.html', errors=[ 'Email could not be sent due to server misconfiguration' ]) if not team: return render_template( 'reset_password.html', errors=[ 'If that account exists you will receive an email, please check your inbox' ]) utils.forgot_password(email, team.name) return render_template( 'reset_password.html', errors=[ 'If that account exists you will receive an email, please check your inbox' ]) return render_template('reset_password.html') def new_reset_pass(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name').strip() email = request.form.get('email').strip() website = request.form.get('website').strip() affiliation = request.form.get('affiliation').strip() country = request.form.get('country').strip() user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = utils.check_email_format(email) if utils.check_email_format(name) is True: errors.append('Team name cannot be an email address') if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append( "Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if not utils.get_config( 'prevent_name_change' ) and names and name != session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if not utils.get_config('prevent_name_change') and name_len: errors.append('Pick a longer team name') if website.strip() and not utils.validate_url(website): errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if team.name != name: if not utils.get_config('prevent_name_change'): team.name = name session['username'] = team.name if team.email != email.lower(): team.email = email.lower() if utils.get_config('verify_emails'): team.verified = False if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) message = json.dumps(["change", name, password]) channel.basic_publish( exchange='', routing_key='shell_queue', body=message, properties=pika.BasicProperties( delivery_mode=2, # make message persistent )) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = utils.get_config('prevent_name_change') confirm_email = utils.get_config( 'verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login')) app.view_functions['auth.register'] = new_register app.view_functions['views.profile'] = new_profile app.view_functions['auth.reset_password'] = new_reset_pass
def import_ctf(backup, segments=None, erase=False): side_db = dataset.connect(get_config('SQLALCHEMY_DATABASE_URI')) if segments is None: segments = ['challenges', 'teams', 'both', 'metadata'] if not zipfile.is_zipfile(backup): raise TypeError backup = zipfile.ZipFile(backup) groups = { 'challenges': [ 'challenges', 'files', 'tags', 'keys', 'hints', ], 'teams': [ 'teams', 'tracking', 'awards', ], 'both': [ 'solves', 'wrong_keys', 'unlocks', ], 'metadata': [ 'alembic_version', 'config', 'pages', 'containers', ] } ## Need special handling of metadata if 'metadata' in segments: meta = groups['metadata'] segments.remove('metadata') meta.remove('alembic_version') for item in meta: table = side_db[item] path = "db/{}.json".format(item) data = backup.open(path).read() ## Some JSON files will be empty if data: if item == 'config': saved = json.loads(data) for entry in saved['results']: key = entry['key'] value = entry['value'] set_config(key, value) elif item == 'pages': saved = json.loads(data) for entry in saved['results']: route = entry['route'] html = entry['html'] page = Pages.query.filter_by(route=route).first() if page: page.html = html else: page = Pages(route, html) db.session.add(page) db.session.commit() elif item == 'containers': saved = json.loads(data) for entry in saved['results']: name = entry['name'] buildfile = entry['buildfile'] container = Containers.query.filter_by( name=name).first() if container: container.buildfile = buildfile else: container = Containers(name, buildfile) db.session.add(container) db.session.commit() for segment in segments: group = groups[segment] for item in group: table = side_db[item] path = "db/{}.json".format(item) data = backup.open(path).read() if data: saved = json.loads(data) for entry in saved['results']: entry_id = entry.pop('id', None) table.insert(entry) else: continue
def setup(): # with app.app_context(): # admin = Teams.query.filter_by(admin=True).first() if not is_setup(): if not session.get('nonce'): session['nonce'] = sha512(os.urandom(10)) if request.method == 'POST': ctf_name = request.form['ctf_name'] ctf_name = set_config('ctf_name', ctf_name) ## CSS css = set_config('start', '') ## Admin user name = request.form['name'] email = request.form['email'] password = request.form['password'] admin = Teams(name, email, password) admin.admin = True admin.banned = True ## Index page page = Pages('index', """<div class="container main-container"> <img class="logo" src="{0}/static/original/img/logo.png" /> <h3 class="text-center"> Welcome to a cool CTF competition organized by <a href="https://www.facebook.com/CLB/Tinhoc.TLU">TLIT Club</a> and info at <a href="http://thanglongit.me/d/87">thanglongit.me</a> </h3> <h4 class="text-center"> <a href="{0}/login">Click here</a> to login and play now! </h4> </div>""".format(request.script_root)) #max attempts per challenge max_tries = set_config("max_tries",0) ## Start time start = set_config('start', None) end = set_config('end', None) ## Challenges cannot be viewed by unregistered users view_challenges_unregistered = set_config('view_challenges_unregistered', None) ## Allow/Disallow registration prevent_registration = set_config('prevent_registration', None) ## Verify emails verify_emails = set_config('verify_emails', None) mail_server = set_config('mail_server', None) mail_port = set_config('mail_port', None) mail_tls = set_config('mail_tls', None) mail_ssl = set_config('mail_ssl', None) mail_username = set_config('mail_username', None) mail_password = set_config('mail_password', None) setup = set_config('setup', True) db.session.add(page) db.session.add(admin) db.session.commit() db.session.close() app.setup = False return redirect(url_for('views.static_html')) return render_template('setup.html', nonce=session.get('nonce')) return redirect(url_for('views.static_html'))