def tracker(): if authed(): if not Tracking.query.filter_by(ip=ip2long(request.remote_addr)).first(): visit = Tracking(request.remote_addr, session['id']) db.session.add(visit) db.session.commit() db.session.close()
def topteams(count): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) try: count = int(count) except: count = 10 if count > 20 or count < 0: count = 10 json = {'scores':{}} standings = get_standings(count=count) for team in standings: solves = Solves.query.filter_by(teamid=team.teamid).all() awards = Awards.query.filter_by(teamid=team.teamid).all() json['scores'][team.name] = [] scores = [] for x in solves: json['scores'][team.name].append({ 'chal': x.chalid, 'team': x.teamid, 'value': x.chal.value, 'time': unix_time(x.date) }) for award in awards: json['scores'][team.name].append({ 'chal': None, 'team': award.teamid, 'value': award.value, 'time': unix_time(award.date) }) json['scores'][team.name] = sorted(json['scores'][team.name], key=lambda k: k['time']) return jsonify(json)
def scores(): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) score = db.func.sum(Challenges.value).label('score') scores = db.session.query(Solves.teamid.label('teamid'), Teams.name.label('name'), score, Solves.date.label('date')) \ .join(Teams) \ .join(Challenges) \ .filter(Teams.banned == None) \ .group_by(Solves.teamid) awards = db.session.query(Teams.id.label('teamid'), Teams.name.label('name'), db.func.sum(Awards.value).label('score'), Awards.date.label('date'))\ .filter(Teams.id==Awards.teamid)\ .group_by(Teams.id) results = union_all(scores, awards) standings = db.session.query(results.columns.teamid, results.columns.name, db.func.sum(results.columns.score).label('score'))\ .group_by(results.columns.teamid)\ .order_by(db.func.sum(results.columns.score).desc(), db.func.max(results.columns.date))\ .all() db.session.close() json = {'standings':[]} for i, x in enumerate(standings): json['standings'].append({'pos':i+1, 'id':x.teamid, 'team':x.name,'score':int(x.score)}) return jsonify(json)
def solves(teamid=None): solves = None awards = None if teamid is None: if is_admin(): solves = Solves.query.filter_by(teamid=session['id']).all() elif authed(): solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.teamid==session['id'], Teams.banned==None).all() 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': unix_time(solve.date) }) for award in awards: json['solves'].append({ 'chal': award.name, 'chalid': None, 'team': award.teamid, 'value': award.value, 'category': award.category, 'time': unix_time(award.date) }) json['solves'].sort(key=lambda k: k['time']) return jsonify(json)
def topteams(count): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) try: count = int(count) except: count = 10 if count > 20 or count < 0: count = 10 json = {'scores':{}} score = db.func.sum(Challenges.value).label('score') quickest = db.func.max(Solves.date).label('quickest') teams = db.session.query(Solves.teamid, Teams.name, score)\ .join(Teams)\ .join(Challenges)\ .filter(Teams.banned == None)\ .group_by(Solves.teamid).order_by(score.desc(), quickest)\ .limit(count) for team in teams: solves = Solves.query.filter_by(teamid=team.teamid).all() json['scores'][team.name] = [] for x in solves: json['scores'][team.name].append({ 'id': x.teamid, 'chal': x.chalid, 'team': x.teamid, 'value': x.chal.value, 'time': unix_time(x.date) }) return jsonify(json)
def scores(): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) standings = get_standings() json = {'standings':[]} for i, x in enumerate(standings): json['standings'].append({'pos':i+1, 'id':x.teamid, 'team':x.name,'score':int(x.score)}) return jsonify(json)
def logout(): if authed(): session.clear() try: session.regenerate() except: pass return redirect('/')
def confirm_user(data=None): if not utils.get_config('verify_emails'): # If the CTF doesn't care about confirming email addresses then redierct to challenges return redirect(url_for('challenges.challenges_view')) # User is confirming email account if data and request.method == "GET": try: s = Signer(app.config['SECRET_KEY']) email = s.unsign(urllib.unquote_plus(data.decode('base64'))) except BadSignature: return render_template('confirm.html', errors=['Your confirmation link seems wrong']) except: return render_template('confirm.html', errors=['Your link appears broken, please try again.']) team = Teams.query.filter_by(email=email).first_or_404() team.verified = True db.session.commit() logger = logging.getLogger('regs') logger.warn("[{0}] {1} confirmed {2}".format(time.strftime("%m/%d/%Y %X"), team.name.encode('utf-8'), team.email.encode('utf-8'))) db.session.close() if utils.authed(): return redirect(url_for('challenges.challenges_view')) return redirect(url_for('auth.login')) # User is trying to start or restart the confirmation flow if not utils.authed(): return redirect(url_for('auth.login')) team = Teams.query.filter_by(id=session['id']).first_or_404() if data is None: if request.method == "POST": # User wants to resend their confirmation email if team.verified: return redirect(url_for('views.profile')) else: utils.verify_email(team.email) return render_template('confirm.html', team=team, infos=['Your confirmation email has been resent!']) elif request.method == "GET": # User has been directed to the confirm page team = Teams.query.filter_by(id=session['id']).first_or_404() if team.verified: # If user is already verified, redirect to their profile return redirect(url_for('views.profile')) return render_template('confirm.html', team=team)
def profile(): if authed(): if request.method == "POST": errors = [] name = request.form.get('name') email = request.form.get('email') website = request.form.get('website') affiliation = request.form.get('affiliation') country = request.form.get('country') names = Teams.query.filter_by(name=name).first() emails = Teams.query.filter_by(email=email).first() valid_email = re.match("[^@]+@[^@]+\.[^@]+", email) name_len = len(request.form['name']) == 0 if not bcrypt_sha256.verify(request.form.get('confirm').strip(), names.password): errors.append("Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if names and name!=session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if name_len: errors.append('Pick a longer team name') if not validate_url(website): errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() team.name = name team.email = email if 'password' in request.form.keys() and not len(request.form['password']) == 0: team.password = bcrypt_sha256.encrypt(request.form.get('password')) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect('/profile') else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country) else: return redirect('/login')
def scoreboard_view(): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) score = db.func.sum(Challenges.value).label('score') quickest = db.func.max(Solves.date).label('quickest') teams = db.session.query(Solves.teamid, Teams.name, score)\ .join(Teams)\ .join(Challenges)\ .filter(Teams.banned == None)\ .group_by(Solves.teamid).order_by(score.desc(), quickest) db.session.close() return render_template('scoreboard.html', teams=teams)
def topteams(count): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) try: count = int(count) except: count = 10 if count > 20 or count < 0: count = 10 json = {'scores':{}} score = db.func.sum(Challenges.value).label('score') scores = db.session.query(Solves.teamid.label('teamid'), Teams.name.label('name'), score, Solves.date.label('date')) \ .join(Teams) \ .join(Challenges) \ .filter(Teams.banned == None) \ .group_by(Solves.teamid) awards = db.session.query(Teams.id.label('teamid'), Teams.name.label('name'), db.func.sum(Awards.value).label('score'), Awards.date.label('date')) \ .filter(Teams.id == Awards.teamid) \ .group_by(Teams.id) results = union_all(scores, awards) standings = db.session.query(results.columns.teamid, results.columns.name, db.func.sum(results.columns.score).label('score')) \ .group_by(results.columns.teamid) \ .order_by(db.func.sum(results.columns.score).desc(), db.func.max(results.columns.date)) \ .limit(count).all() for team in standings: solves = Solves.query.filter_by(teamid=team.teamid).all() awards = Awards.query.filter_by(teamid=team.teamid).all() json['scores'][team.name] = [] scores = [] for x in solves: json['scores'][team.name].append({ 'chal': x.chalid, 'team': x.teamid, 'value': x.chal.value, 'time': unix_time(x.date) }) for award in awards: json['scores'][team.name].append({ 'chal': None, 'team': award.teamid, 'value': award.value, 'time': unix_time(award.date) }) json['scores'][team.name] = sorted(json['scores'][team.name], key=lambda k: k['time']) return jsonify(json)
def chal(chalid): if not ctftime(): return redirect("/") if authed(): 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) if get_kpm(session["id"]) > 10: wrong = WrongKeys(session["id"], chalid, request.form["key"]) db.session.add(wrong) db.session.commit() db.session.close() logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data)) return "3" # Submitting too fast solves = Solves.query.filter_by(teamid=session["id"], chalid=chalid).first() if not solves: keys = Keys.query.filter_by(chal=chalid).all() key = request.form["key"].strip().lower() for x in keys: if x.key_type == 0: # static key if x.flag.strip().lower() == key: solve = Solves(chalid=chalid, teamid=session["id"], ip=request.remote_addr) db.session.add(solve) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data)) return "1" # key was correct elif x.key_type == 1: # regex res = re.match(str(x), key, re.IGNORECASE) if res and res.group() == key: solve = Solves(chalid=chalid, teamid=session["id"], ip=request.remote_addr) db.session.add(solve) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data)) return "1" # key was correct wrong = WrongKeys(session["id"], chalid, request.form["key"]) db.session.add(wrong) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data)) return "0" # key was wrong else: logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data)) return "2" # challenge was already solved else: return "-1"
def solves(teamid=None): if teamid is None: if authed(): solves = Solves.query.filter_by(teamid=session['id']).all() else: abort(401) else: solves = Solves.query.filter_by(teamid=teamid).all() db.session.close() json = {'solves':[]} for x in solves: json['solves'].append({ 'chal':x.chal.name, 'chalid':x.chalid,'team':x.teamid, 'value': x.chal.value, 'category':x.chal.category, 'time':unix_time(x.date)}) return jsonify(json)
def chal(chalid): if not ctftime(): return redirect('/challenges') if authed(): fails = WrongKeys.query.filter_by(team=session['id'],chal=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) if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0: return "4" #too many tries on this challenge if get_kpm(session['id']) > 10: wrong = WrongKeys(session['id'], chalid, request.form['key']) db.session.add(wrong) db.session.commit() db.session.close() logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data)) return "3" # Submitting too fast solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() if not solves: keys = Keys.query.filter_by(chal=chalid).all() key = request.form['key'].strip().lower() for x in keys: if x.key_type == 0: #static key if x.flag.strip().lower() == key: solve = Solves(chalid=chalid, teamid=session['id'], ip=request.remote_addr, flag=key) db.session.add(solve) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data)) return "1" # key was correct elif x.key_type == 1: #regex res = re.match(str(x), key, re.IGNORECASE) if res and res.group() == key: solve = Solves(chalid=chalid, teamid=session['id'], ip=request.remote_addr, flag=key) db.session.add(solve) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data)) return "1" # key was correct wrong = WrongKeys(session['id'], chalid, request.form['key']) db.session.add(wrong) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data)) return '0' # key was wrong else: logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data)) return "2" # challenge was already solved else: return "-1"
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(teamid=None): if teamid is None: if is_admin(): solves = Solves.query.filter_by(teamid=session['id']).all() elif authed(): solves = Solves.query.join(Teams, Solves.teamid == Teams.id).filter(Solves.teamid==session['id'], Teams.banned==None).all() else: return redirect(url_for('auth.login', next='solves')) else: solves = Solves.query.filter_by(teamid=teamid).all() db.session.close() json = {'solves':[]} for x in solves: json['solves'].append({ 'chal':x.chal.name, 'chalid':x.chalid,'team':x.teamid, 'value': x.chal.value, 'category':x.chal.category, 'time':unix_time(x.date)}) return jsonify(json)
def scores(): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) score = db.func.sum(Challenges.value).label('score') quickest = db.func.max(Solves.date).label('quickest') teams = db.session.query(Solves.teamid, Teams.name, score)\ .join(Teams)\ .join(Challenges)\ .filter(Teams.banned == None)\ .group_by(Solves.teamid).order_by(score.desc(), quickest) db.session.close() json = {'standings':[]} for i, x in enumerate(teams): json['standings'].append({'pos':i+1, 'id':x.teamid, 'team':x.name,'score':int(x.score)}) return jsonify(json)
def team(teamid): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) user = Teams.query.filter_by(id=teamid).first() solves = Solves.query.filter_by(teamid=teamid).all() score = user.score() place = user.place() db.session.close() if request.method == 'GET': return render_template('team.html', solves=solves, team=user, score=score, place=place) elif request.method == 'POST': json = {'solves':[]} for x in solves: json['solves'].append({'id':x.id, 'chal':x.chalid, 'team':x.teamid}) return jsonify(json)
def submit_flag(): result = {} cur_round = get_current_round() if not ctftime(): return redirect('/challenges') if authed(): submitkey = str(request.form['flag'].strip().lower()) teamid = session['id'] request_ip = request.remote_addr querykey = Keys.query.filter_by(flag=submitkey, round=cur_round).first() if querykey: # Right flag if Gameboxs.query.filter_by(id=querykey.gameboxid).first().teamid == teamid: # Self flag result['status'] = 2 result['msg'] = 'Self flag' else: querysolve = Solves.query.filter_by(keyid=querykey.id, teamid=teamid).first() if querysolve: # Already submitted result['status'] = 2 result['msg'] = 'Already submitted' else: # Right flag newsolve = Solves(querykey.id, teamid, querykey.chalid ,querykey.round, request_ip) db.session.add(newsolve) db.session.commit() result['status'] = 1 result['msg'] = 'Right Flag' else: # Wrong flag result['status'] = 0 result['msg'] = 'Wrong Flag' else: result['status'] = -1 result['msg'] = 'Login First' db.session.close() return jsonify(result)
def confirm_user(data=None): if not get_config('verify_emails'): return redirect(url_for('challenges.challenges_view')) if data and request.method == "GET": ## User is confirming email account try: s = Signer(app.config['SECRET_KEY']) email = s.unsign(data.decode('base64')) except BadSignature: return render_template('confirm.html', errors=['Your confirmation link seems wrong']) team = Teams.query.filter_by(email=email).first() team.verified = True db.session.commit() db.session.close() if authed(): return redirect(url_for('challenges.challenges_view')) return redirect(url_for('auth.login')) if not data and request.method == "GET": ## User has been directed to the confirm page because his account is not verified team = Teams.query.filter_by(id=session['id']).first() if team.verified: return redirect(url_for('views.profile')) return render_template('confirm.html', team=team)
def solves(teamid=None): if teamid is None: if authed(): solves = Solves.query.filter_by(teamid=session["id"]).all() else: abort(401) else: solves = Solves.query.filter_by(teamid=teamid).all() db.session.close() json = {"solves": []} for x in solves: json["solves"].append( { "id": x.id, "chal": x.chal.name, "chalid": x.chalid, "team": x.teamid, "value": x.chal.value, "category": x.chal.category, "time": unix_time(x.date), } ) return jsonify(json)
def scoreboard_view(): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) score = db.func.sum(Challenges.value).label('score') scores = db.session.query(Solves.teamid.label('teamid'), Teams.name.label('name'), score, Solves.date.label('date')) \ .join(Teams) \ .join(Challenges) \ .filter(Teams.banned == None) \ .group_by(Solves.teamid) awards = db.session.query(Teams.id.label('teamid'), Teams.name.label('name'), db.func.sum(Awards.value).label('score'), Awards.date.label('date')) \ .filter(Teams.id == Awards.teamid) \ .group_by(Teams.id) results = union_all(scores, awards) standings = db.session.query(results.columns.teamid, results.columns.name, db.func.sum(results.columns.score).label('score')) \ .group_by(results.columns.teamid) \ .order_by(db.func.sum(results.columns.score).desc(), db.func.max(results.columns.date)) \ .all() db.session.close() return render_template('scoreboard.html', teams=standings)
def team(teamid): if utils.get_config('view_scoreboard_if_utils.authed') and not utils.authed(): return redirect(url_for('auth.login', next=request.path)) errors = [] freeze = utils.get_config('freeze') user = Teams.query.filter_by(id=teamid).first_or_404() solves = Solves.query.filter_by(teamid=teamid) awards = Awards.query.filter_by(teamid=teamid) place = user.place() score = user.score() 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() if utils.hide_scores() and teamid != session.get('id'): errors.append('Scores are currently hidden') if errors: return render_template('team.html', team=user, errors=errors) if request.method == 'GET': return render_template('team.html', solves=solves, awards=awards, team=user, score=score, place=place, score_frozen=utils.is_scoreboard_frozen()) elif request.method == 'POST': json = {'solves': []} for x in solves: json['solves'].append({'id': x.id, 'chal': x.chalid, 'team': x.teamid}) return jsonify(json)
def profile(): if authed(): if request.method == "POST": errors = [] name = request.form.get("name") email = request.form.get("email") website = request.form.get("website") affiliation = request.form.get("affiliation") country = request.form.get("country") user = Teams.query.filter_by(id=session["id"]).first() if not get_config("prevent_name_change"): names = Teams.query.filter_by(name=name).first() name_len = len(request.form["name"]) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = re.match("[^@]+@[^@]+\.[^@]+", email) if ("password" in request.form.keys() and not len(request.form["password"]) == 0) and ( not bcrypt_sha256.verify(request.form.get("confirm").strip(), user.password) ): errors.append("Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if not get_config("prevent_name_change") and names and name != session["username"]: errors.append("That team name is already taken") if emails and emails.id != session["id"]: errors.append("That email has already been used") if not get_config("prevent_name_change") and name_len: errors.append("Pick a longer team name") if website.strip() and not validate_url(website): errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template( "profile.html", name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors, ) else: team = Teams.query.filter_by(id=session["id"]).first() if not get_config("prevent_name_change"): team.name = name team.email = email session["username"] = team.name if "password" in request.form.keys() and not len(request.form["password"]) == 0: team.password = bcrypt_sha256.encrypt(request.form.get("password")) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect("/profile") else: user = Teams.query.filter_by(id=session["id"]).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = get_config("prevent_name_change") return render_template( "profile.html", name=name, email=email, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, ) else: return redirect("/login")
def chal(chalid): if not ctftime(): return redirect(url_for('challenges.challenges_view')) if authed(): fails = WrongKeys.query.filter_by(teamid=session['id'], chalid=chalid).count() logger = logging.getLogger('keys') data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), request.form['key'].encode('utf-8'), get_kpm(session['id'])) print("[{0}] {1} submitted {2} with kpm {3}".format(*data)) # Hit max attempts if fails >= int(get_config("max_tries")) and int(get_config("max_tries")) > 0: return "4" #too many tries on this challenge # Anti-bruteforce / submitting keys too quickly if get_kpm(session['id']) > 10: wrong = WrongKeys(session['id'], chalid, request.form['key']) db.session.add(wrong) db.session.commit() db.session.close() logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data)) return "3" # Submitting too fast solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: chal = Challenges.query.filter_by(id=chalid).first() key = str(request.form['key'].strip().lower()) keys = json.loads(chal.flags) for x in keys: if x['type'] == 0: #static key print(x['flag'], key.strip().lower()) if x['flag'] and x['flag'].strip().lower() == key.strip().lower(): solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key) db.session.add(solve) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data)) return "1" # key was correct elif x['type'] == 1: #regex res = re.match(str(x['flag']), key, re.IGNORECASE) if res and res.group() == key: solve = Solves(chalid=chalid, teamid=session['id'], ip=get_ip(), flag=key) db.session.add(solve) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data)) return "1" # key was correct wrong = WrongKeys(session['id'], chalid, request.form['key']) db.session.add(wrong) db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [WRONG]".format(*data)) return '0' # key was wrong # Challenge already solved else: logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data)) return "2" # challenge was already solved else: return "-1"
def profile(): if authed(): if request.method == "POST": errors = [] name = request.form.get('name') email = request.form.get('email') schoolCode = request.form.get('schoolCode') website = request.form.get('website') affiliation = request.form.get('affiliation') country = request.form.get('country') user = Teams.query.filter_by(id=session['id']).first() if not get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = re.match("[^@]+@[^@]+\.[^@]+", email) if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append("Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if not get_config('prevent_name_change') and names and name!=session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if not get_config('prevent_name_change') and name_len: errors.append('Pick a longer team name') if website.strip() and not validate_url(website): errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, schoolCode=schoolCode, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if not get_config('prevent_name_change'): team.name = name if team.email != email.lower(): team.email = email.lower() if get_config('verify_emails'): team.verified = False session['username'] = team.name if 'password' in request.form.keys() and not len(request.form['password']) == 0: team.password = bcrypt_sha256.encrypt(request.form.get('password')) team.schoolCode = schoolCode team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email schoolCode = user.schoolCode website = user.website affiliation = user.affiliation country = user.country prevent_name_change = get_config('prevent_name_change') confirm_email = get_config('verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, schoolCode=schoolCode, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login'))
def profile(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name').strip() country = request.form.get('country').strip() user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append("当前密码不正确") if not utils.get_config( 'prevent_name_change' ) and names and name != session['username']: errors.append('That team name is already taken') if not utils.get_config('prevent_name_change') and name_len: errors.append('Pick a longer team name') if len(errors) > 0: return render_template('profile.html', name=name, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if team.name != name: if not utils.get_config('prevent_name_change'): team.name = name session['username'] = team.name if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name website = user.website affiliation = user.affiliation country = user.country prevent_name_change = utils.get_config('prevent_name_change') return render_template('profile.html', name=name, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change) else: return redirect(url_for('auth.login'))
def profile(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name') email = request.form.get('email') website = request.form.get('website') affiliation = request.form.get('affiliation') country = request.form.get('country') user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = re.match( r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", email) if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append("Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if not utils.get_config( 'prevent_name_change' ) and names and name != session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if not utils.get_config('prevent_name_change') and name_len: errors.append('Pick a longer team name') if website.strip() and not utils.validate_url(website): errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): team.name = name if team.email != email.lower(): team.email = email.lower() if utils.get_config('verify_emails'): team.verified = False session['username'] = team.name if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = utils.get_config('prevent_name_change') confirm_email = utils.get_config( 'verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login'))
def new_reset_pass(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name').strip() email = request.form.get('email').strip() website = request.form.get('website').strip() affiliation = request.form.get('affiliation').strip() country = request.form.get('country').strip() user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = utils.check_email_format(email) if utils.check_email_format(name) is True: errors.append('Team name cannot be an email address') if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append( "Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if not utils.get_config( 'prevent_name_change' ) and names and name != session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if not utils.get_config('prevent_name_change') and name_len: errors.append('Pick a longer team name') if website.strip() and not utils.validate_url(website): errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if team.name != name: if not utils.get_config('prevent_name_change'): team.name = name session['username'] = team.name if team.email != email.lower(): team.email = email.lower() if utils.get_config('verify_emails'): team.verified = False if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) message = json.dumps(["change", name, password]) channel.basic_publish( exchange='', routing_key='shell_queue', body=message, properties=pika.BasicProperties( delivery_mode=2, # make message persistent )) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = utils.get_config('prevent_name_change') confirm_email = utils.get_config( 'verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login'))
def anonchal(): if utils.ctf_paused(): return jsonify({ 'status': 3, 'message': '{} is paused'.format(utils.ctf_name()) }) if utils.is_admin() or (utils.authed() and utils.is_verified() and (utils.ctf_started() or utils.view_after_ctf())): team = Teams.query.filter_by(id=session['id']).first() provided_key = request.form['key'].strip() logger = logging.getLogger('keys') data = (time.strftime("%m/%d/%Y %X"), session['username'].encode('utf-8'), provided_key.encode('utf-8'), utils.get_kpm(session['id'])) # Anti-bruteforce / KPM is based on last failed key (not logged), so sleep instead. time.sleep(2) # Find challenge by looking up the provided flag key = db.session.query(Keys).\ join(AnonymousChallenge).\ filter(Keys.flag == provided_key).first() if not key: logger.info( "[{0}] {1} submitted {2} with kpm {3} [WRONG]".format( *data)) return jsonify({'status': 0, 'message': 'Invalid Flag'}) chal = AnonymousChallenge.query.filter_by(id=key.chal).first() chal_class = get_chal_class(chal.type) solves = Solves.query.filter_by(teamid=session['id'], chalid=chal.id).first() # If team hasn't solved challenge yet, save the solve if not solves: # We already know the flag is correct because we checked it already 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': "Correct"}) # Otherwise, raise an error else: logger.info( "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format( *data)) 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 csrf(): if authed() and request.method == "POST": if session['nonce'] != request.form.get('nonce'): abort(403)
def shell_view(): if not authed(): return redirect(url_for('auth.login', next=request.path)) return render_template('shell.html', root=request.script_root)
def chal(chalid): if utils.ctf_paused(): return jsonify({ 'status': 3, 'message': '{} is paused'.format(utils.ctf_name()) }) 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)) chal = Challenges.query.filter_by(id=chalid).first_or_404() if chal.hidden: abort(404) chal_class = get_chal_class(chal.type) # Anti-bruteforce / submitting keys too quickly if utils.get_kpm(session['id']) > 10: if utils.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."}) solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: 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" }) 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)) filter = Challenges.query.filter_by(id = chalid).all() chalname = filter[0].name teams = Teams.query.filter_by(id=session['id']) chal_category = filter[0].category chal_value = filter[0].value t = datetime.datetime.fromtimestamp(time.time()).strftime('%c').split(' ')[3] broadcast(t + ": Đội " + teams[0].name + " đã giải được "+ chal_category + str(chal_value) + ": " + chalname) 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 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 utils.ctf_paused(): return jsonify({ 'status': 3, 'message': '{} is paused'.format(utils.ctf_name()) }) 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)) chal = Challenges.query.filter_by(id=chalid).first_or_404() if chal.hidden: abort(404) chal_class = get_chal_class(chal.type) # Anti-bruteforce / submitting keys too quickly if utils.get_kpm(session['id']) > 10: if utils.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." }) solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: 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" }) 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 isinstance( message, int): # This means someone submitted others' flag if utils.ctftime() or utils.is_admin(): chal_class.penalty( team1=team, team2=Teams.query.filter_by(id=message).first(), chal=chal, request=request) logger.info( "[{0}] {1} submitted {2} with kpm {3} [CHEAT]".format( *data)) message = "Incorrect(Warning!You are trying to submit other team's flag)" else: 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 scoreboard_view(): if get_config('view_scoreboard_if_authed') and not authed(): return redirect(url_for('auth.login', next=request.path)) standings = get_standings() return render_template('scoreboard.html', teams=standings)
def restart(): if authed(): session.clear() return redirect('/home')
def inject_user(): if authed(): return dict(session) return dict()
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" })
def team_management(): if authed(): user = Users.query.filter_by(id=session.get('id')).first_or_404() if user.teamid: ## Already has team s = Signer(app.config['SECRET_KEY']) team = Teams.query.filter_by(id=user.teamid).first_or_404() users = Users.query.filter_by(teamid=user.teamid) secret = urllib.quote_plus(s.sign(str(team.id)).encode('base64')) if request.method == "POST": errors = [] if team.captain == user.id: website = request.form.get('website') affiliation = request.form.get('affiliation') country = request.form.get('country') if website.strip() and not validate_url(website): errors.append("That doesn't look like a valid URL") team.website = website team.affiliation = affiliation team.country = country else: errors.append( 'Only team captains can change this information.') if errors: return render_template('view_team.html', team=team, users=users, secret=secret, errors=errors) db.session.commit() db.session.close() return redirect(url_for('views.team_management')) else: captain = False if team.captain == user.id: captain = True return render_template('view_team.html', team=team, users=users, secret=secret, captain=captain) else: ## Needs a team if request.method == "POST": name = request.form.get('name') captain = session.get('id') team = Teams.query.filter_by(name=name).first() errors = [] if team: errors.append('That team name is already taken') t = Teams(name, captain) if errors: return render_template('create_team.html', errors=errors, team=t) db.session.add(t) db.session.flush() user.teamid = t.id db.session.commit() db.session.close() return redirect(url_for('views.team_management')) else: return render_template('create_team.html') else: return redirect(url_for('auth.login'))
def logout(): if authed(): session.clear() return redirect('/')
def profile(): if utils.authed(): if request.method == "POST": errors = [] name = request.form.get('name').strip() email = request.form.get('email').strip() affiliation = request.form.get('grade').strip() website = request.form.get('major').strip() country = request.form.get('college').strip() user = Teams.query.filter_by(id=session['id']).first() if not utils.get_config('prevent_name_change'): names = Teams.query.filter_by(name=name).first() name_len = len(request.form['name']) == 0 emails = Teams.query.filter_by(email=email).first() valid_email = utils.check_email_format(email) if utils.check_email_format(name) is True: errors.append('用户名不能和邮箱一样') if ('password' in request.form.keys() and not len(request.form['password']) == 0) and \ (not bcrypt_sha256.verify(request.form.get('confirm').strip(), user.password)): errors.append("旧密码错误") if not valid_email: errors.append("邮箱格式不对") if not utils.get_config( 'prevent_name_change' ) and names and name != session['username']: errors.append('用户名已被其他用户使用') if emails and emails.id != session['id']: errors.append('邮箱已被其他用户使用') if not utils.get_config('prevent_name_change') and name_len: errors.append('用户名长度不够') #if website.strip() and not utils.validate_url(website): #errors.append("That doesn't look like a valid URL") if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() if team.name != name: if not utils.get_config('prevent_name_change'): team.name = name session['username'] = team.name if team.email != email.lower(): team.email = email.lower() if utils.get_config('verify_emails'): team.verified = False if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect(url_for('views.profile')) else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country prevent_name_change = utils.get_config('prevent_name_change') confirm_email = utils.get_config( 'verify_emails') and not user.verified return render_template('profile.html', name=name, email=email, major=website, grade=affiliation, college=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email) else: return redirect(url_for('auth.login'))
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(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.solve(chal, provided_key) if status: # The challenge plugin says the input is right # TODO: if auth flag success, add gamble point if utils.ctftime(): score = chal.value original_score = chal.original_value solved_problem = Solves.query.filter_by( chalid=chalid).count() solved_team = Solves.query.filter_by(chalid=chalid).all() challenge = Challenges.query.filter_by(id=chalid).first() solve = Solves(teamid=session['id'], chalid=chalid, ip=utils.get_ip(), flag=provided_key) gamble = Gamble(teamid=session['id'], chalid=chalid, value=original_score) gamble.name = "gamble point" # result = (original_score * ((solved_problem * 10) / 100)) result = (original_score * (1 / 10)) failed = False try: if solved_problem == 0: challenge.original_value = score if solved_problem >= 1: challenge.value -= result db.session.add(challenge) db.session.commit() db.session.add(solve) db.session.commit() db.session.add(gamble) db.session.commit() db.session.close() except Exception as e: db.session.rollback() db.session.flush() failed = True 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(): wrong = WrongKeys(teamid=session['id'], chalid=chalid, ip=utils.get_ip(), 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' 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 logout(): if utils.authed(): session.clear() return redirect(url_for('views.index'))
def logout(): if utils.authed(): session.clear() return redirect(url_for('views.static_html'))
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) 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 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 profile(): if authed(): if request.method == "POST": errors = [] name = request.form.get('name') email = request.form.get('email') website = request.form.get('website') affiliation = request.form.get('affiliation') country = request.form.get('country') names = Teams.query.filter_by(name=name).first() emails = Teams.query.filter_by(email=email).first() valid_email = re.match("[^@]+@[^@]+\.[^@]+", email) name_len = len(request.form['name']) == 0 if not bcrypt_sha256.verify( request.form.get('confirm').strip(), names.password): errors.append( "Your old password doesn't match what we have.") if not valid_email: errors.append("That email doesn't look right") if names and name != session['username']: errors.append('That team name is already taken') if emails and emails.id != session['id']: errors.append('That email has already been used') if name_len: errors.append('Pick a longer team name') if len(errors) > 0: return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country, errors=errors) else: team = Teams.query.filter_by(id=session['id']).first() team.name = name team.email = email if 'password' in request.form.keys() and not len( request.form['password']) == 0: team.password = bcrypt_sha256.encrypt( request.form.get('password')) team.website = website team.affiliation = affiliation team.country = country db.session.commit() db.session.close() return redirect('/profile') else: user = Teams.query.filter_by(id=session['id']).first() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country return render_template('profile.html', name=name, email=email, website=website, affiliation=affiliation, country=country) else: return redirect('/login')
def chal(chalid): if utils.ctf_paused(): return jsonify({ 'status': 3, 'message': get_tip('IS_PAUSED').format(utils.ctf_name()) }) 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)) chal = Challenges.query.filter_by(id=chalid).first_or_404() if chal.hidden: abort(404) chal_class = get_chal_class(chal.type) # Anti-bruteforce / submitting keys too quickly if utils.get_kpm(session['id']) > 10: if utils.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': get_tip('SUBMIT_TOO_FAST') }) solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: 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': get_tip('ZERO_CAN_TRY') }) 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': get_tip('MANY_CAN_TRY').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': get_tip('HAVE_SOLVE')}) else: return jsonify({'status': -1, 'message': get_tip('MUST_LOGGED')})
def chal_custom(chalid): if utils.ctf_paused(): return jsonify({ 'status': 3, 'message': '{} is paused'.format(utils.ctf_name()) }) 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)) chal = Challenges.query.filter_by(id=chalid).first_or_404() if chal.hidden: abort(404) chal_class = get_chal_class(chal.type) # Anti-bruteforce / submitting keys too quickly if utils.get_kpm(session['id']) > 10: if utils.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." }) solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: 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" }) 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)) if "SmartCity" in str(chal_class): print(session['id']) smart_color = SmartCityTeam.query.filter_by( teamId=session['id']).first().color smart_buildingId = SmartCityChallenge.query.filter_by( id=chalid).first().buildingId smart_soundId = SmartCityChallenge.query.filter_by( id=chalid).first().soundId smart_image = SmartCityTeam.query.filter_by( teamId=session['id']).first().image b = smart_buildingId.split('\', \'') b[0] = b[0][2:] b[-1] = b[-1][:-2] print("Team with color " + str(smart_color) + " and image " + str(smart_image) + " solved challenege with buildingId " + str(b) + "and sound " + smart_soundId) smartSession = SmartTable(b, smart_color, smart_image, smart_soundId) createSmartCityTableSession2(smartSession) 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 confirm_user(data=None): if not utils.get_config('verify_emails'): # If the CTF doesn't care about confirming email addresses then redierct to challenges return redirect(url_for('challenges.challenges_view')) logger = logging.getLogger('regs') # User is confirming email account if data and request.method == "GET": try: s = TimedSerializer(app.config['SECRET_KEY']) email = s.loads(utils.base64decode(data, urldecode=True), max_age=1800) except BadTimeSignature: return render_template( 'confirm.html', errors=['Your confirmation link has expired']) except (BadSignature, TypeError, base64.binascii.Error): return render_template( 'confirm.html', errors=['Your confirmation token is invalid']) team = Teams.query.filter_by(email=email).first_or_404() team.verified = True db.session.commit() logger.warn( "[{date}] {ip} - {username} confirmed their account".format( date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=team.name.encode('utf-8'), email=team.email.encode('utf-8'))) db.session.close() if utils.authed(): return redirect(url_for('challenges.challenges_view')) return redirect(url_for('auth.login')) # User is trying to start or restart the confirmation flow if not utils.authed(): return redirect(url_for('auth.login')) team = Teams.query.filter_by(id=session['id']).first_or_404() if data is None: if request.method == "POST": # User wants to resend their confirmation email if team.verified: return redirect(url_for('views.profile')) else: utils.verify_email(team.email) logger.warn( "[{date}] {ip} - {username} initiated a confirmation email resend" .format(date=time.strftime("%m/%d/%Y %X"), ip=utils.get_ip(), username=team.name.encode('utf-8'), email=team.email.encode('utf-8'))) return render_template( 'confirm.html', team=team, infos=['Your confirmation email has been resent!']) elif request.method == "GET": # User has been directed to the confirm page team = Teams.query.filter_by(id=session['id']).first_or_404() if team.verified: # If user is already verified, redirect to their profile return redirect(url_for('views.profile')) return render_template('confirm.html', team=team)
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_or_404() 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 solves_private_endpoint(): if not utils.authed(): return jsonify({'solves': []}) solves_public_endpoint(session['id'])
def logout(): if authed(): session.clear() return redirect(url_for('views.static_html'))
def chal_contest(contestid, chalid): contest = Contests.query.filter_by(id=contestid).first() if utils.ctf_ended( contest=contest) and not utils.view_after_ctf(contest=contest): return redirect(url_for('challenges.challenges_view')) if not utils.user_can_view_challenges(contest=contest): return redirect(url_for('contests.contests_view')) if utils.authed() and utils.is_verified() and utils.is_participated( contest=contest) and (utils.ctf_started(contest=contest) or utils.view_after_ctf(contest=contest)): 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() 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.solve(chal, provided_key) if status: # The challenge plugin says the input is right if utils.ctftime(contest=contest): solve = Solves(teamid=session['id'], chalid=chalid, ip=utils.get_ip(), flag=provided_key, contestid=contestid) db.session.add(solve) db.session.commit() db.session.close() else: message += '. But time is up' if solves: message += ". You already solved this" logger.info( "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format( *data)) # return '2' # challenge was already solved return jsonify({'status': 2, 'message': message}) 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(contest=contest): wrong = WrongKeys(teamid=session['id'], chalid=chalid, ip=utils.get_ip(), flag=provided_key, contestid=contestid) db.session.add(wrong) db.session.commit() db.session.close() else: message += '. But time is up' if solves: message += ". You already solved this" logger.info( "{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format( *data)) # return '2' # challenge was already solved return jsonify({'status': 2, 'message': message}) 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}) else: return jsonify({ 'status': -1, 'message': "You must be logged in to solve a challenge" })