Пример #1
0
    def post(self):
        if authed() is False:
            return {"success": True, "data": {"status": "authentication_required"}}, 403

        if request.content_type != "application/json":
            request_data = request.form
        else:
            request_data = request.get_json()

        challenge_id = request_data.get("challenge_id")

        if current_user.is_admin():
            preview = request.args.get("preview", False)
            if preview:
                challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()
                chal_class = get_chal_class(challenge.type)
                status, message = chal_class.attempt(challenge, request)

                return {
                    "success": True,
                    "data": {
                        "status": "correct" if status else "incorrect",
                        "message": message,
                    },
                }

        if ctf_paused():
            return (
                {
                    "success": True,
                    "data": {
                        "status": "paused",
                        "message": "{} is paused".format(config.ctf_name()),
                    },
                },
                403,
            )

        user = get_current_user()
        team = get_current_team()

        # TODO: Convert this into a re-useable decorator
        if config.is_teams_mode() and team is None:
            abort(403)

        fails = Fails.query.filter_by(
            account_id=user.account_id, challenge_id=challenge_id
        ).count()

        challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()

        if challenge.state == "hidden":
            abort(404)

        if challenge.state == "locked":
            abort(403)

        if challenge.requirements:
            requirements = challenge.requirements.get("prerequisites", [])
            solve_ids = (
                Solves.query.with_entities(Solves.challenge_id)
                .filter_by(account_id=user.account_id)
                .order_by(Solves.challenge_id.asc())
                .all()
            )
            solve_ids = set([solve_id for solve_id, in solve_ids])
            prereqs = set(requirements)
            if solve_ids >= prereqs:
                pass
            else:
                abort(403)

        chal_class = get_chal_class(challenge.type)

        # Anti-bruteforce / submitting Flags too quickly
        kpm = current_user.get_wrong_submissions_per_minute(user.account_id)
        if kpm > 10:
            if ctftime():
                chal_class.fail(
                    user=user, team=team, challenge=challenge, request=request
                )
            log(
                "submissions",
                "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [TOO FAST]",
                submission=request_data.get("submission", "").encode("utf-8"),
                challenge_id=challenge_id,
                kpm=kpm,
            )
            # Submitting too fast
            return (
                {
                    "success": True,
                    "data": {
                        "status": "ratelimited",
                        "message": "You're submitting flags too fast. Slow down.",
                    },
                },
                429,
            )

        solves = Solves.query.filter_by(
            account_id=user.account_id, challenge_id=challenge_id
        ).first()

        # Challenge not solved yet
        if not solves:
            # Hit max attempts
            max_tries = challenge.max_attempts
            if max_tries and fails >= max_tries > 0:
                return (
                    {
                        "success": True,
                        "data": {
                            "status": "incorrect",
                            "message": "You have 0 tries remaining",
                        },
                    },
                    403,
                )

            status, message = chal_class.attempt(challenge, request)
            if status:  # The challenge plugin says the input is right
                if ctftime() or current_user.is_admin():
                    chal_class.solve(
                        user=user, team=team, challenge=challenge, request=request
                    )
                    clear_standings()

                log(
                    "submissions",
                    "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [CORRECT]",
                    submission=request_data.get("submission", "").encode("utf-8"),
                    challenge_id=challenge_id,
                    kpm=kpm,
                )
                return {
                    "success": True,
                    "data": {"status": "correct", "message": message},
                }
            else:  # The challenge plugin says the input is wrong
                if ctftime() or current_user.is_admin():
                    chal_class.fail(
                        user=user, team=team, challenge=challenge, request=request
                    )
                    clear_standings()

                log(
                    "submissions",
                    "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [WRONG]",
                    submission=request_data.get("submission", "").encode("utf-8"),
                    challenge_id=challenge_id,
                    kpm=kpm,
                )

                if max_tries:
                    # Off by one since fails has changed since it was gotten
                    attempts_left = max_tries - fails - 1
                    tries_str = "tries"
                    if attempts_left == 1:
                        tries_str = "try"
                    # Add a punctuation mark if there isn't one
                    if message[-1] not in "!().;?[]{}":
                        message = message + "."
                    return {
                        "success": True,
                        "data": {
                            "status": "incorrect",
                            "message": "{} You have {} {} remaining.".format(
                                message, attempts_left, tries_str
                            ),
                        },
                    }
                else:
                    return {
                        "success": True,
                        "data": {"status": "incorrect", "message": message},
                    }

        # Challenge already solved
        else:
            log(
                "submissions",
                "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [ALREADY SOLVED]",
                submission=request_data.get("submission", "").encode("utf-8"),
                challenge_id=challenge_id,
                kpm=kpm,
            )
            return {
                "success": True,
                "data": {
                    "status": "already_solved",
                    "message": "You already solved this",
                },
            }
Пример #2
0
    def post(self):
        if authed() is False:
            return {
                'success': True,
                'data': {
                    'status': "authentication_required",
                }
            }, 403

        if request.content_type != 'application/json':
            request_data = request.form
        else:
            request_data = request.get_json()

        challenge_id = request_data.get('challenge_id')

        if current_user.is_admin():
            preview = request.args.get('preview', False)
            if preview:
                challenge = Challenges.query.filter_by(
                    id=challenge_id).first_or_404()
                chal_class = get_chal_class(challenge.type)
                status, message = chal_class.attempt(challenge, request)

                return {
                    'success': True,
                    'data': {
                        'status': "correct" if status else "incorrect",
                        'message': message
                    }
                }

        if ctf_paused():
            return {
                'success': True,
                'data': {
                    'status': "paused",
                    'message': '{} приостановлены'.format(config.ctf_name())
                }
            }, 403

        user = get_current_user()
        team = get_current_team()

        fails = Fails.query.filter_by(account_id=user.account_id,
                                      challenge_id=challenge_id).count()

        challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()

        if challenge.state == 'hidden':
            abort(404)

        if challenge.state == 'locked':
            abort(403)

        if challenge.requirements:
            requirements = challenge.requirements.get('prerequisites', [])
            solve_ids = Solves.query \
                .with_entities(Solves.challenge_id) \
                .filter_by(account_id=user.account_id) \
                .order_by(Solves.challenge_id.asc()) \
                .all()
            solve_ids = set([solve_id for solve_id, in solve_ids])
            prereqs = set(requirements)
            if solve_ids >= prereqs:
                pass
            else:
                abort(403)

        chal_class = get_chal_class(challenge.type)

        # Anti-bruteforce / submitting Flags too quickly
        if current_user.get_wrong_submissions_per_minute(session['id']) > 10:
            if ctftime():
                chal_class.fail(user=user,
                                team=team,
                                challenge=challenge,
                                request=request)
            log('submissions',
                "[{date}] {name} submitted {submission} with kpm {kpm} [TOO FAST]",
                submission=request_data['submission'].encode('utf-8'),
                kpm=current_user.get_wrong_submissions_per_minute(
                    session['id']))
            # Submitting too fast
            return {
                'success': True,
                'data': {
                    'status': "ratelimited",
                    'message':
                    "Вы отправляете флаги слишком быстро. Помедленнее."
                }
            }, 429

        solves = Solves.query.filter_by(account_id=user.account_id,
                                        challenge_id=challenge_id).first()

        # Challenge not solved yet
        if not solves:
            # Hit max attempts
            max_tries = challenge.max_attempts
            if max_tries and fails >= max_tries > 0:
                return {
                    'success': True,
                    'data': {
                        'status': "incorrect",
                        'message': "У вас осталось 0 попыток"
                    }
                }, 403

            status, message = chal_class.attempt(challenge, request)
            if status:  # The challenge plugin says the input is right
                if ctftime() or current_user.is_admin():
                    chal_class.solve(user=user,
                                     team=team,
                                     challenge=challenge,
                                     request=request)
                    clear_standings()

                log('submissions',
                    "[{date}] {name} submitted {submission} with kpm {kpm} [CORRECT]",
                    submission=request_data['submission'].encode('utf-8'),
                    kpm=current_user.get_wrong_submissions_per_minute(
                        session['id']))
                return {
                    'success': True,
                    'data': {
                        'status': "correct",
                        'message': message
                    }
                }
            else:  # The challenge plugin says the input is wrong
                if ctftime() or current_user.is_admin():
                    chal_class.fail(user=user,
                                    team=team,
                                    challenge=challenge,
                                    request=request)
                    clear_standings()

                log('submissions',
                    "[{date}] {name} submitted {submission} with kpm {kpm} [WRONG]",
                    submission=request_data['submission'].encode('utf-8'),
                    kpm=current_user.get_wrong_submissions_per_minute(
                        session['id']))

                if max_tries:
                    # Off by one since fails has changed since it was gotten
                    attempts_left = max_tries - fails - 1
                    tries_str = 'попытки'
                    if attempts_left == 1:
                        tries_str = 'попытка'
                    # Add a punctuation mark if there isn't one
                    if message[-1] not in '!().;?[]{}':
                        message = message + '.'
                    return {
                        'success': True,
                        'data': {
                            'status':
                            "incorrect",
                            'message':
                            '{} У вас {} {} осталось.'.format(
                                message, attempts_left, tries_str)
                        }
                    }
                else:
                    return {
                        'success': True,
                        'data': {
                            'status': "incorrect",
                            'message': message
                        }
                    }

        # Challenge already solved
        else:
            log('submissions',
                "[{date}] {name} submitted {submission} with kpm {kpm} [ALREADY SOLVED]",
                submission=request_data['submission'].encode('utf-8'),
                kpm=current_user.get_wrong_submissions_per_minute(
                    user.account_id))
            return {
                'success': True,
                'data': {
                    'status': "already_solved",
                    'message': 'Вы уже решили это'
                }
            }
Пример #3
0
    def post(self):
        if authed() is False:
            return {
                'success': True,
                'data': {
                    'status': "authentication_required",
                }
            }, 403

        if request.content_type != 'application/json':
            request_data = request.form
        else:
            request_data = request.get_json()

        challenge_id = request_data.get('challenge_id')

        if current_user.is_admin():
            preview = request.args.get('preview', False)
            if preview:
                challenge = Challenges.query.filter_by(
                    id=challenge_id).first_or_404()
                chal_class = get_chal_class(challenge.type)
                status, message = chal_class.attempt(challenge, request)

                return {
                    'success': True,
                    'data': {
                        'status': "correct" if status else "incorrect",
                        'message': message
                    }
                }

        if ctf_paused():
            return {
                'success': True,
                'data': {
                    'status': "paused",
                    'message': '{} is paused'.format(config.ctf_name())
                }
            }, 403

        user = get_current_user()
        team = get_current_team()

        # TODO: Convert this into a re-useable decorator
        if config.is_teams_mode() and team is None:
            abort(403)

        fails = Fails.query.filter_by(account_id=user.account_id,
                                      challenge_id=challenge_id).count()

        challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()

        if challenge.state == 'hidden':
            abort(404)

        if challenge.state == 'locked':
            abort(403)

        if challenge.requirements:
            requirements = challenge.requirements.get('prerequisites', [])
            solve_ids = Solves.query \
                .with_entities(Solves.challenge_id) \
                .filter_by(account_id=user.account_id) \
                .order_by(Solves.challenge_id.asc()) \
                .all()
            solve_ids = set([solve_id for solve_id, in solve_ids])
            prereqs = set(requirements)
            if solve_ids >= prereqs:
                pass
            else:
                abort(403)

        chal_class = get_chal_class(challenge.type)

        # Anti-bruteforce / submitting Flags too quickly
        if current_user.get_wrong_submissions_per_time(
                get_current_user(), config.get_attempt_limit_type(),
                config.get_attempt_limit_hour(),
                config.get_attempt_limit_minute(),
                config.get_attempt_limit_second()
        ) > config.get_attempt_limit_count():
            if ctftime():
                chal_class.fail(user=user,
                                team=team,
                                challenge=challenge,
                                request=request)
            log('submissions',
                "[{date}] {name} submitted {submission} with kpm {kpm} [TOO FAST]",
                submission=request_data['submission'].encode('utf-8'),
                kpm=current_user.get_wrong_submissions_per_time(
                    get_current_user(), config.get_attempt_limit_type(),
                    config.get_attempt_limit_hour(),
                    config.get_attempt_limit_minute(),
                    config.get_attempt_limit_second()))
            # Submitting too fast
            return {
                'success': True,
                'data': {
                    'status': "ratelimited",
                    'message': "You're submitting flags too fast. Slow down."
                }
            }, 429

        solves = Solves.query.filter_by(account_id=user.account_id,
                                        challenge_id=challenge_id).first()

        # Challenge not solved yet
        if not solves:
            # Hit max attempts
            max_tries = challenge.max_attempts
            if max_tries and fails >= max_tries > 0:
                return {
                    'success': True,
                    'data': {
                        'status': "incorrect",
                        'message': "You have 0 tries remaining"
                    }
                }, 403

            status, message = chal_class.attempt(challenge, request)
            if status:  # The challenge plugin says the input is right
                if ctftime() or current_user.is_admin():
                    chal_class.solve(user=user,
                                     team=team,
                                     challenge=challenge,
                                     request=request)
                    clear_standings()

                log('submissions',
                    "[{date}] {name} submitted {submission} with kpm {kpm} [CORRECT]",
                    submission=request_data['submission'].encode('utf-8'),
                    kpm=current_user.get_wrong_submissions_per_minute(
                        session['id']))
                return {
                    'success': True,
                    'data': {
                        'status': "correct",
                        'message': message
                    }
                }
            else:  # The challenge plugin says the input is wrong
                if ctftime() or current_user.is_admin():
                    chal_class.fail(user=user,
                                    team=team,
                                    challenge=challenge,
                                    request=request)
                    clear_standings()

                log('submissions',
                    "[{date}] {name} submitted {submission} with kpm {kpm} [WRONG]",
                    submission=request_data['submission'].encode('utf-8'),
                    kpm=current_user.get_wrong_submissions_per_minute(
                        session['id']))

                if max_tries:
                    # Off by one since fails has changed since it was gotten
                    attempts_left = max_tries - fails - 1
                    tries_str = 'tries'
                    if attempts_left == 1:
                        tries_str = 'try'
                    # Add a punctuation mark if there isn't one
                    if message[-1] not in '!().;?[]{}':
                        message = message + '.'
                    return {
                        'success': True,
                        'data': {
                            'status':
                            "incorrect",
                            'message':
                            '{} You have {} {} remaining.'.format(
                                message, attempts_left, tries_str)
                        }
                    }
                else:
                    return {
                        'success': True,
                        'data': {
                            'status': "incorrect",
                            'message': message
                        }
                    }

        # Challenge already solved
        else:
            log('submissions',
                "[{date}] {name} submitted {submission} with kpm {kpm} [ALREADY SOLVED]",
                submission=request_data['submission'].encode('utf-8'),
                kpm=current_user.get_wrong_submissions_per_minute(
                    user.account_id))
            return {
                'success': True,
                'data': {
                    'status': "already_solved",
                    'message': 'You already solved this'
                }
            }
Пример #4
0
    def post(self):
        if authed() is False:
            return {
                "success": True,
                "data": {
                    "status": "authentication_required"
                }
            }, 403

        if request.content_type != "application/json":
            request_data = request.form
        else:
            request_data = request.get_json()

        challenge_id = request_data.get("challenge_id")

        if current_user.is_admin():
            preview = request.args.get("preview", False)
            if preview:
                challenge = Challenges.query.filter_by(
                    id=challenge_id).first_or_404()
                chal_class = get_chal_class(challenge.type)
                status, message = chal_class.attempt(challenge, request)

                return {
                    "success": True,
                    "data": {
                        "status": "correct" if status else "incorrect",
                        "message": message,
                    },
                }

        if ctf_paused():
            return (
                {
                    "success": True,
                    "data": {
                        "status": "paused",
                        "message": "{} is paused".format(config.ctf_name()),
                    },
                },
                403,
            )

        user = get_current_user()
        team = get_current_team()

        # TODO: Convert this into a re-useable decorator
        if config.is_teams_mode() and team is None:
            abort(403)

        fails = Fails.query.filter_by(account_id=user.account_id,
                                      challenge_id=challenge_id).count()

        challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()

        if challenge.state == "hidden":
            abort(404)

        if challenge.state == "locked":
            abort(403)

        if challenge.requirements:
            requirements = challenge.requirements.get("prerequisites", [])
            solve_ids = (Solves.query.with_entities(
                Solves.challenge_id).filter_by(
                    account_id=user.account_id).order_by(
                        Solves.challenge_id.asc()).all())
            solve_ids = {solve_id for solve_id, in solve_ids}
            # Gather all challenge IDs so that we can determine invalid challenge prereqs
            all_challenge_ids = {
                c.id
                for c in Challenges.query.with_entities(Challenges.id).all()
            }
            prereqs = set(requirements).intersection(all_challenge_ids)
            if solve_ids >= prereqs:
                pass
            else:
                abort(403)

        chal_class = get_chal_class(challenge.type)

        # Anti-bruteforce / submitting Flags too quickly
        kpm = current_user.get_wrong_submissions_per_minute(user.account_id)
        if kpm > 10:
            if ctftime():
                chal_class.fail(user=user,
                                team=team,
                                challenge=challenge,
                                request=request)
            log(
                "submissions",
                "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [TOO FAST]",
                name=user.name,
                submission=request_data.get("submission", "").encode("utf-8"),
                challenge_id=challenge_id,
                kpm=kpm,
            )
            # Submitting too fast
            return (
                {
                    "success": True,
                    "data": {
                        "status": "ratelimited",
                        "message":
                        "You're submitting flags too fast. Slow down.",
                    },
                },
                429,
            )

        solves = Solves.query.filter_by(account_id=user.account_id,
                                        challenge_id=challenge_id).first()

        # Challenge not solved yet
        if not solves:
            # Hit max attempts
            max_tries = challenge.max_attempts
            if max_tries and fails >= max_tries > 0:
                return (
                    {
                        "success": True,
                        "data": {
                            "status": "incorrect",
                            "message": "You have 0 tries remaining",
                        },
                    },
                    403,
                )

            status, message = chal_class.attempt(challenge, request)
            if status:  # The challenge plugin says the input is right
                if ctftime() or current_user.is_admin():

                    # send discord webhook
                    # @TODO replace static url with a global variable containing the site url in config.py
                    user_url = "https://ctf.sigpwny.com/users/" + str(user.id)
                    challenge_url = "https://ctf.sigpwny.com/challenges#" + quote(
                        challenge.name)

                    description = ":white_check_mark: [{0}]({1}) solved [{2}]({3}) ({4})".format(
                        user.name, user_url, challenge.name, challenge_url,
                        challenge.value)

                    embeds = [{
                        "description":
                        description,
                        "color":
                        10553667,
                        "timestamp":
                        datetime.datetime.utcnow().strftime(
                            '%Y-%m-%d %H:%M:%SZ')
                    }]

                    send_discord_webhook(embeds)

                    chal_class.solve(user=user,
                                     team=team,
                                     challenge=challenge,
                                     request=request)
                    clear_standings()

                log(
                    "submissions",
                    "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [CORRECT]",
                    name=user.name,
                    submission=request_data.get("submission",
                                                "").encode("utf-8"),
                    challenge_id=challenge_id,
                    kpm=kpm,
                )
                return {
                    "success": True,
                    "data": {
                        "status": "correct",
                        "message": message
                    },
                }
            else:  # The challenge plugin says the input is wrong
                if ctftime() or current_user.is_admin():
                    chal_class.fail(user=user,
                                    team=team,
                                    challenge=challenge,
                                    request=request)
                    clear_standings()

                log(
                    "submissions",
                    "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [WRONG]",
                    name=user.name,
                    submission=request_data.get("submission",
                                                "").encode("utf-8"),
                    challenge_id=challenge_id,
                    kpm=kpm,
                )

                if max_tries:
                    # Off by one since fails has changed since it was gotten
                    attempts_left = max_tries - fails - 1
                    tries_str = "tries"
                    if attempts_left == 1:
                        tries_str = "try"
                    # Add a punctuation mark if there isn't one
                    if message[-1] not in "!().;?[]{}":
                        message = message + "."
                    return {
                        "success": True,
                        "data": {
                            "status":
                            "incorrect",
                            "message":
                            "{} You have {} {} remaining.".format(
                                message, attempts_left, tries_str),
                        },
                    }
                else:
                    return {
                        "success": True,
                        "data": {
                            "status": "incorrect",
                            "message": message
                        },
                    }

        # Challenge already solved
        else:
            log(
                "submissions",
                "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [ALREADY SOLVED]",
                name=user.name,
                submission=request_data.get("submission", "").encode("utf-8"),
                challenge_id=challenge_id,
                kpm=kpm,
            )
            return {
                "success": True,
                "data": {
                    "status": "already_solved",
                    "message": "You already solved this",
                },
            }
Пример #5
0
    def flaganizer_submit():
        if authed() is False:
            return {
                "success": True,
                "data": {
                    "status": "authentication_required"
                }
            }, 403

        if request.content_type != "application/json":
            request_data = request.form
        else:
            request_data = request.get_json()

        if ctf_paused():
            return (
                {
                    "success": True,
                    "data": {
                        "status": "paused",
                        "message": "{} is paused".format(config.ctf_name()),
                    },
                },
                403,
            )

        user = get_current_user()
        team = get_current_team()

        # TODO: Convert this into a re-useable decorator
        if config.is_teams_mode() and team is None:
            abort(403)

        kpm = current_user.get_wrong_submissions_per_minute(user.account_id)

        frsp = requests.post(FLAGANIZER_VERIFY_ENDPOINT,
                             data={
                                 "flag": request_data.get("submission", "")
                             },
                             headers={
                                 "X-CTFProxy-SubAcc-JWT":
                                 request.headers.get("X-CTFProxy-JWT")
                             }).json()
        if frsp["Success"] == 0:
            if ctftime() or current_user.is_admin():
                placeholder_challenge = Challenges.query.filter_by(
                    name="wrong submission").first()
                if placeholder_challenge is None:
                    placeholder_challenge = Challenges(
                        name="wrong submission",
                        description=FLAGANIZER_DESCRIPTION_PREFIX +
                        "a placeholder challenge for unrecognized flags",
                        value=0,
                        category="misc",
                        state="hidden",
                        max_attempts=0)
                    db.session.add(placeholder_challenge)
                    db.session.commit()
                    db.session.close()
                    placeholder_challenge = Challenges.query.filter_by(
                        name="wrong submission").first()
                chal_class = get_chal_class(placeholder_challenge.type)
                if placeholder_challenge is not None:
                    chal_class.fail(user=user,
                                    team=team,
                                    challenge=placeholder_challenge,
                                    request=request)
                    clear_standings()
            log(
                "submissions",
                "[{date}] {name} submitted {submission} via flaganizer with kpm {kpm} [WRONG]",
                submission=request_data.get("submission", "").encode("utf-8"),
                kpm=kpm,
            )
            return {
                "success": True,
                "data": {
                    "status": "incorrect",
                    "message": frsp["Message"]
                },
            }

        challenge = Challenges.query.filter_by(
            description=FLAGANIZER_DESCRIPTION_PREFIX +
            frsp["Flag"]["Id"]).first()
        if challenge is None:
            challenge = Challenges(name=frsp["Flag"]["DisplayName"],
                                   description=FLAGANIZER_DESCRIPTION_PREFIX +
                                   frsp["Flag"]["Id"],
                                   value=frsp["Flag"]["Points"],
                                   category=frsp["Flag"]["Category"],
                                   state="hidden",
                                   max_attempts=0)

            db.session.add(challenge)
            db.session.commit()
        challenge_id = challenge.id

        if challenge.state == "locked":
            db.session.close()
            abort(403)

        if challenge.requirements:
            requirements = challenge.requirements.get("prerequisites", [])
            solve_ids = (Solves.query.with_entities(
                Solves.challenge_id).filter_by(
                    account_id=user.account_id).order_by(
                        Solves.challenge_id.asc()).all())
            solve_ids = set([solve_id for solve_id, in solve_ids])
            prereqs = set(requirements)
            if solve_ids >= prereqs:
                pass
            else:
                db.session.close()
                abort(403)

        chal_class = get_chal_class(challenge.type)

        if kpm > 10:
            if ctftime():
                chal_class.fail(user=user,
                                team=team,
                                challenge=challenge,
                                request=request)
            log(
                "submissions",
                "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [TOO FAST]",
                submission=request_data.get("submission", "").encode("utf-8"),
                challenge_id=challenge_id,
                kpm=kpm,
            )
            # Submitting too fast
            db.session.close()
            return (
                {
                    "success": True,
                    "data": {
                        "status": "ratelimited",
                        "message":
                        "You're submitting flags too fast. Slow down.",
                    },
                },
                429,
            )

        solves = Solves.query.filter_by(account_id=user.account_id,
                                        challenge_id=challenge_id).first()

        # Challenge not solved yet
        if not solves:
            status, message = chal_class.attempt(challenge, request)
            chal_class.solve(user=user,
                             team=team,
                             challenge=challenge,
                             request=request)
            clear_standings()
            log(
                "submissions",
                "[{date}] {name} submitted {submission} on {challenge_id} via flaganizer with kpm {kpm} [CORRECT]",
                submission=request_data.get("submission", "").encode("utf-8"),
                challenge_id=challenge_id,
                kpm=kpm,
            )
            db.session.close()
            return {
                "success": True,
                "data": {
                    "status": "correct",
                    "message": "Successfully submitted!"
                },
            }
        else:
            log(
                "submissions",
                "[{date}] {name} submitted {submission} on {challenge_id} via flaganizer with kpm {kpm} [ALREADY SOLVED]",
                submission=request_data.get("submission", "").encode("utf-8"),
                challenge_id=challenge_id,
                kpm=kpm,
            )
            db.session.close()
            return {
                "success": True,
                "data": {
                    "status": "already_solved",
                    "message": "You already solved this",
                },
            }
Пример #6
0
    def post(self):
        if authed() is False:
            return {
                "success": True,
                "data": {
                    "status": "authentication_required"
                }
            }, 403

        if ctf_paused():
            return (
                {
                    "success": True,
                    "data": {
                        "status": "paused",
                        "message": "{} is paused".format(config.ctf_name()),
                    },
                },
                403,
            )

        if request.content_type != "application/json":
            request_data = request.form
        else:
            request_data = request.get_json()

        user = get_current_user()
        team = get_current_team()

        if config.is_teams_mode() and team is None:
            abort(403)

        # Anti-bruteforce / submitting Flags too quickly
        kpm = current_user.get_wrong_submissions_per_minute(user.account_id)
        if kpm > 10:
            log(
                "submissions",
                "[{date}] {name} submitted {submission} with kpm {kpm} [TOO FAST]",
                submission=request_data["submission"].encode("utf-8"),
                kpm=kpm,
            )
            # Submitting too fast
            return (
                {
                    "success": True,
                    "data": {
                        "status": "ratelimited",
                        "message":
                        "You're submitting flags too fast. Slow down.",
                    },
                },
                429,
            )

        challs = Challenges.query.all()
        for challenge in challs:
            correct, message = self.attempt_single(request, request_data, user,
                                                   team, kpm, challenge)
            if correct:
                return {
                    "success": True,
                    "data": {
                        "status": "correct",
                        "message": message
                    },
                }

        chal_class = get_chal_class('standard')
        challenge = Challenges.query.filter_by(
            name='__SECRET__').first_or_404()
        chal_class.fail(user=user,
                        team=team,
                        challenge=challenge,
                        request=request)

        return {
            "success": True,
            "data": {
                "status": "incorrect",
                "message": "Incorrect flag.",
            },
        }