def challenges_view(): errors = [] start = utils.get_config('start') or 0 end = utils.get_config('end') or 0 if not utils.is_admin(): # User is not an admin if not utils.ctftime(): # It is not CTF time if utils.view_after_ctf(): # But we are allowed to view after the CTF ends pass else: # We are NOT allowed to view after the CTF ends if utils.get_config('start') and not utils.ctf_started(): errors.append('{} has not started yet'.format(utils.ctf_name())) if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf(): errors.append('{} has ended'.format(utils.ctf_name())) return render_template('chals.html', errors=errors, start=int(start), end=int(end)) if utils.get_config('verify_emails') and not utils.is_verified(): # User is not confirmed return redirect(url_for('auth.confirm_user')) if utils.user_can_view_challenges(): # Do we allow unauthenticated users? if utils.get_config('start') and not utils.ctf_started(): errors.append('{} has not started yet'.format(utils.ctf_name())) if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf(): errors.append('{} has ended'.format(utils.ctf_name())) return render_template('chals.html', errors=errors, start=int(start), end=int(end)) else: return redirect(url_for('auth.login', next='challenges'))
def attempts(): if not utils.user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) chals = Challenges.query.add_columns('id').all() json = {'maxattempts': []} for chal, chalid in chals: fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count() if fails >= int(utils.get_config("max_tries")) and int(utils.get_config("max_tries")) > 0: json['maxattempts'].append({'chalid': chalid}) return jsonify(json)
def who_solved(chalid): if not utils.user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) json = {'teams': []} if utils.hide_scores(): return jsonify(json) solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.chalid == chalid, Teams.banned == False).order_by(Solves.date.asc()) for solve in solves: json['teams'].append({'id': solve.team.id, 'name': solve.team.name, 'date': solve.date}) return jsonify(json)
def solves(teamid=None): solves = None awards = None if teamid is None: 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'], Teams.banned == False).all() else: return jsonify({'solves': []}) else: return redirect(url_for('auth.login', next='solves')) else: solves = Solves.query.filter_by(teamid=teamid) awards = Awards.query.filter_by(teamid=teamid) freeze = utils.get_config('freeze') if freeze: freeze = utils.unix_time_to_utc(freeze) if teamid != session.get('id'): solves = solves.filter(Solves.date < freeze) awards = awards.filter(Awards.date < freeze) solves = solves.all() awards = awards.all() db.session.close() json = {'solves': []} for solve in solves: json['solves'].append({ 'chal': solve.chal.name, 'chalid': solve.chalid, 'team': solve.teamid, 'value': solve.chal.value, 'category': solve.chal.category, 'time': utils.unix_time(solve.date) }) if awards: for award in awards: json['solves'].append({ 'chal': award.name, 'chalid': None, 'team': award.teamid, 'value': award.value, 'category': award.category or "Award", 'time': utils.unix_time(award.date) }) json['solves'].sort(key=lambda k: k['time']) return jsonify(json)
def solves_per_chal(): if not utils.user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) solves_sub = db.session.query(Solves.chalid, db.func.count(Solves.chalid).label('solves')).join(Teams, Solves.teamid == Teams.id).filter(Teams.banned == False).group_by(Solves.chalid).subquery() solves = db.session.query(solves_sub.columns.chalid, solves_sub.columns.solves, Challenges.name) \ .join(Challenges, solves_sub.columns.chalid == Challenges.id).all() json = {} if utils.hide_scores(): for chal, count, name in solves: json[chal] = -1 else: for chal, count, name in solves: json[chal] = count db.session.close() return jsonify(json)
def who_solved(chalid): if not user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) json = {'teams': []} if hide_scores(): return jsonify(json) solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter( Solves.chalid == chalid, Teams.banned == False).order_by(Solves.date.asc()) for solve in solves: json['teams'].append({ 'id': solve.team.id, 'name': solve.team.name, 'date': solve.date }) return jsonify(json)
def who_solved(chalid): if not user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) solves = Solves.query\ .join(Users, Solves.userid == Users.id)\ .join(Teams, Users.teamid == Teams.id) \ .with_entities(Teams.id, Teams.name.label('teamname'), Solves.date.label('date')) \ .filter(Solves.chalid == chalid, Users.banned == False)\ .order_by(Solves.date.asc()) json = {'teams': []} for solve in solves: json['teams'].append({ 'id': solve.id, 'name': solve.teamname, 'date': solve.date }) return jsonify(json)
def challenges_view(): infos = [] errors = [] start = utils.get_config('start') or 0 end = utils.get_config('end') or 0 if utils.ctf_paused(): infos.append('{} is paused'.format(utils.ctf_name())) if not utils.is_admin(): # User is not an admin if not utils.ctftime(): # It is not CTF time if utils.view_after_ctf( ): # But we are allowed to view after the CTF ends pass else: # We are NOT allowed to view after the CTF ends if utils.get_config('start') and not utils.ctf_started(): errors.append('{} has not started yet'.format( utils.ctf_name())) if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf(): errors.append('{} has ended'.format(utils.ctf_name())) return render_template('challenges.html', infos=infos, errors=errors, start=int(start), end=int(end)) if utils.get_config('verify_emails'): if utils.authed(): if utils.is_admin() is False and utils.is_verified( ) is False: # User is not confirmed return redirect(url_for('auth.confirm_user')) if utils.user_can_view_challenges(): # Do we allow unauthenticated users? if utils.get_config('start') and not utils.ctf_started(): errors.append('{} has not started yet'.format(utils.ctf_name())) if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf(): errors.append('{} has ended'.format(utils.ctf_name())) return render_template('challenges.html', infos=infos, errors=errors, start=int(start), end=int(end)) else: return redirect(url_for('auth.login', next='challenges'))
def challenges_view_contest(contest_slug): contest = Contests.query.filter_by(slug=contest_slug).first() errors = [] start = contest.starttime or 0 end = contest.endtime or 0 if not utils.is_admin(): # User is not an admin if not utils.ctftime(): # It is not CTF time if utils.view_after_ctf( ): # But we are allowed to view after the CTF ends pass else: # We are NOT allowed to view after the CTF ends if utils.ctf_started(contest=contest): errors.append('{} has not started yet'.format( contest.name)) if utils.ctf_ended( contest=contest) and not utils.view_after_ctf(): errors.append('{} has ended'.format(contest.name)) return render_template('chals.html', errors=errors, start=start, end=end) if utils.get_config('verify_emails') and not utils.is_verified( ): # User is not confirmed return redirect(url_for('auth.confirm_user')) if utils.user_can_view_challenges( contest=contest): # Do we allow unauthenticated users? if not utils.ctf_started(contest=contest): errors.append('{} has not started yet'.format(contest.name)) if utils.ctf_ended( contest=contest) and not utils.view_after_ctf(contest=contest): errors.append('{} has ended'.format(contest.name)) contest = Contests.query.filter_by(slug=contest_slug).first() contest_dict = vars(contest) contest_dict.pop('_sa_instance_state', None) return render_template('chals.html', errors=errors, start=start, end=end, contest=contest_dict) else: return redirect( url_for("contests.contest_participate", contest_slug=contest_slug))
def solves(teamid=None): solves = None awards = None if teamid is None: 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'], Teams.banned == False).all() else: return jsonify({'solves': []}) else: return redirect(url_for('auth.login', next='solves')) else: solves = Solves.query.filter_by(teamid=teamid).all() awards = Awards.query.filter_by(teamid=teamid).all() db.session.close() json = {'solves': []} for solve in solves: json['solves'].append({ 'chal': solve.chal.name, 'chalid': solve.chalid, 'team': solve.teamid, 'value': solve.chal.value, 'category': solve.chal.category, 'time': utils.unix_time(solve.date) }) if awards: for award in awards: json['solves'].append({ 'chal': award.name, 'chalid': None, 'team': award.teamid, 'value': award.value, 'category': award.category or "Award", 'time': utils.unix_time(award.date) }) json['solves'].sort(key=lambda k: k['time']) return jsonify(json)
def hash_crack_king_chal(chalid): if utils.dates.ctf_paused(): return jsonify({ 'status': 3, 'message': '{} is paused'.format(utils.config.ctf_name()) }) if utils.dates.ctf_ended() and not utils.dates.view_after_ctf(): abort(403) if not utils.user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) if (utils.user.authed() and utils.user.is_verified() and (utils.dates.ctf_started() or utils.dates.view_after_ctf())) or utils.user.is_admin(): team = Teams.query.filter_by(id=session['id']).first() chal = Challenges.query.filter_by(id=chalid).first_or_404() if chal.hidden: abort(404) chal_class = get_chal_class(chal.type) if chal_class is not HashCrack: abort(405) _, data = chal_class.read(chal) # Anti-bruteforce / submitting keys too quickly if utils.user.get_wrong_submissions_per_minute( utils.user.get_current_user()) > 10: if utils.dates.ctftime(): chal_class.fail(team=team, chal=chal, request=request) logger.warn( "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format( *data)) # return '3' # Submitting too fast return jsonify({ 'status': 3, 'message': "You're submitting keys too fast. Slow down." }) return jsonify(data)
def challenges_view(): errors = [] start = get_config('start') or 0 end = get_config('end') or 0 if not is_admin(): # User is not an admin if not ctftime(): # It is not CTF time if start > time.time( ): # We are NOT allowed to view after the CTF ends errors.append('{} challenges will be posted soon!'.format( ctf_name())) elif not view_after_ctf(): errors.append('{} has ended.'.format(ctf_name())) return render_template('chals.html', errors=errors, start=int(start), end=int(end)) if get_config('verify_emails' ) and not is_verified(): # User is not confirmed return redirect(url_for('auth.confirm_user')) if user_can_view_challenges(): # Do we allow unauthenticated users? if get_config('start') and not ctf_started(): errors.append('{} has not started yet'.format(ctf_name())) if (get_config('end') and ctf_ended()) and not view_after_ctf(): errors.append('{} has ended'.format(ctf_name())) if not is_on_team(): errors.append('You are not on a team!') return render_template('chals.html', errors=errors, start=int(start), end=int(end)) else: if not is_on_team(): errors.append( 'You must create or join a team before you can start playing') return render_template('chals.html', errors=errors, start=int(start), end=int(end)) return redirect(url_for('auth.login', next='challenges'))
def solves_per_chal(): if not utils.user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) solves_sub = db.session.query( Solves.chalid, db.func.count(Solves.chalid).label('solves')).join( Teams, Solves.teamid == Teams.id).filter(Teams.banned == False).group_by( Solves.chalid).subquery() solves = db.session.query(solves_sub.columns.chalid, solves_sub.columns.solves, Challenges.name) \ .join(Challenges, solves_sub.columns.chalid == Challenges.id).all() json = {} if utils.hide_scores(): for chal, count, name in solves: json[chal] = -1 else: for chal, count, name in solves: json[chal] = count db.session.close() return jsonify(json)
def solves_private(): solves = None awards = None 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() else: return jsonify({'solves': []}) else: return jsonify({'solves': []}) db.session.close() response = {'solves': []} for solve in solves: response['solves'].append({ 'chal': solve.chal.name, 'chalid': solve.chalid, 'team': solve.teamid, 'value': solve.chal.value, 'category': solve.chal.category, 'time': utils.unix_time(solve.date) }) if awards: for award in awards: response['solves'].append({ 'chal': award.name, 'chalid': None, 'team': award.teamid, 'value': award.value, 'category': award.category or "Award", 'time': utils.unix_time(award.date) }) response['solves'].sort(key=lambda k: k['time']) return jsonify(response)
def solves(teamid=None): if teamid is None: if is_admin() or user_can_view_challenges(): teamid = session['id'] else: return redirect(url_for('auth.login', next='solves')) teamid = int(teamid) user_solves = [] for solve, value in get_solves_and_value(is_admin=is_admin()): if solve.teamid == teamid: j = { 'team': solve.teamid, 'value': value, 'time': unix_time(solve.date), } if isinstance(solve, Solves) and solve.teamid == session['id']: mark = Marks.query.filter_by(teamid=session['id'], chalid=solve.chalid).first() if mark: j.update({'mark': mark.mark, 'feedback': mark.feedback}) else: j.update({'mark': None, 'feedback': None}) if isinstance(solve, Solves): j['chalid'] = solve.chalid j['chal'] = solve.chal.name j['category'] = solve.chal.category elif isinstance(solve, Awards): j['chalid'] = None j['chal'] = solve.name j['category'] = solve.category else: raise RuntimeError("Objects returned by get_solves_and_value " "should be Solves or Awards") user_solves.append(j) user_solves = sorted(user_solves, key=operator.itemgetter('time')) return jsonify({'solves': user_solves})
def solves_per_chal(): if not utils.user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) chals = Challenges.query\ .filter(or_(Challenges.hidden != True, Challenges.hidden == None))\ .order_by(Challenges.value)\ .all() solves_sub = db.session.query( Solves.chalid, db.func.count(Solves.chalid).label('solves') )\ .join(Teams, Solves.teamid == Teams.id) \ .filter(Teams.banned == False) \ .group_by(Solves.chalid).subquery() solves = db.session.query( solves_sub.columns.chalid, solves_sub.columns.solves, Challenges.name ) \ .join(Challenges, solves_sub.columns.chalid == Challenges.id).all() data = {} if utils.hide_scores(): for chal, count, name in solves: data[chal] = -1 for c in chals: if c.id not in data: data[c.id] = -1 else: for chal, count, name in solves: data[chal] = count for c in chals: if c.id not in data: data[c.id] = 0 db.session.close() return jsonify(data)
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 competitions(): 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()): competitions = Competitions.query.all() json = {'competitions': []} for x in competitions: json['competitions'].append({ 'id': x.id, 'title': x.title, 'description': x.description }) db.session.close() return jsonify(json) else: db.session.close() abort(403)
def chals(): if not is_admin(): if not ctftime(): if view_after_ctf(): pass else: return redirect(url_for('views.static_html')) if user_can_view_challenges() and (ctf_started() or is_admin()): chals = Challenges.query.filter( or_(Challenges.hidden != True, Challenges.hidden == None)).add_columns( 'id', 'name', 'value', 'description', 'category').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[1]).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=x.id).all() ] json['game'].append({ 'id': x[1], 'name': x[2], 'value': x[3], 'description': x[4], 'category': x[5], 'files': files, 'tags': tags }) db.session.close() return jsonify(json) else: db.session.close() return redirect(url_for('auth.login', next='chals'))
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()): 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() abort(403)
def chal(chalid): if utils.ctf_ended() and not utils.view_after_ctf(): abort(403) if not utils.user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) if (utils.authed() and utils.is_verified() and (utils.ctf_started() or utils.view_after_ctf())) or utils.is_admin(): team = Teams.query.filter_by(id=session['id']).first() fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count() logger = logging.getLogger('keys') data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), utils.get_kpm(session['id'])) print("[{0}] {1} submitted {2} with kpm {3}".format(*data)) # Anti-bruteforce / submitting keys too quickly if utils.get_kpm(session['id']) > 10: if utils.ctftime(): wrong = WrongKeys(teamid=session['id'], chalid=chalid, ip=utils.get_ip(), flag=request.form['key'].strip()) db.session.add(wrong) db.session.commit() db.session.close() logger.warn( "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format( *data)) # return '3' # Submitting too fast return jsonify({ 'status': 3, 'message': "You're submitting keys too fast. Slow down." }) solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: chal = Challenges.query.filter_by(id=chalid).first_or_404() provided_key = request.form['key'].strip() saved_keys = Keys.query.filter_by(chal=chal.id).all() # Hit max attempts max_tries = chal.max_attempts if max_tries and fails >= max_tries > 0: return jsonify({ 'status': 0, 'message': "You have 0 tries remaining" }) chal_class = get_chal_class(chal.type) status, message = chal_class.attempt(chal, request) if status: # The challenge plugin says the input is right if utils.ctftime() or utils.is_admin(): chal_class.solve(team=team, chal=chal, request=request) logger.info( "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format( *data)) return jsonify({'status': 1, 'message': message}) else: # The challenge plugin says the input is wrong if utils.ctftime() or utils.is_admin(): chal_class.fail(team=team, chal=chal, request=request) logger.info( "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format( *data)) # return '0' # key was wrong if max_tries: attempts_left = max_tries - fails - 1 # Off by one since fails has changed since it was gotten tries_str = 'tries' if attempts_left == 1: tries_str = 'try' if message[ -1] not in '!().;?[]\{\}': # Add a punctuation mark if there isn't one message = message + '.' return jsonify({ 'status': 0, 'message': '{} You have {} {} remaining.'.format( message, attempts_left, tries_str) }) else: return jsonify({'status': 0, 'message': message}) # Challenge already solved else: logger.info( "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format( *data)) # return '2' # challenge was already solved return jsonify({'status': 2, 'message': 'You already solved this'}) else: return jsonify({ 'status': -1, 'message': "You must be logged in to solve a challenge" })
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" })
def solves(teamid=None): solves = None awards = None if teamid is None: 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'], Teams.banned == False).all() else: return jsonify({'solves': []}) else: return redirect(url_for('auth.login', next='solves')) else: if utils.authed() and session['id'] == teamid: solves = Solves.query.filter_by(teamid=teamid) awards = Awards.query.filter_by(teamid=teamid) freeze = utils.get_config('freeze') if freeze: freeze = utils.unix_time_to_utc(freeze) if teamid != session.get('id'): solves = solves.filter(Solves.date < freeze) awards = awards.filter(Awards.date < freeze) solves = solves.all() awards = awards.all() elif utils.hide_scores(): # Use empty values to hide scores solves = [] awards = [] else: solves = Solves.query.filter_by(teamid=teamid) awards = Awards.query.filter_by(teamid=teamid) freeze = utils.get_config('freeze') if freeze: freeze = utils.unix_time_to_utc(freeze) if teamid != session.get('id'): solves = solves.filter(Solves.date < freeze) awards = awards.filter(Awards.date < freeze) solves = solves.all() awards = awards.all() db.session.close() json = {'solves': []} for solve in solves: json['solves'].append({ 'chal': solve.chal.name, 'chalid': solve.chalid, 'team': solve.teamid, 'value': solve.chal.value, 'category': solve.chal.category, 'time': utils.unix_time(solve.date) }) if awards: for award in awards: json['solves'].append({ 'chal': award.name, 'chalid': None, 'team': award.teamid, 'value': award.value, 'category': award.category or "Award", 'time': utils.unix_time(award.date) }) json['solves'].sort(key=lambda k: k['time']) return jsonify(json)
def chals(): if not utils.is_admin(): if not utils.ctftime(): if utils.view_after_ctf(): pass elif utils.ctf_paused(): abort(make_response('{} paused'.format(utils.ctf_name()), 503)) else: abort( make_response( 'These are not the challenges you are looking for', 403)) if utils.get_config('verify_emails'): if utils.authed(): if utils.is_admin() is False and utils.is_verified( ) is False: # User is not confirmed abort(403) if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()): teamid = session.get('id') chals = Challenges.query.filter( or_(Challenges.hidden != True, Challenges.hidden == None)).order_by(Challenges.value).all() json = {'game': []} for x in chals: tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=x.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=x.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=teamid) ]) hints = [] for hint in Hints.query.filter_by(chal=x.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({ 'id': hint.id, 'cost': hint.cost, 'hint': hint.hint }) else: hints.append({'id': hint.id, 'cost': hint.cost}) chal_type = get_chal_class(x.type) json['game'].append({ 'id': x.id, 'type': chal_type.name, 'name': x.name, 'value': x.value, 'description': x.description, 'category': x.category, 'files': files, 'tags': tags, 'hints': hints, 'template': chal_type.templates['modal'], 'script': chal_type.scripts['modal'], }) db.session.close() return jsonify(json) else: db.session.close() abort(403)
def comp_challenges(compid): if not utils.is_admin(): if not utils.ctftime(): if utils.view_after_ctf(): pass else: abort(403) if utils.get_config('verify_emails'): if utils.authed(): if utils.is_admin() is False and utils.is_verified( ) is False: # User is not confirmed abort(403) if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()): teamid = session.get('id') comp = Competitions.query.filter(Competitions.id == compid).first() if comp is None: abort(403) if comp.startTime > datetime.datetime.utcnow(): abort(403) #chals=comp.chals json = { 'competition': { 'id': comp.id, 'title': comp.title, 'description': comp.description, 'startTime': comp.startTime, 'endTime': comp.endTime }, 'game': [] } for x in comp.chals: chal = Challenges.query.filter(Challenges.id == x.chalid).first() if chal is None: abort(502) tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter( Tags.chal == chal.id).all() ] files = [ str(f.location) for f in Files.query.filter(Files.chal == chal.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter( Unlocks.model == 'hints', Unlocks.teamid == teamid) ]) hints = [] for hint in Hints.query.filter(Hints.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}) chal_type = get_chal_class(chal.type) json['game'].append({ 'id': chal.id, 'type': chal_type.name, 'name': chal.name, 'value': chal.value, 'description': chal.description, 'category': chal.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 challenges_view(compid): infos = [] errors = [] start = utils.get_config('start') or 0 end = utils.get_config('end') or 0 comp = Competitions.query.filter(Competitions.id == compid).first() if utils.ctf_paused(): infos.append('{} is paused'.format(utils.ctf_name())) if not utils.is_admin(): # User is not an admin if not utils.ctftime(): # It is not CTF time if utils.view_after_ctf( ): # But we are allowed to view after the CTF ends pass else: # We are NOT allowed to view after the CTF ends if utils.get_config('start') and not utils.ctf_started(): errors.append('{} has not started yet'.format( utils.ctf_name())) if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf(): errors.append('{} has ended'.format(utils.ctf_name())) if comp is None: errors.append('no such competition') start = False if comp.startTime > datetime.datetime.utcnow(): errors = append('{} 尚未开始,敬请期待'.format(comp.title)) start = False return render_template('comp_challenges.html', infos=infos, errors=errors, start=int(start), end=int(end), comp=comp) if utils.get_config('verify_emails'): if utils.authed(): if utils.is_admin() is False and utils.is_verified( ) is False: # User is not confirmed return redirect(url_for('auth.confirm_user')) if utils.user_can_view_challenges(): # Do we allow unauthenticated users? if utils.get_config('start') and not utils.ctf_started(): errors.append('{} has not started yet'.format(utils.ctf_name())) if (utils.get_config('end') and utils.ctf_ended()) and not utils.view_after_ctf(): errors.append('{} has ended'.format(utils.ctf_name())) if comp is None: errors.append('no such competition') start = False if comp.startTime > datetime.datetime.utcnow(): errors.append('{} 尚未开始,敬请期待'.format(comp.title)) start = False return render_template('comp_challenges.html', infos=infos, errors=errors, start=int(start), end=int(end), comp=comp) else: return redirect(url_for('auth.login', next=request.path))
def chals_linearunlocked(): # 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) db_chals = Challenges.query.filter( or_(Challenges.hidden != True, Challenges.hidden == None)).order_by(Challenges.value).all() response = {'game': []} linearunlock_games = {} other_games = [] for chal in db_chals: # Skip if is linear locked and should be hidden lu_id = -1 lu_name = "__NOT_IN_ANY_CHAIN__" lu_position = -1 is_hidden = False lu_entries = LinearUnlockingEntry.query.filter_by( chalid=chal.id).all() for lu_entry in lu_entries: # Initialize lu_id if possible, used for sorting the challenges later if lu_id == -1: lu_model = LinearUnlockingModel.query.filter_by( id=lu_entry.linearunlockid).first() lu_id = lu_model.id lu_name = lu_model.name lu_position = lu_entry.position if lu_entry.requires_chalid > -1 and lu_entry.requires_chalid not in solve_ids: lu_model = LinearUnlockingModel.query.filter_by( id=lu_entry.linearunlockid).first() if lu_model.is_hidden: is_hidden = True break if is_hidden: continue tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=chal.id).all() ] chal_type = get_chal_class(chal.type) game = { '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'], # Add more info for chain presentation 'chainid': lu_id, 'chainname': lu_name, 'chainposition': lu_position, } if lu_id > -1: if lu_id not in linearunlock_games: linearunlock_games[lu_id] = [] linearunlock_games[lu_id].append(game) else: other_games.append(game) # Add all linear unlock chain challenges in sorted order first for lu_id, lu_chain_games in linearunlock_games.iteritems(): lu_chain_games.sort(key=lambda x: x['chainposition']) response['game'].extend(lu_chain_games) # Then add all other games that are not in any chain response['game'].extend(other_games) db.session.close() return jsonify(response)
def chal(chalid): if ctf_ended() and not view_after_ctf(): return redirect(url_for('challenges.challenges_view')) if not user_can_view_challenges(): return redirect(url_for('auth.login', next=request.path)) if authed() and is_verified() and (ctf_started() or view_after_ctf()): fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count() logger = logging.getLogger('keys') data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id'])) print("[{0}] {1} submitted {2} with kpm {3}".format(*data)) # Anti-bruteforce / submitting keys too quickly if get_kpm(session['id']) > 10: if ctftime(): wrong = WrongKeys(session['id'], chalid, request.form['key']) db.session.add(wrong) db.session.commit() db.session.close() logger.warn( "[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format( *data)) # return "3" # Submitting too fast return jsonify({ 'status': '3', 'message': "You're submitting keys too fast. Slow down." }) solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: chal = Challenges.query.filter_by(id=chalid).first() key = unicode(request.form['key'].strip().lower()) keys = json.loads(chal.flags) # Hit max attempts max_tries = int(get_config("max_tries")) if fails >= max_tries > 0: return jsonify({ 'status': '0', 'message': "You have 0 tries remaining" }) for x in keys: if x['type'] == 0: #static key print(x['flag'], key.strip().lower()) if x['flag'] and x['flag'].strip().lower() == key.strip( ).lower(): if ctftime(): solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key) db.session.add(solve) db.session.commit() db.session.close() logger.info( "[{0}] {1} submitted {2} with kpm {3} [CORRECT]". format(*data)) # return "1" # key was correct return jsonify({'status': '1', 'message': 'Correct'}) elif x['type'] == 1: #regex res = re.match(x['flag'], key, re.IGNORECASE) if res and res.group() == key: if ctftime(): solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key) db.session.add(solve) db.session.commit() db.session.close() logger.info( "[{0}] {1} submitted {2} with kpm {3} [CORRECT]". format(*data)) # return "1" # key was correct return jsonify({'status': '1', 'message': 'Correct'}) if ctftime(): wrong = WrongKeys(session['id'], chalid, request.form['key']) db.session.add(wrong) db.session.commit() db.session.close() logger.info( "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data)) # return '0' # key was wrong if max_tries: attempts_left = max_tries - fails tries_str = 'tries' if attempts_left == 1: tries_str = 'try' return jsonify({ 'status': '0', 'message': 'Incorrect. You have {} {} remaining.'.format( attempts_left, tries_str) }) else: return jsonify({'status': '0', 'message': 'Incorrect'}) # Challenge already solved else: logger.info( "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format( *data)) # return "2" # challenge was already solved return jsonify({ 'status': '2', 'message': 'You already solved this' }) else: return "-1"
def chals(): if not utils.is_admin(): if not utils.ctftime(): if utils.view_after_ctf(): pass else: abort(403) if utils.get_config('verify_emails'): if utils.authed(): if utils.is_admin() is False and utils.is_verified( ) is False: # User is not confirmed abort(403) if utils.user_can_view_challenges() and (utils.ctf_started() or utils.is_admin()): teamid = session.get('id') chals = Challenges.query.filter( or_(Challenges.hidden != True, Challenges.hidden == None)).order_by( Challenges.value).all() json = {'game': []} for x in chals: tags = [ tag.tag for tag in Tags.query.add_columns('tag').filter_by( chal=x.id).all() ] files = [ str(f.location) for f in Files.query.filter_by(chal=x.id).all() ] unlocked_hints = set([ u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=teamid) ]) hints = [] for hint in Hints.query.filter_by(chal=x.id).all(): if hint.id in unlocked_hints or utils.ctf_ended(): hints.append({ 'id': hint.id, 'cost': hint.cost, 'hint': hint.hint }) else: hints.append({'id': hint.id, 'cost': hint.cost}) chal_type = get_chal_class(x.type) if chal_type == CommunityChallenge: owner_id = CommunityChallengeModel.query.filter( CommunityChallengeModel.id == x.id).first().owner else: owner_id = 1 owner = Teams.query.filter(Teams.id == owner_id).first().name own = (owner_id == session['id']) chal_data = { '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, 'owner': owner, 'own': own, 'template': chal_type.templates['modal'], 'script': chal_type.scripts['modal'] } if own == True: chal_data.update({'nonce': session.get('nonce')}) json['game'].append(chal_data) db.session.close() return jsonify(json) else: db.session.close() abort(403)
def chals(chalid=None): 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()): json = {'game': [], 'nonce': ''} if chalid is None: chals = Challenges.query.order_by(Challenges.value).all() 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() ] chal_type = get_chal_class(x.type) if x.hidden: json['game'].append({ 'id': x.id, 'name': x.name, 'value': x.value, 'category': x.category, 'hidden': True }) else: file_data = [] for i in range(len(files)): file_data.append( [str(files[i]).split('/')[1], str(files[i])]) json['game'].append({ 'id': x.id, 'type': chal_type.name, 'name': x.name, 'value': x.value, 'description': x.description, 'category': x.category, 'files': file_data, 'tags': tags, 'hint': x.hint }) json["nonce"] = session["nonce"] else: chal = Challenges.query.filter_by(id=chalid).all()[0] if chal is None or chal.hidden: json = {"locked": True} else: 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() ] chal_type = get_chal_class(chal.type) json = { 'id': chal.id, 'type': chal_type.name, 'name': chal.name, 'value': chal.value, 'description': chal.description, 'category': chal.category, 'files': files, 'tags': tags, 'hint': chal.hint } 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 = unicode(request.form['key'].strip()) saved_keys = Keys.query.filter_by(chal=chal.id).all() # Hit max attempts max_tries = chal.max_attempts if max_tries and fails >= max_tries > 0: return jsonify({ 'status': '0', 'message': "You have 0 tries remaining" }) chal_class = get_chal_class(chal.type) if chal_class.solve(chal, provided_key): if utils.ctftime(): solve = Solves(chalid=chalid, teamid=session['id'], ip=utils.get_ip(), flag=provided_key) db.session.add(solve) db.session.commit() db.session.close() logger.info( "[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format( *data)) return jsonify({'status': '1', 'message': 'Correct'}) if utils.ctftime(): wrong = WrongKeys(teamid=session['id'], chalid=chalid, flag=provided_key) db.session.add(wrong) db.session.commit() db.session.close() logger.info( "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data)) # return '0' # key was wrong if max_tries: attempts_left = max_tries - fails - 1 ## Off by one since fails has changed since it was gotten tries_str = 'tries' if attempts_left == 1: tries_str = 'try' return jsonify({ 'status': '0', 'message': 'Incorrect. You have {} {} remaining.'.format( attempts_left, tries_str) }) else: return jsonify({'status': '0', 'message': 'Incorrect'}) # Challenge already solved else: logger.info( "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format( *data)) # return '2' # challenge was already solved return jsonify({ 'status': '2', 'message': 'You already solved this' }) else: return jsonify({ 'status': '-1', 'message': "You must be logged in to solve a challenge" })