def listing(): infos = get_infos() errors = get_errors() if ctf_started() is False: errors.append(f"{config.ctf_name()} ещё не начался") if ctf_paused() is True: infos.append(f"{config.ctf_name()} приостановлен") if ctf_ended() is True: infos.append(f"{config.ctf_name()} закончился") return render_template("challenges.html", infos=infos, errors=errors)
def listing(): infos = get_infos() errors = get_errors() if ctf_started() is False: errors.append(f"{config.ctf_name()} has not started yet") if ctf_paused() is True: infos.append(f"{config.ctf_name()} is paused") if ctf_ended() is True: infos.append(f"{config.ctf_name()} has ended") return render_template("challenges.html", infos=infos, errors=errors)
def bonus(): if dates.ctf_paused(): return redirect('/scoreboard') #try to open the file itself because I can't figure out how to change template path... this way it lives in the assets path location = (app.instance_path + '/plugins/BonusChallenge/assets/bonus.html').replace("instance", "CTFd") # # print(location) file = open(location, 'r') template_string = file.read() file.close() # # print(template_string) #bonus flags already captured by this team #bhk3 sqlalchemy notes already_solved = Solves.query.join(Challenges).filter(Solves.team_id == session.get('id'), Challenges.type == 'bonus').all() if request.method == 'GET': return render_template_string(template_string, already_solved=already_solved, message='' ) # return render_template('bonus.html', already_solved=already_solved, message='') #if you get here, you're submitting a flag / POSTING unsolved_bonuses = Challenges.query.filter(Challenges.type == 'bonus').all() team = Teams.query.filter(Teams.id == session.get('id')).first() provided_valid_key = False for chal in unsolved_bonuses: #searching for a lock that this key will open status, message = BonusChallenge.attempt(chal, request) #status will be True if valid key presented if status == True: # presented valid flag resubmitted_key = False for solved_chal in already_solved: #searching for a resubmitted key if chal.id == solved_chal.id: message = "You've already submitted this flag." # print(message) resubmitted_key = True break if resubmitted_key: break #if you got here,you submitted a flag which has not already been submitted by this team and get points provided_valid_key = True BonusChallenge.solve(team=team, chal=chal, request=request) #points given as an Award break if provided_valid_key == False or resubmitted_key == True: # BonusChallenge.fail(team=team, chal=chal, request=request) # print(f"team '{team.name}' submitted a bonus flag: '{request.form.get('key').strip()}'") message = 'Invalid key or you\'ve already submitted this before.' return render_template_string(template_string, already_solved=already_solved, message=message )
def listing(): infos = get_infos() errors = get_errors() start = get_config("start") or 0 end = get_config("end") or 0 if ctf_paused(): infos.append("{} is paused".format(config.ctf_name())) # CTF has ended but we want to allow view_after_ctf. Show error but let JS load challenges. if ctf_ended() and view_after_ctf(): infos.append("{} has ended".format(config.ctf_name())) return render_template( "challenges.html", infos=infos, errors=errors, start=int(start), end=int(end) )
def listing(): infos = get_infos() errors = get_errors() start = get_config('start') or 0 end = get_config('end') or 0 if ctf_paused(): infos.append('{} is paused'.format(config.ctf_name())) if view_after_ctf(): infos.append('{} has ended'.format(config.ctf_name())) return render_template('challenges.html', infos=infos, errors=errors, start=int(start), end=int(end))
def listing(): if (Configs.challenge_visibility == ChallengeVisibilityTypes.PUBLIC and authed() is False): pass else: if is_teams_mode() and get_current_team() is None: return redirect(url_for("teams.private", next=request.full_path)) infos = get_infos() errors = get_errors() if ctf_started() is False: errors.append(f"{Configs.ctf_name} has not started yet") if ctf_paused() is True: infos.append(f"{Configs.ctf_name} is paused") if ctf_ended() is True: infos.append(f"{Configs.ctf_name} has ended") return render_template("challenges.html", infos=infos, errors=errors)
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", }, }
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': 'Вы уже решили это' } }
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' } }
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", }, }
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", }, }
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.", }, }
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, ) if current_user.already_rated(challenge_id): return ( { "success": False, "data": { "status": "rated", "message": "user already rated", } }, 403, ) user = get_current_user() team = get_current_team() solves = Solves.query.filter_by(account_id=user.account_id, challenge_id=challenge_id).first() if not solves: return ( { "success": False, "data": { "status": "unsolved", "message": "user not solved the challenge", } }, 403, ) else: chal_class = get_chal_class(challenge.type) chal_class.rate(user=user, challenge=challenge, request=request)