def admin_update_chal(): challenge = Challenges.query.filter_by( id=request.form['id']).first_or_404() if challenge.hidden == True: chal_class = get_chal_class(challenge.type) chal_class.update(challenge, request) if not 'hidden' in request.form: t = datetime.datetime.fromtimestamp( time.time()).strftime('%c').split(' ')[3] broadcast(t + ": Thử thách " + request.form['category'] + " " + request.form['value'] + ": " + request.form['name'] + " đã được mở!") else: chal_class = get_chal_class(challenge.type) chal_class.update(challenge, request) if not 'hidden' in request.form: t = datetime.datetime.fromtimestamp( time.time()).strftime('%c').split(' ')[3] broadcast(t + " Thử thách " + request.form['category'] + " " + request.form['value'] + ": " + request.form['name'] + " đã được update") else: t = datetime.datetime.fromtimestamp( time.time()).strftime('%c').split(' ')[3] broadcast(t + ": Thử thách " + request.form['category'] + " " + request.form['value'] + ": " + request.form['name'] + " đã được đóng") return redirect(url_for('admin_challenges.admin_chals'))
def admin_update_chal(): challenge = Challenges.query.filter_by( id=request.form['id']).first_or_404() chal_class = get_chal_class(challenge.type) old_description = challenge.description challenge_name = challenge.name chal_class.update(challenge, request) new_description = request.form["description"] if old_description != new_description and not 'hidden' in request.form: chal_url = url_for("challenges.challenges_view", _anchor=challenge_name, _external=True) description = ":pencil: [{0}]({1}) has been updated!\n```{2}```".format( challenge_name, chal_url, new_description or "No description") embeds = [{ "description": description, "color": 10553667, "timestamp": datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%SZ') }] utils.send_discord_webhook(embeds) return redirect(url_for('admin_challenges.admin_chals'))
def admin_create_chal(): if request.method == 'POST': chal_type = request.form['chaltype'] chal_class = get_chal_class(chal_type) chal = chal_class.create(request) if not chal.hidden: chal_url = url_for("challenges.challenges_view", _anchor=chal.name, _external=True) description = ":new: [{0}]({1}) ({2}) has been created!".format( chal.name, chal_url, chal.value, chal.description) if chal.description: description += "\n```{0}```".format(chal.description) embeds = [{ "description": description, "color": 10553667, "timestamp": datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%SZ') }] utils.send_discord_webhook(embeds) return redirect(url_for('admin_challenges.admin_chals')) else: return render_template('admin/chals/create.html')
def test_admin_chal_detail_returns_proper_data(): """Test that the /admin/chals/<int:chalid> endpoint returns the proper data""" app = create_ctfd() with app.app_context(): client = login_as_user(app, name="admin", password="******") chal = gen_challenge(app.db) chal_class = get_chal_class(chal.type) data = { 'id': chal.id, 'name': chal.name, 'value': chal.value, 'description': chal.description, 'category': chal.category, 'hidden': chal.hidden, 'max_attempts': chal.max_attempts, 'type': chal.type, 'type_data': { 'id': chal_class.id, 'name': chal_class.name, 'templates': chal_class.templates, 'scripts': chal_class.scripts, } } assert Challenges.query.count() == 1 r = client.get('/admin/chal/1') response = json.loads(r.get_data(as_text=True)) assert data == response destroy_ctfd(app)
def post(self): data = request.form or request.get_json() challenge_type = data["type"] challenge_class = get_chal_class(challenge_type) challenge = challenge_class.create(request) response = challenge_class.read(challenge) return {"success": True, "data": response}
def admin_chal_detail(chalid): chal = Challenges.query.filter_by(id=chalid).first_or_404() chal_class = get_chal_class(chal.type) if request.method == 'POST': status, message = chal_class.attempt(chal, request) if status: return jsonify({'status': 1, 'message': message}) else: return jsonify({'status': 0, 'message': message}) elif request.method == 'GET': obj, data = chal_class.read(chal) tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=chal.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=chal.id).all() ] hints = [] for hint in Hints.query.filter_by(chal=chal.id).all(): hints.append({'id': hint.id, 'cost': hint.cost, 'hint': hint.hint}) data['tags'] = tags data['files'] = files data['hints'] = hints return jsonify(data)
def challenges_detail(challenge_id): challenges = dict( Challenges.query.with_entities(Challenges.id, Challenges.name).all()) challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() solves = Solves.query.filter_by(challenge_id=challenge.id).all() flags = Flags.query.filter_by(challenge_id=challenge.id).all() challenge_class = get_chal_class(challenge.type) with open( os.path.join(app.root_path, challenge_class.templates['update'].lstrip('/')), 'rb') as update: tpl = update.read() if six.PY3 and isinstance(tpl, binary_type): tpl = tpl.decode('utf-8') update_j2 = render_template_string(tpl, challenge=challenge) update_script = url_for( 'views.static_html', route=challenge_class.scripts['update'].lstrip('/')) return render_template('admin/challenges/challenge.html', update_template=update_j2, update_script=update_script, challenge=challenge, challenges=challenges, solves=solves, flags=flags)
def chal_view(chal_id): teamid = session.get('id') chal = Challenges.query.filter_by(id=chal_id).first_or_404() if chal.hidden: abort(404) chal_class = get_chal_class(chal.type) tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by(chal=chal.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=chal.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=teamid) ]) hints = [] for hint in Hints.query.filter_by(chal=chal.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({'id': hint.id, 'cost': hint.cost, 'hint': hint.hint}) else: hints.append({'id': hint.id, 'cost': hint.cost}) challenge, response = chal_class.read(challenge=chal) response['files'] = files response['tags'] = tags response['hints'] = hints db.session.close() return jsonify(response)
def chals(): db_category = db.session.query(Challenges.category,func.count(Challenges.category)).group_by(Challenges.category).order_by(Challenges.category).all() if(len(db_category) > 1): first_category = db_category[0][0] db_chals = Challenges.query.filter(or_(Challenges.hidden != True, Challenges.hidden == None)).filter(Challenges.category == first_category).order_by(Challenges.value).all() else: db_chals = []; response = {'game': [],'category':db_category} for chal in db_chals: tags = [tag.tag for tag in Tags.query.add_columns('tag').filter_by(chal=chal.id).all()] chal_type = get_chal_class(chal.type) response['game'].append({ 'id': chal.id, 'type': chal_type.name, 'name': chal.name, 'value': chal.value, 'category': chal.category, 'tags': tags, 'template': chal_type.templates['modal'], 'script': chal_type.scripts['modal'], }) db.session.close() return jsonify(response)
def get(self, level_id): challenges = (Challenges.query.filter( Challenges.level == level_id)).all() response = [] tag_schema = TagSchema(view="user", many=True) comp_schema = CompetenceSchema(view="user", many=True) for challenge in challenges: challenge_type = get_chal_class(challenge.type) response.append({ "id": challenge.id, "type": challenge_type.name, "name": challenge.name, "value": challenge.value, "category": challenge.category, "result": challenge.result, "level": challenge.level, "tags": tag_schema.dump(challenge.tags).data, "competences": comp_schema.dump(challenge.competences).data, "template": challenge_type.templates["view"], "script": challenge_type.scripts["view"], }) db.session.close() return {"success": True, "data": response}
def post(self): data = request.form or request.get_json() challenge_type = data['type'] challenge_class = get_chal_class(challenge_type) challenge = challenge_class.create(request) response = challenge_class.read(challenge) return {'success': True, 'data': response}
def challenges_detail(challenge_id): challenges = dict( Challenges.query.with_entities(Challenges.id, Challenges.name).all()) challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() solves = (Solves.query.filter_by(challenge_id=challenge.id).order_by( Solves.date.asc()).all()) flags = Flags.query.filter_by(challenge_id=challenge.id).all() try: challenge_class = get_chal_class(challenge.type) except KeyError: abort( 500, f"The underlying challenge type ({challenge.type}) is not installed. This challenge can not be loaded.", ) update_j2 = render_template( challenge_class.templates["update"].lstrip("/"), challenge=challenge) update_script = url_for( "views.static_html", route=challenge_class.scripts["update"].lstrip("/")) return render_template( "admin/challenges/challenge.html", update_template=update_j2, update_script=update_script, challenge=challenge, challenges=challenges, solves=solves, flags=flags, )
def get(self): # This can return None (unauth) if visibility is set to public user = get_current_user() challenges = (Challenges.query.filter( and_(Challenges.state != "hidden", Challenges.state != "locked")).order_by( Challenges.value).all()) if user: solve_ids = (Solves.query.with_entities( Solves.challenge_id).filter_by( account_id=user.account_id).order_by( Solves.challenge_id.asc()).all()) if is_admin(): pass else: if config.is_teams_mode() and get_current_team() is None: abort(403) else: solve_ids = [] response = [] tag_schema = TagSchema(view="user", many=True) for challenge in challenges: if challenge.requirements: requirements = challenge.requirements.get("prerequisites", []) anonymize = challenge.requirements.get("anonymize") if compare(requirements, solve_ids): pass else: if anonymize: response.append({ "id": challenge.id, "type": "hidden", "name": "???", "value": 0, "category": "???", "tags": [], "template": "", "script": "", }) # Fallthrough to continue continue challenge_type = get_chal_class(challenge.type) response.append({ "id": challenge.id, "type": challenge_type.name, "name": challenge.name, "value": challenge.value, "category": challenge.category, "tags": tag_schema.dump(challenge.tags).data, "template": challenge_type.templates["view"], "script": challenge_type.scripts["view"], }) db.session.close() return {"success": True, "data": response}
def get(self): # This can return None (unauth) if visibility is set to public user = get_current_user() challenges = Challenges.query.filter( and_(Challenges.state != 'hidden', Challenges.state != 'locked') ).order_by(Challenges.value).all() if user: 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([value for value, in solve_ids]) else: solve_ids = set() response = [] tag_schema = TagSchema(view='user', many=True) for challenge in challenges: if challenge.requirements: requirements = challenge.requirements.get('prerequisites', []) anonymize = challenge.requirements.get('anonymize') prereqs = set(requirements) if solve_ids >= prereqs: pass else: if anonymize: response.append({ 'id': challenge.id, 'type': 'hidden', 'name': '???', 'value': 0, 'category': '???', 'tags': [], 'template': '', 'script': '' }) # Fallthrough to continue continue challenge_type = get_chal_class(challenge.type) response.append({ 'id': challenge.id, 'type': challenge_type.name, 'name': challenge.name, 'value': challenge.value, 'category': challenge.category, 'tags': tag_schema.dump(challenge.tags).data, 'template': challenge_type.templates['view'], 'script': challenge_type.scripts['view'], }) db.session.close() return { 'success': True, 'data': response }
def admin_chal_detail(chalid): if request.method == 'POST': pass elif request.method == 'GET': chal = Challenges.query.filter_by(id=chalid).first_or_404() chal_class = get_chal_class(chal.type) obj, data = chal_class.read(chal) return jsonify(data)
def delete(self, challenge_id): challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() chal_class = get_chal_class(challenge.type) chal_class.delete(challenge) return { 'success': True, }
def admin_create_chal(): if request.method == 'POST': chal_type = request.form['chaltype'] chal_class = get_chal_class(chal_type) chal_class.create(request) return redirect(url_for('admin_challenges.admin_chals')) else: return render_template('admin/chals/create.html')
def chals_contest(contestid): contest = Contests.query.filter_by(id=contestid).first() if not utils.is_admin(): if not utils.ctftime(contest=contest): if utils.view_after_ctf(contest=contest): pass else: return redirect(url_for('views.static_html')) if utils.user_can_view_challenges(contest=contest) and ( utils.ctf_started(contest=contest) or utils.is_admin()): chals = Challenges.query.filter( and_(or_(Challenges.hidden != True, Challenges.hidden == None), Challenges.contestid == contestid)).order_by( Challenges.value).all() json = {'game': []} for x in chals: tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=x.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=x.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=session['id']) ]) hints = [] for hint in Hints.query.filter_by(chal=x.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({ 'id': hint.id, 'cost': hint.cost, 'hint': hint.hint }) else: hints.append({'id': hint.id, 'cost': hint.cost}) # hints = [{'id':hint.id, 'cost':hint.cost} for hint in Hints.query.filter_by(chal=x.id).all()] chal_type = get_chal_class(x.type) json['game'].append({ 'id': x.id, 'type': chal_type.name, 'name': x.name, 'value': x.value, 'description': x.description, 'category': x.category, 'files': files, 'tags': tags, 'hints': hints }) db.session.close() return jsonify(json) else: db.session.close() return redirect(url_for('auth.login', next='chals'))
def patch(self, challenge_id): challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() challenge_class = get_chal_class(challenge.type) challenge = challenge_class.update(challenge, request) response = challenge_class.read(challenge) return { 'success': True, 'data': response }
def chals(): if not utils.is_admin(): if not utils.ctftime(): if utils.view_after_ctf(): pass else: abort(403) if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()): teamid = session.get('id') chals = Challenges.query.filter( or_(Challenges.hidden != True, Challenges.hidden == None)).order_by(Challenges.value).all() json = {'game': []} for x in chals: tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=x.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=x.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=teamid) ]) hints = [] for hint in Hints.query.filter_by(chal=x.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({ 'id': hint.id, 'cost': hint.cost, 'hint': hint.hint }) else: hints.append({'id': hint.id, 'cost': hint.cost}) chal_type = get_chal_class(x.type) json['game'].append({ 'id': x.id, 'type': chal_type.name, 'name': x.name, 'value': x.value, 'description': x.description, 'category': x.category, 'files': files, 'tags': tags, 'hints': hints, 'template': chal_type.templates['modal'], 'script': chal_type.scripts['modal'], }) db.session.close() return jsonify(json) else: db.session.close() abort(403)
def chal_view_linearunlocked(chal_id): teamid = session.get('id') chal = Challenges.query.filter_by(id=chal_id).first_or_404() chal_class = get_chal_class(chal.type) # Get solved challenge ids solves = [] if utils.is_admin(): solves = Solves.query.filter_by(teamid=session['id']).all() elif utils.user_can_view_challenges(): if utils.authed(): solves = Solves.query\ .join(Teams, Solves.teamid == Teams.id)\ .filter(Solves.teamid == session['id'])\ .all() solve_ids = [] for solve in solves: solve_ids.append(solve.chalid) # Return nothing if there is at least one linear unlocking requirement not solved lu_entries = LinearUnlockingEntry.query.filter_by(chalid=chal.id).all() for lu_entry in lu_entries: if lu_entry.requires_chalid > -1 and lu_entry.requires_chalid not in solve_ids: return jsonify([]) tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=chal.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=chal.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=teamid) ]) hints = [] for hint in Hints.query.filter_by(chal=chal.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({ 'id': hint.id, 'cost': hint.cost, 'hint': hint.hint }) else: hints.append({'id': hint.id, 'cost': hint.cost}) challenge, response = chal_class.read(challenge=chal) response['files'] = files response['tags'] = tags response['hints'] = hints db.session.close() return jsonify(response)
def attempt_single(self, request, request_data, user, team, kpm, challenge): challenge_id = challenge.id if challenge.state == "hidden": return False, '' if challenge.state == "locked": return False, '' 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: return False, '' chal_class = get_chal_class(challenge.type) 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) 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=kpm, ) return True, message else: # The challenge plugin says the input is wrong if ctftime() or current_user.is_admin(): clear_standings() return False, message # Challenge already solved else: return False, ''
def test_challenges_model_access_plugin_class(): """ Test that the Challenges model can access its plugin class """ app = create_ctfd() with app.app_context(): from CTFd.plugins.challenges import get_chal_class chal = gen_challenge(app.db) assert chal.plugin_class == get_chal_class("standard") destroy_ctfd(app)
def get(self, challenge_id): if is_admin(): chal = Challenges.query.filter(Challenges.id == challenge_id).first_or_404() else: chal = Challenges.query.filter( Challenges.id == challenge_id, and_(Challenges.state != 'hidden', Challenges.state != 'locked') ).first_or_404() chal_class = get_chal_class(chal.type) tags = [ tag['value'] for tag in TagSchema( "user", many=True).dump( chal.tags).data] files = [f.location for f in chal.files] unlocked_hints = set() hints = [] if authed(): user = get_current_user() unlocked_hints = set([u.target for u in HintUnlocks.query.filter_by( type='hints', account_id=user.account_id)]) for hint in Hints.query.filter_by(challenge_id=chal.id).all(): if hint.id in unlocked_hints or ctf_ended(): hints.append({'id': hint.id, 'cost': hint.cost, 'content': hint.content}) else: hints.append({'id': hint.id, 'cost': hint.cost}) response = chal_class.read(challenge=chal) Model = get_model() if scores_visible() is True and accounts_visible() is True: solves = Solves.query\ .join(Model, Solves.account_id == Model.id)\ .filter(Solves.challenge_id == chal.id, Model.banned == False, Model.hidden == False)\ .count() response['solves'] = solves else: response['solves'] = None response['files'] = files response['tags'] = tags response['hints'] = hints db.session.close() return { 'success': True, 'data': response }
def admin_chal_detail(chalid): chal = Challenges.query.filter_by(id=chalid).first_or_404() chal_class = get_chal_class(chal.type) if request.method == 'POST': status, message = chal_class.attempt(chal, request) if status: return jsonify({'status': 1, 'message': message}) else: return jsonify({'status': 0, 'message': message}) elif request.method == 'GET': obj, data = chal_class.read(chal) return jsonify(data)
def load_challenges_csv(dict_reader): schema = ChallengeSchema() errors = [] for i, line in enumerate(dict_reader): # Throw away fields that we can't trust if provided _ = line.pop("id", None) _ = line.pop("requirements", None) flags = line.pop("flags", None) tags = line.pop("tags", None) hints = line.pop("hints", None) challenge_type = line.pop("type", "standard") # Load in custom type_data type_data = json.loads(line.pop("type_data", "{}") or "{}") line.update(type_data) response = schema.load(line) if response.errors: errors.append((i + 1, response.errors)) continue ChallengeClass = get_chal_class(challenge_type) challenge = ChallengeClass.challenge_model(**line) db.session.add(challenge) db.session.commit() if flags: flags = [flag.strip() for flag in flags.split(",")] for flag in flags: f = Flags(type="static", challenge_id=challenge.id, content=flag,) db.session.add(f) db.session.commit() if tags: tags = [tag.strip() for tag in tags.split(",")] for tag in tags: t = Tags(challenge_id=challenge.id, value=tag,) db.session.add(t) db.session.commit() if hints: hints = [hint.strip() for hint in hints.split(",")] for hint in hints: h = Hints(challenge_id=challenge.id, content=hint,) db.session.add(h) db.session.commit() if errors: return errors return True
def admin_create_chal(): if request.method == 'POST': chal_type = request.form['chaltype'] chal_class = get_chal_class(chal_type) chal_class.create(request) if not 'hidden' in request.form: t = datetime.datetime.fromtimestamp( time.time()).strftime('%c').split(' ')[3] broadcast(t + ": Thử thách " + request.form['category'] + " " + request.form['value'] + ": " + request.form['name'] + " đã được mở!") return redirect(url_for('admin_challenges.admin_chals')) else: return render_template('admin/chals/create.html')
def patch(self, challenge_id): data = request.get_json() # Load data through schema for validation but not for insertion schema = ChallengeSchema() response = schema.load(data) if response.errors: return {"success": False, "errors": response.errors}, 400 challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() challenge_class = get_chal_class(challenge.type) challenge = challenge_class.update(challenge, request) response = challenge_class.read(challenge) return {"success": True, "data": response}
def post(self): data = request.form or request.get_json() # Load data through schema for validation but not for insertion schema = ChallengeSchema() response = schema.load(data) if response.errors: return {"success": False, "errors": response.errors}, 400 challenge_type = data["type"] challenge_class = get_chal_class(challenge_type) challenge = challenge_class.create(request) response = challenge_class.read(challenge) return {"success": True, "data": response}
def load_challenges_csv(dict_reader): for line in dict_reader: flags = line.pop("flags", None) tags = line.pop("tags", None) hints = line.pop("hints", None) challenge_type = line.pop("type", "standard") # Load in custom type_data type_data = json.loads(line.pop("type_data", "{}") or "{}") line.update(type_data) ChallengeClass = get_chal_class(challenge_type) challenge = ChallengeClass.challenge_model(**line) db.session.add(challenge) db.session.commit() if flags: flags = [flag.strip() for flag in flags.split(",")] for flag in flags: f = Flags( type="static", challenge_id=challenge.id, content=flag, ) db.session.add(f) db.session.commit() if tags: tags = [tag.strip() for tag in tags.split(",")] for tag in tags: t = Tags( challenge_id=challenge.id, value=tag, ) db.session.add(t) db.session.commit() if hints: hints = [hint.strip() for hint in hints.split(",")] for hint in hints: h = Hints( challenge_id=challenge.id, content=hint, ) db.session.add(h) db.session.commit() return True
def chals(): if not utils.is_admin(): if not utils.ctftime(): if utils.view_after_ctf(): pass else: return redirect(url_for('views.static_html')) if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()): chals = Challenges.query.filter(or_(Challenges.hidden != True, Challenges.hidden == None)).order_by(Challenges.value).all() json = {'game': []} for x in chals: tags = [tag.tag for tag in Tags.query.add_columns('tag').filter_by(chal=x.id).all()] files = [str(f.location) for f in Files.query.filter_by(chal=x.id).all()] unlocked_hints = set([u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=session['id'])]) hints = [] for hint in Hints.query.filter_by(chal=x.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({'id': hint.id, 'cost': hint.cost, 'hint': hint.hint}) else: hints.append({'id': hint.id, 'cost': hint.cost}) # hints = [{'id':hint.id, 'cost':hint.cost} for hint in Hints.query.filter_by(chal=x.id).all()] chal_type = get_chal_class(x.type) json['game'].append({ 'id': x.id, 'type': chal_type.name, 'name': x.name, 'value': x.value, 'description': x.description, 'category': x.category, 'files': files, 'tags': tags, 'hints': hints }) db.session.close() return jsonify(json) else: db.session.close() return redirect(url_for('auth.login', next='chals'))
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" })