Пример #1
0
def challenges_view():
    errors = []
    start = get_config('start') or 0
    end = get_config('end') or 0
    if not is_admin():  # User is not an admin
        if not ctftime():
            # It is not CTF time
            if view_after_ctf(
            ):  # But we are allowed to view after the CTF ends
                pass
            else:  # We are NOT allowed to view after the CTF ends
                if get_config('start') and not ctf_started():
                    errors.append('{} has not started yet'.format(ctf_name()))
                if (get_config('end')
                        and ctf_ended()) and not view_after_ctf():
                    errors.append('{} has ended'.format(ctf_name()))
                return render_template('chals.html',
                                       errors=errors,
                                       start=int(start),
                                       end=int(end))
        if get_config('verify_emails'
                      ) and not is_verified():  # User is not confirmed
            return redirect(url_for('auth.confirm_user'))
    if user_can_view_challenges():  # Do we allow unauthenticated users?
        if get_config('start') and not ctf_started():
            errors.append('{} has not started yet'.format(ctf_name()))
        if (get_config('end') and ctf_ended()) and not view_after_ctf():
            errors.append('{} has ended'.format(ctf_name()))
        return render_template('chals.html',
                               errors=errors,
                               start=int(start),
                               end=int(end))
    else:
        return redirect(url_for('auth.login', next='challenges'))
Пример #2
0
def challenges_view():
    infos = []
    errors = []
    start = utils.get_config('start') or 0
    end = utils.get_config('end') or 0

    if utils.ctf_paused():
        infos.append('{} is paused'.format(utils.ctf_name()))

    if not utils.ctftime():
        # It is not CTF time
        if utils.view_after_ctf(
        ):  # But we are allowed to view after the CTF ends
            pass
        else:  # We are NOT allowed to view after the CTF ends
            if utils.get_config('start') and not utils.ctf_started():
                errors.append('{} has not started yet'.format(
                    utils.ctf_name()))
            if (utils.get_config('end')
                    and utils.ctf_ended()) and not utils.view_after_ctf():
                errors.append('{} has ended'.format(utils.ctf_name()))
            return render_template('challenges.html',
                                   infos=infos,
                                   errors=errors,
                                   start=int(start),
                                   end=int(end))

    return render_template('challenges.html',
                           infos=infos,
                           errors=errors,
                           start=int(start),
                           end=int(end))
Пример #3
0
def challenges_view():
    errors = []
    start = utils.get_config('start') or 0
    end = utils.get_config('end') or 0
    if not utils.is_admin():  # User is not an admin
        if not utils.ctftime():
            # It is not CTF time
            if utils.view_after_ctf():  # But we are allowed to view after the CTF ends
                pass
            else:  # We are NOT allowed to view after the CTF ends
                if utils.get_config('start') and not utils.ctf_started():
                    errors.append('{} has not started yet'.format(utils.ctf_name()))
                if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf():
                    errors.append('{} has ended'.format(utils.ctf_name()))
                return render_template('chals.html', errors=errors, start=int(start), end=int(end))
        if utils.get_config('verify_emails') and not utils.is_verified():  # User is not confirmed
            return redirect(url_for('auth.confirm_user'))
    if utils.user_can_view_challenges():  # Do we allow unauthenticated users?
        if utils.get_config('start') and not utils.ctf_started():
            errors.append('{} has not started yet'.format(utils.ctf_name()))
        if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf():
            errors.append('{} has ended'.format(utils.ctf_name()))
        return render_template('chals.html', errors=errors, start=int(start), end=int(end))
    else:
        return redirect(url_for('auth.login', next='challenges'))
Пример #4
0
def team(teamid):
    if utils.get_config('workshop_mode'):
        abort(404)

    if utils.get_config('view_scoreboard_if_utils.authed') and not utils.authed():
        return redirect(url_for('auth.login', next=request.path))
    infos = []
    errors = []

    if utils.ctf_paused():
        infos.append('{} is paused'.format(utils.ctf_name()))

    if not utils.ctftime():
        # It is not CTF time
        if utils.view_after_ctf():  # But we are allowed to view after the CTF ends
            pass
        else:  # We are NOT allowed to view after the CTF ends
            if utils.get_config('start') and not utils.ctf_started():
                errors.append('{} has not started yet'.format(utils.ctf_name()))
            if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf():
                errors.append('{} has ended'.format(utils.ctf_name()))
    
    freeze = utils.get_config('freeze')
    user = Teams.query.filter_by(id=teamid).first_or_404()
    solves = Solves.query.filter_by(teamid=teamid)
    awards = Awards.query.filter_by(teamid=teamid)

    place = user.place()
    score = user.score()

    if freeze:
        freeze = utils.unix_time_to_utc(freeze)
        if teamid != session.get('id'):
            solves = solves.filter(Solves.date < freeze)
            awards = awards.filter(Awards.date < freeze)

    solves = solves.all()
    awards = awards.all()

    db.session.close()

    if utils.hide_scores() and teamid != session.get('id'):
        errors.append('Scores are currently hidden')
    else:
        # banned is a synonym for hidden :/
        if not utils.is_admin() and (user.admin or user.banned):
            errors.append('Scores are currently hidden')

    if errors:
        return render_template('team.html', team=user, infos=infos, errors=errors)

    if request.method == 'GET':
        return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen(), infos=infos)
    elif request.method == 'POST':
        json = {'solves': []}
        for x in solves:
            json['solves'].append({'id': x.id, 'chal': x.chalid, 'team': x.teamid})
        return jsonify(json)
Пример #5
0
    def during_ctf_time_only_wrapper(*args, **kwargs):
        if utils.ctftime() or utils.is_admin():
            return f(*args, **kwargs)
        else:
            if utils.ctf_ended():
                if utils.view_after_ctf():
                    return f(*args, **kwargs)
                else:
                    error = '{} has ended'.format(utils.ctf_name())
                    abort(403, description=error)

            if utils.ctf_started() is False:
                error = '{} has not started yet'.format(utils.ctf_name())
                abort(403, description=error)
Пример #6
0
def challenges_view():
    infos = []
    errors = []
    start = utils.get_config('start') or 0
    end = utils.get_config('end') or 0
    if utils.ctf_paused():
        infos.append(get_tip('IS_PAUSED').format(utils.ctf_name()))
    if not utils.is_admin():  # User is not an admin
        if not utils.ctftime():
            # It is not CTF time
            if utils.view_after_ctf(
            ):  # But we are allowed to view after the CTF ends
                pass
            else:  # We are NOT allowed to view after the CTF ends
                if utils.get_config('start') and not utils.ctf_started():
                    errors.append(
                        get_tip('NOT_START').format(utils.ctf_name()))
                if (utils.get_config('end')
                        and utils.ctf_ended()) and not utils.view_after_ctf():
                    errors.append(get_tip('HAS_END').format(utils.ctf_name()))
                return render_template('challenges.html',
                                       infos=infos,
                                       errors=errors,
                                       start=int(start),
                                       end=int(end))

    if utils.get_config('verify_emails'):
        if utils.authed():
            if utils.is_admin() is False and utils.is_verified(
            ) is False:  # User is not confirmed
                return redirect(url_for('auth.confirm_user'))

    if utils.user_can_view_challenges():  # Do we allow unauthenticated users?
        if utils.get_config('start') and not utils.ctf_started():
            errors.append(get_tip('NOT_START').format(utils.ctf_name()))
        if (utils.get_config('end')
                and utils.ctf_ended()) and not utils.view_after_ctf():
            errors.append(get_tip('HAS_END').format(utils.ctf_name()))
        return render_template('challenges.html',
                               infos=infos,
                               errors=errors,
                               start=int(start),
                               end=int(end))
    else:
        return redirect(url_for('auth.login', next='challenges'))
Пример #7
0
def admin_export_ctf():
    segments = request.args.get('segments')
    if segments:
        backup = export_ctf(segments.split(','))
    else:
        backup = export_ctf()
    ctf_name = utils.ctf_name()
    day = datetime.datetime.now().strftime("%Y-%m-%d")
    full_name = "{}.{}.zip".format(ctf_name, day)
    return send_file(backup, as_attachment=True, attachment_filename=full_name)
Пример #8
0
def admin_export_ctf():
    segments = request.args.get('segments')
    if segments:
        backup = export_ctf(segments.split(','))
    else:
        backup = export_ctf()
    ctf_name = utils.ctf_name()
    day = datetime.datetime.now().strftime("%Y-%m-%d")
    full_name = "{}.{}.zip".format(ctf_name, day)
    return send_file(backup, as_attachment=True, attachment_filename=full_name)
Пример #9
0
def scoreboard_view():
    errors = []
    if get_config('view_scoreboard_if_authed') and not authed():
        return redirect(url_for('auth.login', next=request.path))
    if (get_config('start') > time.time()):
        errors.append(
            '{} scoreboard will be posted once the competition starts'.format(
                ctf_name()))
        return render_template('scoreboard.html', errors=errors, teams="")
    standings = get_standings()
    return render_template('scoreboard.html', teams=standings)
Пример #10
0
def challenges_view():
    errors = []
    start = get_config('start') or 0
    end = get_config('end') or 0
    if not is_admin():  # User is not an admin
        if not ctftime():
            # It is not CTF time
            if start > time.time(
            ):  # We are NOT allowed to view after the CTF ends
                errors.append('{} challenges will be posted soon!'.format(
                    ctf_name()))
            elif not view_after_ctf():
                errors.append('{} has ended.'.format(ctf_name()))
            return render_template('chals.html',
                                   errors=errors,
                                   start=int(start),
                                   end=int(end))

        if get_config('verify_emails'
                      ) and not is_verified():  # User is not confirmed
            return redirect(url_for('auth.confirm_user'))
    if user_can_view_challenges():  # Do we allow unauthenticated users?
        if get_config('start') and not ctf_started():
            errors.append('{} has not started yet'.format(ctf_name()))
        if (get_config('end') and ctf_ended()) and not view_after_ctf():
            errors.append('{} has ended'.format(ctf_name()))
        if not is_on_team():
            errors.append('You are not on a team!')
        return render_template('chals.html',
                               errors=errors,
                               start=int(start),
                               end=int(end))
    else:
        if not is_on_team():
            errors.append(
                'You must create or join a team before you can start playing')
            return render_template('chals.html',
                                   errors=errors,
                                   start=int(start),
                                   end=int(end))
        return redirect(url_for('auth.login', next='challenges'))
Пример #11
0
def chals():
    if not utils.is_admin():
        if not utils.ctftime():
            if utils.view_after_ctf():
                pass
            elif utils.ctf_paused():
                abort(make_response('{} paused'.format(utils.ctf_name()), 503))
            else:
                abort(
                    make_response(
                        'These are not the challenges you are looking for',
                        403))

    if utils.get_config('verify_emails'):
        if utils.authed():
            if utils.is_admin() is False and utils.is_verified(
            ) is False:  # User is not confirmed
                abort(403)

    if utils.user_can_view_challenges() and (utils.ctf_started()
                                             or utils.is_admin()):
        teamid = session.get('id')
        chals = Challenges.query.filter(
            or_(Challenges.hidden != True,
                Challenges.hidden == None)).order_by(Challenges.value).all()
        json = {'game': []}
        for x in chals:
            tags = [
                tag.tag for tag in Tags.query.add_columns('tag').filter_by(
                    chal=x.id).all()
            ]
            files = [
                str(f.location)
                for f in Files.query.filter_by(chal=x.id).all()
            ]
            unlocked_hints = set([
                u.itemid
                for u in Unlocks.query.filter_by(model='hints', teamid=teamid)
            ])
            hints = []
            for hint in Hints.query.filter_by(chal=x.id).all():
                if hint.id in unlocked_hints or utils.ctf_ended():
                    hints.append({
                        'id': hint.id,
                        'cost': hint.cost,
                        'hint': hint.hint
                    })
                else:
                    hints.append({'id': hint.id, 'cost': hint.cost})
            chal_type = get_chal_class(x.type)
            json['game'].append({
                'id': x.id,
                'type': chal_type.name,
                'name': x.name,
                'value': x.value,
                'description': x.description,
                'category': x.category,
                'files': files,
                'tags': tags,
                'hints': hints,
                'template': chal_type.templates['modal'],
                'script': chal_type.scripts['modal'],
            })

        db.session.close()
        return jsonify(json)
    else:
        db.session.close()
        abort(403)
Пример #12
0
    def anonchal():
        if utils.ctf_paused():
            return jsonify({
                'status': 3,
                'message': '{} is paused'.format(utils.ctf_name())
            })

        if utils.is_admin() or (utils.authed() and utils.is_verified() and
                                (utils.ctf_started()
                                 or utils.view_after_ctf())):

            team = Teams.query.filter_by(id=session['id']).first()
            provided_key = request.form['key'].strip()
            logger = logging.getLogger('keys')
            data = (time.strftime("%m/%d/%Y %X"),
                    session['username'].encode('utf-8'),
                    provided_key.encode('utf-8'), utils.get_kpm(session['id']))

            # Anti-bruteforce / KPM is based on last failed key (not logged), so sleep instead.
            time.sleep(2)

            # Find challenge by looking up the provided flag
            key = db.session.query(Keys).\
                join(AnonymousChallenge).\
                filter(Keys.flag == provided_key).first()

            if not key:
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(
                        *data))
                return jsonify({'status': 0, 'message': 'Invalid Flag'})

            chal = AnonymousChallenge.query.filter_by(id=key.chal).first()

            chal_class = get_chal_class(chal.type)
            solves = Solves.query.filter_by(teamid=session['id'],
                                            chalid=chal.id).first()

            # If team hasn't solved challenge yet, save the solve
            if not solves:
                # We already know the flag is correct because we checked it already
                chal_class.solve(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': 1, 'message': "Correct"})

            # Otherwise, raise an error
            else:
                logger.info(
                    "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                        *data))
                return jsonify({
                    'status': 2,
                    'message': 'You already solved this'
                })
        else:
            return jsonify({
                'status':
                -1,
                'message':
                "You must be logged in to solve a challenge"
            })
Пример #13
0
def chal(chalid):
    if utils.ctf_paused():
        return jsonify({
            'status': 3,
            'message': '{} is paused'.format(utils.ctf_name())
        })
    if (utils.authed() and utils.is_verified() and
        (utils.ctf_started() or utils.view_after_ctf())) or utils.is_admin():
        team = Teams.query.filter_by(id=session['id']).first()
        fails = WrongKeys.query.filter_by(teamid=session['id'],
                                          chalid=chalid).count()
        logger = logging.getLogger('keys')
        data = (time.strftime("%m/%d/%Y %X"),
                session['username'].encode('utf-8'),
                request.form['key'].encode('utf-8'),
                utils.get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        chal = Challenges.query.filter_by(id=chalid).first_or_404()
        if chal.hidden:
            abort(404)
        chal_class = get_chal_class(chal.type)

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                chal_class.fail(team=team, chal=chal, request=request)
            logger.warn(
                "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(
                    *data))
            # return '3' # Submitting too fast
            return jsonify({
                'status':
                3,
                'message':
                "You're submitting keys too fast. Slow down."
            })

        solves = Solves.query.filter_by(teamid=session['id'],
                                        chalid=chalid).first()

        # Challange not solved yet
        if not solves:
            provided_key = request.form['key'].strip()
            saved_keys = Keys.query.filter_by(chal=chal.id).all()

            # Hit max attempts
            max_tries = chal.max_attempts
            if max_tries and fails >= max_tries > 0:
                return jsonify({
                    'status': 0,
                    'message': "You have 0 tries remaining"
                })

            status, message = chal_class.attempt(chal, request)
            if status:  # The challenge plugin says the input is right
                if utils.ctftime() or utils.is_admin():
                    chal_class.solve(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': 1, 'message': message})
            else:  # The challenge plugin says the input is wrong
                if utils.ctftime() or utils.is_admin():
                    chal_class.fail(team=team, chal=chal, request=request)
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(
                        *data))
                # return '0' # key was wrong
                if max_tries:
                    attempts_left = max_tries - fails - 1  # Off by one since fails has changed since it was gotten
                    tries_str = 'tries'
                    if attempts_left == 1:
                        tries_str = 'try'
                    if message[
                            -1] not in '!().;?[]\{\}':  # Add a punctuation mark if there isn't one
                        message = message + '.'
                    return jsonify({
                        'status':
                        0,
                        'message':
                        '{} You have {} {} remaining.'.format(
                            message, attempts_left, tries_str)
                    })
                else:
                    return jsonify({'status': 0, 'message': message})

        # Challenge already solved
        else:
            logger.info(
                "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(
                    *data))
            # return '2' # challenge was already solved
            return jsonify({'status': 2, 'message': 'You already solved this'})
    else:
        return jsonify({
            'status': -1,
            'message': "You must be logged in to solve a challenge"
        })
Пример #14
0
def challenges_view(compid):
    infos = []
    errors = []
    start = utils.get_config('start') or 0
    end = utils.get_config('end') or 0
    comp = Competitions.query.filter(Competitions.id == compid).first()

    if utils.ctf_paused():
        infos.append('{} is paused'.format(utils.ctf_name()))
    if not utils.is_admin():  # User is not an admin
        if not utils.ctftime():
            # It is not CTF time
            if utils.view_after_ctf(
            ):  # But we are allowed to view after the CTF ends
                pass
            else:  # We are NOT allowed to view after the CTF ends
                if utils.get_config('start') and not utils.ctf_started():
                    errors.append('{} has not started yet'.format(
                        utils.ctf_name()))
                if (utils.get_config('end')
                        and utils.ctf_ended()) and not utils.view_after_ctf():
                    errors.append('{} has ended'.format(utils.ctf_name()))
                if comp is None:
                    errors.append('no such competition')
                    start = False
                if comp.startTime > datetime.datetime.utcnow():
                    errors = append('{} 尚未开始,敬请期待'.format(comp.title))
                    start = False
                return render_template('comp_challenges.html',
                                       infos=infos,
                                       errors=errors,
                                       start=int(start),
                                       end=int(end),
                                       comp=comp)

    if utils.get_config('verify_emails'):
        if utils.authed():
            if utils.is_admin() is False and utils.is_verified(
            ) is False:  # User is not confirmed
                return redirect(url_for('auth.confirm_user'))

    if utils.user_can_view_challenges():  # Do we allow unauthenticated users?
        if utils.get_config('start') and not utils.ctf_started():
            errors.append('{} has not started yet'.format(utils.ctf_name()))
        if (utils.get_config('end')
                and utils.ctf_ended()) and not utils.view_after_ctf():
            errors.append('{} has ended'.format(utils.ctf_name()))
        if comp is None:
            errors.append('no such competition')
            start = False
        if comp.startTime > datetime.datetime.utcnow():
            errors.append('{} 尚未开始,敬请期待'.format(comp.title))
            start = False
        return render_template('comp_challenges.html',
                               infos=infos,
                               errors=errors,
                               start=int(start),
                               end=int(end),
                               comp=comp)
    else:
        return redirect(url_for('auth.login', next=request.path))
Пример #15
0
from CTFd import create_app
from CTFd.utils import ctf_name, export_ctf

import datetime
import sys
import shutil
import zipfile


app = create_app()
with app.app_context():
    backup = export_ctf()

    if len(sys.argv) > 1:
        with open(sys.argv[1], 'wb') as target:
            shutil.copyfileobj(backup, target)
    else:
        ctf_name = ctf_name()
        day = datetime.datetime.now().strftime("%Y-%m-%d")
        full_name = "{}.{}.zip".format(ctf_name, day)

        with open(full_name, 'wb') as target:
            shutil.copyfileobj(backup, target)
Пример #16
0
 def export_csv():
     output = get_invited_teams_csv()
     ctf_name = utils.ctf_name()
     full_name = '{}-invited-teams.csv'.format(ctf_name)
     return send_file(output, as_attachment=True,
                      attachment_filename=full_name)
Пример #17
0
from CTFd import create_app
from CTFd.utils import ctf_name, export_ctf

import datetime
import sys
import shutil
import zipfile

app = create_app()
with app.app_context():
    backup = export_ctf()

    if len(sys.argv) > 1:
        with open(sys.argv[1], 'wb') as target:
            shutil.copyfileobj(backup, target)
    else:
        ctf_name = ctf_name()
        day = datetime.datetime.now().strftime("%Y-%m-%d")
        full_name = "{}.{}.zip".format(ctf_name, day)

        with open(full_name, 'wb') as target:
            shutil.copyfileobj(backup, target)