Пример #1
0
def confirm_user(data=None):
    if not utils.get_config('verify_emails'):
        # If the CTF doesn't care about confirming email addresses then redierct to challenges
        return redirect(url_for('challenges.challenges_view'))

    logger = logging.getLogger('regs')
    # User is confirming email account
    if data and request.method == "GET":
        try:
            s = TimedSerializer(app.config['SECRET_KEY'])
            email = s.loads(utils.base64decode(data, urldecode=True),
                            max_age=1800)
        except BadTimeSignature:
            return render_template('confirm.html',
                                   errors=[get_tip('LINK_EXPIRED')])
        except (BadSignature, TypeError, base64.binascii.Error):
            return render_template('confirm.html',
                                   errors=[get_tip('INVIDE_RESET_TOKEN')])
        team = Teams.query.filter_by(email=email).first_or_404()
        team.verified = True
        db.session.commit()
        logger.warn(
            get_tip('USER_HAVE_CM').format(date=time.strftime("%m/%d/%Y %X"),
                                           ip=utils.get_ip(),
                                           username=team.name.encode('utf-8'),
                                           email=team.email.encode('utf-8')))
        db.session.close()
        if utils.authed():
            return redirect(url_for('challenges.challenges_view'))
        return redirect(url_for('auth.login'))

    # User is trying to start or restart the confirmation flow
    if not utils.authed():
        return redirect(url_for('auth.login'))

    team = Teams.query.filter_by(id=session['id']).first_or_404()

    if data is None:
        if request.method == "POST":
            # User wants to resend their confirmation email
            if team.verified:
                return redirect(url_for('views.profile'))
            else:
                utils.verify_email(team.email)
                logger.warn(
                    get_tip('EMAIL_CF_RESENT').format(
                        date=time.strftime("%m/%d/%Y %X"),
                        ip=utils.get_ip(),
                        username=team.name.encode('utf-8'),
                        email=team.email.encode('utf-8')))
            return render_template('confirm.html',
                                   team=team,
                                   infos=[get_tip('EMAIL_CF_SENT')])
        elif request.method == "GET":
            # User has been directed to the confirm page
            team = Teams.query.filter_by(id=session['id']).first_or_404()
            if team.verified:
                # If user is already verified, redirect to their profile
                return redirect(url_for('views.profile'))
            return render_template('confirm.html', team=team)
Пример #2
0
def login():
    logger = logging.getLogger('logins')
    if request.method == 'POST':
        errors = []
        name = request.form['name']

        # Check if the user submitted an email address or a team name
        if utils.check_email_format(name) is True:
            team = Teams.query.filter_by(email=name).first()
        elif utils.check_sno_format(name) is True:
            team = Teams.query.filter_by(sno=name).first()
        else:
            team = Teams.query.filter_by(name=name).first()

        if team:
            if team and bcrypt_sha256.verify(request.form['password'],
                                             team.password):
                try:
                    session.regenerate()  # NO SESSION FIXATION FOR YOU
                except:
                    pass  # TODO: Some session objects don't implement regenerate :(
                session['username'] = team.name
                session['id'] = team.id
                session['admin'] = team.admin
                session['nonce'] = utils.sha512(os.urandom(10))
                db.session.close()

                logger.warn("[{date}] {ip} - {username} logged in".format(
                    date=time.strftime("%m/%d/%Y %X"),
                    ip=utils.get_ip(),
                    username=session['username'].encode('utf-8')))

                if request.args.get('next') and utils.is_safe_url(
                        request.args.get('next')):
                    return redirect(request.args.get('next'))
                return redirect(url_for('challenges.challenges_view'))

            else:  # This user exists but the password is wrong
                logger.warn(
                    "[{date}] {ip} - submitted invalid password for {username}"
                    .format(date=time.strftime("%m/%d/%Y %X"),
                            ip=utils.get_ip(),
                            username=team.name.encode('utf-8')))
                errors.append("Your username or password is incorrect")
                db.session.close()
                return render_template('login.html', errors=errors)

        else:  # This user just doesn't exist
            logger.warn(
                "[{date}] {ip} - submitted invalid account information".format(
                    date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip()))
            errors.append("Your username or password is incorrect")
            db.session.close()
            return render_template('login.html', errors=errors)

    else:
        db.session.close()
        return render_template('login.html')
Пример #3
0
def confirm_user(data=None):
    if not utils.get_config('verify_emails'):
        # If the CTF doesn't care about confirming email addresses then redierct to challenges
        return redirect(url_for('challenges.challenges_view'))

    logger = logging.getLogger('regs')
    # User is confirming email account
    if data and request.method == "GET":
        try:
            s = TimedSerializer(app.config['SECRET_KEY'])
            email = s.loads(utils.base64decode(data, urldecode=True), max_age=1800)
        except BadTimeSignature:
            return render_template('confirm.html', errors=['Your confirmation link has expired'])
        except BadSignature:
            return render_template('confirm.html', errors=['Your confirmation link seems wrong'])
        team = Teams.query.filter_by(email=email).first_or_404()
        team.verified = True
        db.session.commit()
        logger.warn("[{date}] {ip} - {username} confirmed their account".format(
            date=time.strftime("%m/%d/%Y %X"),
            ip=utils.get_ip(),
            username=team.name.encode('utf-8'),
            email=team.email.encode('utf-8')
        ))
        db.session.close()
        if utils.authed():
            return redirect(url_for('challenges.challenges_view'))
        return redirect(url_for('auth.login'))

    # User is trying to start or restart the confirmation flow
    if not utils.authed():
        return redirect(url_for('auth.login'))

    team = Teams.query.filter_by(id=session['id']).first_or_404()

    if data is None:
        if request.method == "POST":
            # User wants to resend their confirmation email
            if team.verified:
                return redirect(url_for('views.profile'))
            else:
                utils.verify_email(team.email)
                logger.warn("[{date}] {ip} - {username} initiated a confirmation email resend".format(
                    date=time.strftime("%m/%d/%Y %X"),
                    ip=utils.get_ip(),
                    username=team.name.encode('utf-8'),
                    email=team.email.encode('utf-8')
                ))
            return render_template('confirm.html', team=team, infos=['Your confirmation email has been resent!'])
        elif request.method == "GET":
            # User has been directed to the confirm page
            team = Teams.query.filter_by(id=session['id']).first_or_404()
            if team.verified:
                # If user is already verified, redirect to their profile
                return redirect(url_for('views.profile'))
            return render_template('confirm.html', team=team)
Пример #4
0
 def penalty(team1, team2, chal, request):
     provided_key = request.form['key'].strip()
     cp1 = CheatPenalty(teamid=team1.id, chalid=chal.id, ip=utils.get_ip(request), flag=provided_key, penalty=chal.penalty)
     cp2 = CheatPenalty(teamid=team2.id, chalid=chal.id, ip=utils.get_ip(request), flag=provided_key, penalty=chal.penalty)
     award1 = Awards(teamid=team1.id, name=text_type('Cheating Penalty for {}'.format(chal.name)), value=(-chal.penalty))
     award2 = Awards(teamid=team2.id, name=text_type('Cheating Penalty for {}'.format(chal.name)), value=(-chal.penalty))  
     db.session.add(award1)
     db.session.add(award2)
     db.session.add(cp1)
     db.session.add(cp2)
     db.session.commit()
     db.session.close()
Пример #5
0
    def solve(team, chal, request):
        """
        This method is used to insert Solves into the database in order to mark a challenge as solved.
        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        teamid = Teams.query.filter_by(id=session['id']).first().id
        chalid = request.path.split('/')[-1]
        provided_key = request.form['key'].strip()
        db.session.expunge_all()
        partial = Partialsolve.query.filter_by(teamid=teamid,
                                               chalid=chalid).first()
        keys = json.loads(partial.flags)

        for key, solved in keys.iteritems():
            if not solved:
                return

        db.session.expunge_all()
        solve = Solves(teamid=teamid,
                       chalid=chalid,
                       ip=utils.get_ip(req=request),
                       flag=provided_key)
        db.session.add(solve)
        db.session.commit()
        db.session.close()
Пример #6
0
def reset_password(data=None):
    if utils.get_config('no_emails'):
        return redirect(url_for('auth.login'))
    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')))
            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')
Пример #7
0
    def solve(team, chal, request):
        """
        This method is used to insert Solves into the database in order to mark a challenge as solved.
        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        team_id = Teams.query.filter_by(id=session['id']).first().id
        chal_id = request.path.split('/')[-1]
        try:
            chal_id = int(chal_id)
        except ValueError:
            return

        provided_key = request.form['key'].strip()
        db.session.expunge_all()

        interm_award_handler = IntermediateAwardHandler(chal_id, team_id)
        if not interm_award_handler.is_chal_solved():
            return

        db.session.expunge_all()
        # REC FUTURE : La valeur "provided_key" n'est pas très significative. C'est le dernier flag intermédiaire obtenu pour valider le challenge.
        # Osef, un petit peu. Faudrait trouver le moyen de les stocker tous.
        solve = Solves(teamid=team_id,
                       chalid=chal_id,
                       ip=utils.get_ip(req=request),
                       flag=provided_key)
        db.session.add(solve)
        db.session.commit()
        interm_award_handler.nullify_scores()
        db.session.close()
Пример #8
0
    def solve(team, chal, request):
        """
        This method is used to insert Solves into the database in order to mark a challenge as solved.
        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        chal = CommunityChallengeModel.query.filter_by(id=chal.id).first()
        solve_count = Solves.query.join(Teams,
                                        Solves.teamid == Teams.id).filter(
                                            Solves.chalid == chal.id,
                                            Teams.banned == False).count()

        # if this is the first validation, we give the bonus points to the chal's owner
        if solve_count == 0:
            award = Awards(
                teamid=chal.owner,
                name=text_type(
                    'Bonus points for submitting challenge {}'.format(
                        chal.name)),
                value=chal.value)
            db.session.add(award)

        provided_key = request.form['key'].strip()
        solve = Solves(teamid=team.id,
                       chalid=chal.id,
                       ip=utils.get_ip(req=request),
                       flag=provided_key)
        db.session.add(solve)
        db.session.commit()
        db.session.close()
Пример #9
0
    def solve(team, chal, request):
        """
        This method is used to insert Solves into the database in order to mark a challenge as solved.

        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        chal = FirstBloodChallenges.query.filter_by(id=chal.id).first()

        solve_count = Solves.query.join(Teams,
                                        Solves.teamid == Teams.id).filter(
                                            Solves.chalid == chal.id,
                                            Teams.banned == False).count()

        if solve_count == 0:
            name = 'First Blood ({})'.format(chal.name)
            db.session.add(Awards(team.id, name, chal.bonus))

        provided_key = request.form['key'].strip()
        solve = Solves(teamid=team.id,
                       chalid=chal.id,
                       ip=utils.get_ip(req=request),
                       flag=provided_key)
        db.session.add(solve)

        db.session.commit()
        db.session.close()
Пример #10
0
    def solve(team, chal, request):
        """
        This method is used to insert Solves into the database in order to mark a challenge as solved.

        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        chal = DynamicChallenge.query.filter_by(id=chal.id).first()

        solve_count = Solves.query.join(Teams,
                                        Solves.teamid == Teams.id).filter(
                                            Solves.chalid == chal.id,
                                            Teams.banned == False).count()

        value = (((chal.minimum - chal.initial) / (chal.decay**2)) *
                 (solve_count**2)) + chal.initial
        value = math.ceil(value)

        if value < chal.minimum:
            value = chal.minimum

        chal.value = value

        provided_key = request.form['key'].strip()
        solve = Solves(teamid=team.id,
                       chalid=chal.id,
                       ip=utils.get_ip(req=request),
                       flag=provided_key)
        db.session.add(solve)

        db.session.commit()
        db.session.close()
 def solve(team, chal, request):
     provided_key = request.form['key'].strip()
     solve = Solves(teamid=team.id,
                    chalid=chal.id,
                    ip=utils.get_ip(req=request),
                    flag=provided_key)
     db.session.add(solve)
     db.session.commit()
     db.session.close()
 def fail(team, chal, request):
     provided_key = request.form['key'].strip()
     wrong = WrongKeys(teamid=team.id,
                       chalid=chal.id,
                       ip=utils.get_ip(request),
                       flag=provided_key)
     db.session.add(wrong)
     db.session.commit()
     db.session.close()
def reset_password(data=None):
    logger = logging.getLogger('logins')
    if data is not None and request.method == "GET":
        return render_template('reset_password.html', mode='set')
    if data is not None and request.method == "POST":
        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:
            return render_template(
                'reset_password.html',
                errors=['Your link appears broken, please try again.'])
        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')))
        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()
        if not team:
            return render_template(
                'reset_password.html',
                errors=[
                    'If that account exists you will receive an email, please check your inbox'
                ])
        s = TimedSerializer(app.config['SECRET_KEY'])
        token = s.dumps(team.name)
        text = """
Did you initiate a password reset?

{0}/{1}

""".format(url_for('auth.reset_password', _external=True),
           utils.base64encode(token, urlencode=True))

        utils.sendmail(email, text)

        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')
Пример #14
0
    def attempt(chal, request):
        """
        This method is used to check whether a given input is right or wrong. It does not make any changes and should
        return a boolean for correctness and a string to be shown to the user. It is also in charge of parsing the
        user's input from the request itself.

        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return: (boolean, string)
        """
        provided_key = request.form['key'].strip()
        chal_keys = Keys.query.filter_by(chal=chal.id).all()
        for chal_key in chal_keys:
            if get_key_class(chal_key.type).compare(chal_key.flag, provided_key):
                if chal_key.type == "correct":
                    solves = Awards.query.filter_by(teamid=session['id'], name=chal.id,
                                                    description=request.form['key'].strip()).first()
                    try:
                        flag_value = solves.description
                    except AttributeError:
                        flag_value = ""
                    # Challenge not solved yet
                    if provided_key != flag_value or not solves:
                        solve = Awards(teamid=session['id'], name=chal.id, value=chal.value)
                        solve.description = provided_key
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                    return True, 'Correct'
                    # TODO Add description function call to the end of "Correct" in return
                elif chal_key.type == "wrong":
                    solves = Awards.query.filter_by(teamid=session['id'], name=chal.id,
                                                    description=request.form['key'].strip()).first()
                    try:
                        flag_value = solves.description
                    except AttributeError:
                        flag_value = ""
                    # Challenge not solved yet
                    if provided_key != flag_value or not solves:
                        wrong_value = 0
                        wrong_value -= chal.value
                        wrong = WrongKeys(teamid=session['id'], chalid=chal.id, ip=utils.get_ip(request),
                                          flag=provided_key)
                        solve = Awards(teamid=session['id'], name=chal.id, value=wrong_value)
                        solve.description = provided_key
                        db.session.add(wrong)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                    return False, 'Error'
                    # TODO Add description function call to the end of "Error" in return
        return False, 'Incorrect'
Пример #15
0
    def fail(team, chal, request):
        """
        This method is used to insert WrongKeys into the database in order to mark an answer incorrect.

        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        provided_key = request.form['key'].strip()
        wrong = WrongKeys(teamid=team.id, chalid=chal.id, ip=utils.get_ip(request), flag=provided_key)
        db.session.add(wrong)
        db.session.commit()
        db.session.close()
Пример #16
0
    def solve(team, chal, request):
        """
        This method is used to insert Solves into the database in order to mark a challenge as solved.

        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        provided_key = request.form['key'].strip()
        solve = Solves(teamid=team.id, chalid=chal.id, ip=utils.get_ip(req=request), flag=provided_key)
        db.session.add(solve)
        db.session.commit()
        db.session.close()
Пример #17
0
def reset_password(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=[get_tip('LINK_EXPIRED')])
        except (BadSignature, TypeError, base64.binascii.Error):
            return render_template('reset_password.html',
                                   errors=[get_tip('INVIDE_RESET_TOKEN')])

        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(
                get_tip('PASS_HAVE_RESET').format(
                    date=time.strftime("%m/%d/%Y %X"),
                    ip=utils.get_ip(),
                    username=team.name.encode('utf-8')))
            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=[get_tip('EMAIL_NOT_CONFIG')])

        if not team:
            return render_template('reset_password.html',
                                   errors=[get_tip('FORGOT_PASS_NOTICE')])

        utils.forgot_password(email, team.name)

        return render_template('reset_password.html',
                               errors=[get_tip('FORGOT_PASS_NOTICE')])
    return render_template('reset_password.html')
Пример #18
0
def reset_password(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=['您的密码重置链接已经过期'])
        except (BadSignature, TypeError, base64.binascii.Error):
            return render_template('reset_password.html',
                                   errors=['您的密码重置令牌已经失效'])

        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')))
            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=['邮件信息配置异常,无法发送邮件,请联系管理员'])

        if not team:
            return render_template('reset_password.html',
                                   errors=['如果邮箱有效,将会收到一封密码重置邮件,请注意查收'])

        utils.forgot_password(email, team.name)

        return render_template('reset_password.html',
                               errors=['如果邮箱有效,将会收到一封密码重置邮件,请注意查收'])
    return render_template('reset_password.html')
Пример #19
0
def 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']
        password = request.form['password']

        name_len = len(name) == 0
        names = Teams.query.add_columns('name',
                                        'id').filter_by(name=name).first()
        pass_short = len(password) == 0
        pass_long = len(password) > 128

        if names:
            errors.append('That team name is already taken')
        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'],
                                   password=request.form['password'])
        else:
            with app.app_context():
                team = Teams(name, password)
                db.session.add(team)
                db.session.commit()
                db.session.flush()

                session['username'] = team.name
                session['id'] = team.id
                session['admin'] = team.admin
                session['nonce'] = utils.sha512(os.urandom(10))

        logger.warn("[{date}] {ip} - {username} registered".format(
            date=time.strftime("%m/%d/%Y %X"),
            ip=utils.get_ip(),
            username=request.form['name'].encode('utf-8')))
        db.session.close()
        return redirect(url_for('challenges.challenges_view'))
    else:
        return render_template('register.html')
Пример #20
0
    def attempt(chal, request):
        """
        This method is used to check whether a given input is right or wrong. It does not make any changes and should
        return a boolean for correctness and a string to be shown to the user. It is also in charge of parsing the
        user's input from the request itself.
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return: (boolean, string)
        """

        provided_key = request.form['key'].strip()
        provided_keyname = request.form['keyname'].strip()
        chal_keys = Keys.query.filter_by(chal=chal.id).all()

        teamid = Teams.query.filter_by(id=session['id']).first().id
        chalid = request.path.split('/')[-1]
        partial = Partialsolve.query.filter_by(teamid=teamid,
                                               chalid=chalid).first()
        if not partial:
            keys = {}

            for chal_key in chal_keys:
                keys.update(json.loads(chal_key.data))

            flags = json.dumps(keys)
            psolve = Partialsolve(teamid=teamid,
                                  chalid=chalid,
                                  ip=utils.get_ip(req=request),
                                  flags=flags)
            db.session.add(psolve)
            db.session.commit()

        for chal_key in chal_keys:
            key_data = json.loads(chal_key.data)

            if provided_keyname in key_data and get_flag_class(
                    chal_key.type).compare(chal_key, provided_key):
                db.session.expunge_all()
                partial = Partialsolve.query.filter_by(teamid=teamid,
                                                       chalid=chalid).first()

                keys = json.loads(partial.flags)
                keys[provided_keyname] = True
                partial.flags = json.dumps(keys)
                db.session.commit()
                return True, 'Correct'

        return False, 'Incorrect'
    def solve(team, chal, request):
        """
        This method is used to insert TimeDecaySolves into the database in order to mark a challenge as solved.

        :param team: The Team object from the database
        :param chal: The Challenge object from the database
        :param request: The request the user submitted
        :return:
        """
        provided_key = request.form['key'].strip()

        # Record current value for the challenge
        value = TimeDecayChallenge.value(chal)
        solve = Solves(teamid=team.id, chalid=chal.id, ip=utils.get_ip(req=request), flag=provided_key)
        db.session.add(solve)
        time_decay_solve = TimeDecaySolves(teamid=team.id, chalid=chal.id, decayed_value=value)
        db.session.add(time_decay_solve)
        db.session.commit()
        db.session.close()
Пример #22
0
    def attempt(chal, request):
        """Attempt the user answer to see if it's right"""
        provided_key = request.form['key'].strip()
        chal_keys = Keys.query.filter_by(chal=chal.id).all()
        yara_results = yara_rule_tester(provided_key)
        result_type = {}
        for result in yara_results:

            solves = Awards.query.filter_by(
                teamid=session['id'], name=chal.id,
                description=result.strip()).first()
            try:
                flag_value = str(solves.description)
            except AttributeError:
                flag_value = ""
            if result != flag_value and not solves:
                for chal_key in chal_keys:
                    if result == chal_key.flag:
                        result_type[result] = chal_key.type
                    # Challenge not solved yet
                if result_type[result] == "correct":
                    solve = Awards(teamid=session['id'],
                                   name=chal.id,
                                   value=chal.value)
                    solve.description = result
                    db.session.add(solve)
                    db.session.commit()
                elif result_type[result] == "wrong":
                    wrong_value = 0
                    wrong_value -= chal.value
                    wrong = WrongKeys(teamid=session['id'],
                                      chalid=chal.id,
                                      ip=utils.get_ip(request),
                                      flag=result)
                    solve = Awards(teamid=session['id'],
                                   name=chal.id,
                                   value=wrong_value)
                    solve.description = result
                    db.session.add(wrong)
                    db.session.add(solve)
                    db.session.commit()
        db.session.close()
        return False, "Nothing"
Пример #23
0
def 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 = 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()

                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('contests.contests_view'))
    else:
        return render_template('register.html')
Пример #24
0
def chal(chalid):
    if utils.ctf_ended() and not utils.view_after_ctf():
        return redirect(url_for('challenges.challenges_view'))
    if not utils.user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if utils.authed() and utils.is_verified() and (utils.ctf_started() or utils.view_after_ctf()):
        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))

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                wrong = WrongKeys(session['id'], chalid, request.form['key'])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            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:
            chal = Challenges.query.filter_by(id=chalid).first_or_404()
            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"
                })

            chal_class = get_chal_class(chal.type)
            if chal_class.solve(chal, provided_key):
                if utils.ctftime():
                    solve = Solves(chalid=chalid, teamid=session['id'], ip=utils.get_ip(), flag=provided_key)
                    db.session.add(solve)
                    db.session.commit()
                    db.session.close()
                logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                return jsonify({'status': 1, 'message': 'Correct'})

            if utils.ctftime():
                wrong = WrongKeys(teamid=session['id'], chalid=chalid, flag=provided_key)
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            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'
                return jsonify({'status': 0, 'message': 'Incorrect. You have {} {} remaining.'.format(attempts_left, tries_str)})
            else:
                return jsonify({'status': 0, 'message': 'Incorrect'})

        # 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"
        })
Пример #25
0
def chal(chalid):
    if not ctftime():
        return redirect(url_for('challenges.challenges_view'))
    if authed():
        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'), get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Hit max attempts
        if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0:
            return "4" #too many tries on this challenge

        # Anti-bruteforce / submitting keys too quickly
        if get_kpm(session['id']) > 10:
            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data))
            return "3" # Submitting too fast

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

        # Challange not solved yet
        if not solves:
            chal = Challenges.query.filter_by(id=chalid).first()
            key = str(request.form['key'].strip().lower())
            keys = json.loads(chal.flags)
            for x in keys:
                if x['type'] == 0: #static key
                    print(x['flag'], key.strip().lower())
                    if x['flag'] and x['flag'].strip().lower() == key.strip().lower():
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct
                elif x['type'] == 1: #regex
                    res = re.match(str(x['flag']), key, re.IGNORECASE)
                    if res and res.group() == key:
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        return "1" # key was correct

            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data))
            return '0' # key was wrong

        # Challenge already solved
        else:
            logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data))
            return "2" # challenge was already solved
    else:
        return "-1"
Пример #26
0
def chal(chalid):
    if utils.ctf_ended() and not utils.view_after_ctf():
        abort(403)
    if not utils.user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    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))

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                wrong = WrongKeys(teamid=session['id'],
                                  chalid=chalid,
                                  ip=utils.get_ip(),
                                  flag=request.form['key'].strip())
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            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:
            chal = Challenges.query.filter_by(id=chalid).first_or_404()
            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"
                })

            chal_class = get_chal_class(chal.type)
            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"
        })
Пример #27
0
def register_smart():
    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']
        color = request.form['color']
        school = request.form['school']
        image = request.form['image']
        #school = request.form['school']
        if not color in teamColors:
            color = "RED"
        if not image in teamImages:
            image = "HULK"
        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()
        smart_color = SmartCityTeam.query.filter_by(color=color).first()
        smart_image = SmartCityTeam.query.filter_by(image=image).first()
        #challenge = SmartCityChallenge.query.filter_by(id=challenge.id).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 smart_color:
            if not Teams.query.filter_by(id=smart_color.teamId).first().admin:
                errors.append(
                    'Color unavailable. The following colors are available:  \n'
                    + getAvailableColors())
        if smart_image:
            if not Teams.query.filter_by(id=smart_image.teamId).first().admin:
                errors.append('That image is already taken')

        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()

                smart_team = SmartCityTeam(team.id, team.name, color, image,
                                           school)
                db.session.add(smart_team)
                db.session.commit()
                db.session.flush()

                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')
Пример #28
0
def login():
    logger = logging.getLogger('logins')
    if request.method == 'POST':
        errors = []
        name = request.form['name'].strip()
        password = request.form['password']

        # Check if email or password is empty
        if not name or not password:
            errors.append("Please enter your email and password")
            db.session.close()
            return render_template('login.html', errors=errors)

        # Check if the user submitted a valid email address
        if utils.check_email_format(name) is False:
            errors.append("Your email is not in a valid format")
            db.session.close()
            return render_template('login.html', errors=errors)

        # Send POST request to NCL SIO authentication API
        base64creds = base64.b64encode(name + ':' + password)
        headers = {'Authorization': 'Basic ' + base64creds}
        sio_url = utils.ncl_sio_url()

        try:
            r = requests.post(sio_url + '/authentications', headers=headers, timeout=30)
        except requests.exceptions.RequestException as e:
            logger.warn("[{date}] {ip} - error connecting to SIO authentication service: {exception}".format(
                date=time.strftime("%m/%d/%Y %X"),
                ip=utils.get_ip(),
                exception=e
            ))
            errors.append("There is a problem with your login request. Please contact the website administrator")
            db.session.close()
            return render_template('login.html', errors=errors)

        if r.status_code == 200:    # Successful login
            # Check if this user has permission to login (i.e. is in this CTF NCL team)
            ncl_team_name = utils.ncl_team_name()
            is_user_in_ncl_team = False
            user_id = r.json()['id']

            # Send GET request to NCL SIO teams API
            try:
                teams_r = requests.get(sio_url + '/teams?name=' + ncl_team_name, timeout=30)
            except requests.exceptions.RequestException as teams_re:
                logger.warn("[{date}] {ip} - error connecting to SIO teams service: {exception}".format(
                    date=time.strftime("%m/%d/%Y %X"),
                    ip=utils.get_ip(),
                    exception=teams_re
                ))
                errors.append("There is a problem with connecting to login service. Please contact the website administrator")
                db.session.close()
                return render_template('login.html', errors=errors)

            if teams_r.status_code == 200:  # teams GET success
                team_members = teams_r.json()['members']
                for member in team_members:
                    if member['userId'] == user_id:
                        is_user_in_ncl_team = True
                        break
            else:   # teams GET failed
                logger.warn("[{date}] {ip} - invalid response status code: {status}".format(
                    date=time.strftime("%m/%d/%Y %X"),
                    ip=utils.get_ip(),
                    status=str(teams_r.status_code)
                ))
                errors.append("Unknown response from login service. Please contact the website administrator")
                db.session.close()
                return render_template('login.html', errors=errors)

            if not is_user_in_ncl_team:
                # User is not part of NCL team, deny login!
                logger.warn("[{date}] {ip} - not in this CTF NCL team for {username}".format(
                    date=time.strftime("%m/%d/%Y %X"),
                    ip=utils.get_ip(),
                    username=name.encode('utf-8')
                ))
                errors.append("You do not have permissions to login to this site")
                db.session.close()
                return render_template('login.html', errors=errors)

            # User is now allowed to login

            # Try to get info from DB
            team = Teams.query.filter_by(email=name).first()

            # Add to DB if it does not exist
            if not team:
                team = Teams(name.lower(), name.lower(), "unused_password")
                db.session.add(team)
                db.session.commit()
                db.session.flush()
            
            # Get info from DB
            session['username'] = team.name
            session['id'] = team.id
            session['admin'] = team.admin
            session['nonce'] = utils.sha512(os.urandom(10))
            db.session.close()

            logger.warn("[{date}] {ip} - {username} logged in".format(
                date=time.strftime("%m/%d/%Y %X"),
                ip=utils.get_ip(),
                username=session['username'].encode('utf-8')
            ))

            if request.args.get('next') and utils.is_safe_url(request.args.get('next')):
                return redirect(request.args.get('next'))
            return redirect(url_for('challenges.challenges_view'))

        elif r.status_code == 404:  # This user does not exist
            logger.warn("[{date}] {ip} - submitted invalid user email".format(
                date=time.strftime("%m/%d/%Y %X"),
                ip=utils.get_ip()
            ))
            errors.append("Your email or password is incorrect")
            db.session.close()
            return render_template('login.html', errors=errors)

        elif r.status_code == 500:  # This user exists but the password is wrong
            logger.warn("[{date}] {ip} - submitted invalid password for {username}".format(
                date=time.strftime("%m/%d/%Y %X"),
                ip=utils.get_ip(),
                username=name.encode('utf-8')
            ))
            errors.append("Your email or password is incorrect")
            db.session.close()
            return render_template('login.html', errors=errors)

        else:   # Unknown response status code
            logger.warn("[{date}] {ip} - unknown response status code: {status}".format(
                date=time.strftime("%m/%d/%Y %X"),
                ip=utils.get_ip(),
                status=str(r.status_code)
            ))
            errors.append("Unknown login error. Please contact the website administrator")
            db.session.close()
            return render_template('login.html', errors=errors)

    else:
        db.session.close()
        return render_template('login.html')
Пример #29
0
def chal(chalid):
    if not ctftime():
        return redirect(url_for('challenges.challenges_view'))
    if authed():
        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'), get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Anti-bruteforce / submitting keys too quickly
        if get_kpm(session['id']) > 10:
            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            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:
            chal = Challenges.query.filter_by(id=chalid).first()
            key = str(request.form['key'].strip().lower())
            keys = json.loads(chal.flags)

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

            for x in keys:
                if x['type'] == 0: #static key
                    print(x['flag'], key.strip().lower())
                    if x['flag'] and x['flag'].strip().lower() == key.strip().lower():
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        # return "1" # key was correct
                        return jsonify({'status':'1', 'message':'Correct'})
                elif x['type'] == 1: #regex
                    res = re.match(str(x['flag']), key, re.IGNORECASE)
                    if res and res.group() == key:
                        solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key)
                        db.session.add(solve)
                        db.session.commit()
                        db.session.close()
                        logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data))
                        # return "1" # key was correct
                        return jsonify({'status': '1', 'message': 'Correct'})

            wrong = WrongKeys(session['id'], chalid, request.form['key'])
            db.session.add(wrong)
            db.session.commit()
            db.session.close()
            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
                tries_str = 'tries'
                if attempts_left == 1:
                    tries_str = 'try'
                return jsonify({'status': '0', 'message': 'Incorrect. You have {} {} remaining.'.format(attempts_left, tries_str)})
            else:
                return jsonify({'status': '0', 'message': 'Incorrect'})


        # 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 "-1"
Пример #30
0
def chal(chalid):
    if ctf_ended() and not view_after_ctf():
        return redirect(url_for('challenges.challenges_view'))
    if not user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if authed() and is_verified() and (ctf_started() or view_after_ctf()):
        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'), get_kpm(session['id']))
        print("[{0}] {1} submitted {2} with kpm {3}".format(*data))

        # Anti-bruteforce / submitting keys too quickly
        if get_kpm(session['id']) > 10:
            if ctftime():
                wrong = WrongKeys(session['id'], chalid, request.form['key'])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            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:
            chal = Challenges.query.filter_by(id=chalid).first()
            key = unicode(request.form['key'].strip().lower())
            keys = json.loads(chal.flags)

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

            for x in keys:
                if x['type'] == 0:  #static key
                    print(x['flag'], key.strip().lower())
                    if x['flag'] and x['flag'].strip().lower() == key.strip(
                    ).lower():
                        if ctftime():
                            solve = Solves(chalid=chalid,
                                           teamid=session['id'],
                                           ip=get_ip(),
                                           flag=key)
                            db.session.add(solve)
                            db.session.commit()
                            db.session.close()
                        logger.info(
                            "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".
                            format(*data))
                        # return "1" # key was correct
                        return jsonify({'status': '1', 'message': 'Correct'})
                elif x['type'] == 1:  #regex
                    res = re.match(x['flag'], key, re.IGNORECASE)
                    if res and res.group() == key:
                        if ctftime():
                            solve = Solves(chalid=chalid,
                                           teamid=session['id'],
                                           ip=get_ip(),
                                           flag=key)
                            db.session.add(solve)
                            db.session.commit()
                            db.session.close()
                        logger.info(
                            "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".
                            format(*data))
                        # return "1" # key was correct
                        return jsonify({'status': '1', 'message': 'Correct'})

            if ctftime():
                wrong = WrongKeys(session['id'], chalid, request.form['key'])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            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
                tries_str = 'tries'
                if attempts_left == 1:
                    tries_str = 'try'
                return jsonify({
                    'status':
                    '0',
                    'message':
                    'Incorrect. You have {} {} remaining.'.format(
                        attempts_left, tries_str)
                })
            else:
                return jsonify({'status': '0', 'message': 'Incorrect'})

        # 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 "-1"
Пример #31
0
def chal(chalid):
    if utils.ctf_ended() and not utils.view_after_ctf():
        return redirect(url_for('challenges.challenges_view'))
    if not utils.user_can_view_challenges():
        return redirect(url_for('auth.login', next=request.path))
    if utils.authed() and utils.is_verified() and (utils.ctf_started()
                                                   or utils.view_after_ctf()):
        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))

        # Anti-bruteforce / submitting keys too quickly
        if utils.get_kpm(session['id']) > 10:
            if utils.ctftime():
                wrong = WrongKeys(session['id'], chalid, request.form['key'])
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            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:
            chal = Challenges.query.filter_by(id=chalid).first_or_404()
            provided_key = unicode(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"
                })

            chal_class = get_chal_class(chal.type)
            if chal_class.solve(chal, provided_key):
                if utils.ctftime():
                    solve = Solves(chalid=chalid,
                                   teamid=session['id'],
                                   ip=utils.get_ip(),
                                   flag=provided_key)
                    db.session.add(solve)
                    db.session.commit()
                    db.session.close()
                logger.info(
                    "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(
                        *data))
                return jsonify({'status': '1', 'message': 'Correct'})

            if utils.ctftime():
                wrong = WrongKeys(teamid=session['id'],
                                  chalid=chalid,
                                  flag=provided_key)
                db.session.add(wrong)
                db.session.commit()
                db.session.close()
            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'
                return jsonify({
                    'status':
                    '0',
                    'message':
                    'Incorrect. You have {} {} remaining.'.format(
                        attempts_left, tries_str)
                })
            else:
                return jsonify({'status': '0', 'message': 'Incorrect'})

        # 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"
        })
Пример #32
0
def 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("邮箱格式不正确")
        if names:
            errors.append('用户名已被其他用户使用')
        if team_name_email_check is True:
            errors.append('用户名不能和邮箱一样')
        if emails:
            errors.append('邮箱已被其他用户使用')
        if pass_short:
            errors.append('密码长度不够')
        if pass_long:
            errors.append('密码长度超过上限')
        if name_len:
            errors.append('用户名长度不够')

        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()

                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'], "您已经成功过注册了 {}".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')
Пример #33
0
def 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']
        sno = request.form['sno']
        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()
        valid_sno = utils.check_sno_format(request.form['sno'])
        snos = Teams.query.add_columns('sno', 'id').filter_by(sno=sno).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_sno:
            errors.append("Please enter a valid student ID")
        if not valid_email:
            errors.append("Please enter a valid email address")
        if names or snos:
            errors.append('That nick/user 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, sno, email.lower(), password)
                db.session.add(team)
                db.session.commit()
                db.session.flush()

                session['username'] = team.name
                session['sno'] = team.sno
                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}/{sno} registered (UNCONFIRMED) with {email}"
                        .format(date=time.strftime("%m/%d/%Y %X"),
                                ip=utils.get_ip(),
                                username=request.form['name'].encode('utf-8'),
                                sno=request.form['sno'].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}/{sno} registered with {email}".format(
                date=time.strftime("%m/%d/%Y %X"),
                ip=utils.get_ip(),
                username=request.form['name'].encode('utf-8'),
                sno=request.form['sno'].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')