def private(): infos = get_infos() errors = get_errors() user = get_current_user() if config.is_scoreboard_frozen(): infos.append("Scoreboard has been frozen") return render_template( "users/private.html", user=user, account=user.account, infos=infos, errors=errors, )
def get_user_challenge_by_id(challenge_id): if is_admin(): return Challenges.query.filter_by(id=challenge_id).first_or_404() else: user = get_current_user() return (Challenges.query.outerjoin( Solves, Challenges.id == Solves.challenge_id).filter( and_( Challenges.id == challenge_id, Challenges.state != "hidden", Challenges.state != "locked", or_( Challenges.is_secret == False, Solves.account_id == user.account_id, ), ), ).first_or_404())
def get(self): user = get_current_user() fails = user.get_fails(admin=True) view = "user" if not is_admin() else "admin" response = SubmissionSchema(view=view, many=True).dump(fails) if response.errors: return {"success": False, "errors": response.errors}, 400 if is_admin(): data = response.data else: data = [] count = len(response.data) return {"success": True, "data": data, "meta": {"count": count}}
def patch(self): user = get_current_user() data = request.get_json() schema = UserSchema(view="self", instance=user, partial=True) response = schema.load(data) if response.errors: return {"success": False, "errors": response.errors}, 400 db.session.commit() response = schema.dump(response.data) db.session.close() clear_standings() return {"success": True, "data": response.data}
def join(): if request.method == 'GET': return render_template('teams/join_team.html') if request.method == 'POST': teamname = request.form.get('name') passphrase = request.form.get('password', '').strip() team = Teams.query.filter_by(name=teamname).first() user = get_current_user() if team and verify_password(passphrase, team.password): user.team_id = team.id db.session.commit() return redirect(url_for('challenges.listing')) else: errors = ['That information is incorrect'] return render_template('teams/join_team.html', errors=errors)
def private(): user = get_current_user() solves = user.get_solves() awards = user.get_awards() place = user.place score = user.score return render_template('users/private.html', solves=solves, awards=awards, user=user, score=score, place=place, score_frozen=config.is_scoreboard_frozen())
def status(): try: cid = request.args['challenge_id'] uid = get_current_user().id now = time.time() con = models.query_container(cid, uid) # 检查该用户是否真的部署了container if con: left_time = str(int(3600 - (now - con.start_time))) # 返回剩余时间 con_url = con.url return 'Success ' + con_url + ' ' + left_time else: return 'No' except: return 'Error'
def view_target(): if authed(): user = get_current_user() if not login_info.has_key(user.id): randomvalue = uuid4().hex[0:16] url_prefix = randomvalue[:8] login_info[user.id] = url % (url_prefix) random_port_internal = random.randint(1000, 9999) command = create_container % (random_port_internal, login_info[ user.id], login_info[user.id], random_port_internal) system(command) print(command) return_data = return_info % (login_info[user.id]) return render_template('page.html', content=return_data) else: return redirect(url_for('auth.login'))
def wrapper(*args, **kwargs): result = f(*args, **kwargs) if not ctftime(): return result if isinstance(result, JSONMixin): data = result.json if (isinstance(data, dict) and data.get("success") == True and isinstance(data.get("data"), dict) and data.get("data").get("status") == "correct"): if request.content_type != "application/json": request_data = request.form else: request_data = request.get_json() challenge_id = request_data.get("challenge_id") challenge = Challenges.query.filter_by( id=challenge_id).first_or_404() solvers = Solves.query.filter_by(challenge_id=challenge.id) solvers = solvers.filter(Solves.user.has(hidden=False)) num_solves = solvers.count() limit = app.config["DISCORD_WEBHOOK_FIRST_SOLVES"] if limit and num_solves > int(limit): return result webhook = DiscordWebhook( url=app.config["DISCORD_WEBHOOK_URL"]) user = get_current_user() format_args = { "user": sanitize(user.name), "challenge": sanitize(challenge.name), "solves": num_solves, "fsolves": ordinal(num_solves), "category": sanitize(challenge.category), "points": challenge.value, } message = app.config["DISCORD_WEBHOOK_MESSAGE"].format( **format_args) embed = DiscordEmbed(description=message) webhook.add_embed(embed) webhook.execute() return result
def join(): infos = get_infos() errors = get_errors() if request.method == "GET": team_size_limit = get_config("team_size", default=0) if team_size_limit: plural = "" if team_size_limit == 1 else "s" infos.append( "Команды могут содержать не больше {limit} участников".format( limit=team_size_limit, plural=plural)) return render_template("teams/join_team.html", infos=infos, errors=errors) if request.method == "POST": teamname = request.form.get("name") passphrase = request.form.get("password", "").strip() team = Teams.query.filter_by(name=teamname).first() if team and verify_password(passphrase, team.password): team_size_limit = get_config("team_size", default=0) if team_size_limit and len(team.members) >= team_size_limit: errors.append( "Команда {name} уже достигла лимит в {limit} участников". format(name=team.name, limit=team_size_limit)) return render_template("teams/join_team.html", infos=infos, errors=errors) user = get_current_user() user.team_id = team.id db.session.commit() if len(team.members) == 1: team.captain_id = user.id db.session.commit() clear_user_session(user_id=user.id) clear_team_session(team_id=team.id) return redirect(url_for("challenges.listing")) else: errors.append("Такая информация некорректна") return render_template("teams/join_team.html", infos=infos, errors=errors)
def view_quiz_finish(quiz): user_quest = Quiz.query.filter_by(quiz=quiz, user=get_current_user().id).all()[-1] quiz_data = get_quiz_data_or_404(quiz) user_progress = json.loads(user_quest.data) answered_question_count = len(user_progress['questions']) if answered_question_count < quiz_data['questionsToAskCount']: return redirect('/quiz/{}'.format(quiz)) quiz_data = get_quiz_data_or_404(quiz) challenge_quiz = ChallengeQuiz.query.filter_by(quiz=quiz).first() challenge = Challenges.query.filter_by( id=challenge_quiz.challenge).first() user_quest_json_data = json.loads(user_quest.data) correct_answer = 0 for question in user_quest_json_data['questions']: original_question = list( filter(lambda i: i['content'] == question, quiz_data['questions']))[0] if type(original_question['correctAnswer']) == int: original = {original_question['correctAnswer']} else: original = set(original_question['correctAnswer']) user_answer = set(user_quest_json_data['questions'][question]) if original == user_answer: correct_answer += 1 if correct_answer >= quiz_data['goalCount']: user_quest.status = QuizStatusEnum.passed else: user_quest.status = QuizStatusEnum.failed db.session.add(user_quest) db.session.commit() return render_template('quiz-plugin/finish.html', name=quiz, quiz=quiz_data, challenge=challenge, correct=correct_answer)
def add_container(): user_id = current_user.get_current_user().id redis_util = RedisUtils(app=app, user_id=user_id) if not redis_util.acquire_lock(): return json.dumps({'success': False, 'msg': 'Request Too Fast!'}) if ControlUtil.frequency_limit(): return json.dumps({ 'success': False, 'msg': 'Frequency limit, You should wait at least 1 min.' }) ControlUtil.remove_container(app, user_id) challenge_id = request.args.get('challenge_id') ControlUtil.check_challenge(challenge_id, user_id) configs = DBUtils.get_all_configs() current_count = DBUtils.get_all_alive_container_count() if int(configs.get("docker_max_container_count")) <= int( current_count): return json.dumps({ 'success': False, 'msg': 'Max container count exceed.' }) dynamic_docker_challenge = DynamicDockerChallenge.query \ .filter(DynamicDockerChallenge.id == challenge_id) \ .first_or_404() flag = "flag{" + str(uuid.uuid4()) + "}" if dynamic_docker_challenge.redirect_type == "http": ControlUtil.add_container(app=app, user_id=user_id, challenge_id=challenge_id, flag=flag) else: port = redis_util.get_available_port() ControlUtil.add_container(app=app, user_id=user_id, challenge_id=challenge_id, flag=flag, port=port) redis_util.release_lock() return json.dumps({'success': True})
def join(): infos = get_infos() errors = get_errors() if request.method == "GET": team_size_limit = get_config("team_size", default=0) if team_size_limit: plural = "" if team_size_limit == 1 else "s" infos.append( "Teams are limited to {limit} member{plural}".format( limit=team_size_limit, plural=plural ) ) return render_template("teams/join_team.html", infos=infos, errors=errors) if request.method == "POST": teamname = request.form.get("name") passphrase = request.form.get("password", "").strip() team = Teams.query.filter_by(name=teamname).first() if team and verify_password(passphrase, team.password): team_size_limit = get_config("team_size", default=0) if team_size_limit and len(team.members) >= team_size_limit: errors.append( "{name} has already reached the team size limit of {limit}".format( name=team.name, limit=team_size_limit ) ) return render_template( "teams/join_team.html", infos=infos, errors=errors ) user = get_current_user() user.team_id = team.id db.session.commit() if len(team.members) == 1: team.captain_id = user.id db.session.commit() clear_user_session(user_id=user.id) clear_team_session(team_id=team.id) return redirect(url_for("challenges.listing")) else: errors.append("That information is incorrect") return render_template("teams/join_team.html", infos=infos, errors=errors)
def post(self): req = request.get_json() user = get_current_user() req["user_id"] = user.id req["team_id"] = user.team_id Model = get_class_by_tablename(req["type"]) target = Model.query.filter_by(id=req["target"]).first_or_404() if target.cost > user.score: return ( { "success": False, "errors": { "score": "You do not have enough points to unlock this hint" }, }, 400, ) schema = UnlockSchema() response = schema.load(req, session=db.session) if response.errors: return {"success": False, "errors": response.errors}, 400 db.session.add(response.data) award_schema = AwardSchema() award = { "user_id": user.id, "team_id": user.team_id, "name": target.name, "description": target.description, "value": (-target.cost), "category": target.category, } award = award_schema.load(award) db.session.add(award.data) db.session.commit() response = schema.dump(response.data) return {"success": True, "data": response.data}
def destroy(): try: cid = request.form['challenge_id'] uid = get_current_user().id # 检查该用户是否真的部署了container if models.query_container(cid, uid): fish_challenge = models.query_FishChallengeTable(cid) if fish_challenge: url = fish_challenge.url passcode = fish_challenge.passcode if utils.do_destroy(url, uid, passcode): models.delete_containter(cid, uid) return 'Success' return 'Error' except: return 'Error'
def settings(): user = get_current_user() name = user.name email = user.email student_id = user.student_id real_name = user.real_name contact = user.contact prevent_name_change = get_config('prevent_name_change') confirm_email = get_config('verify_emails') and not user.verified return render_template('settings.html', name=name, email=email, student_id=student_id, real_name=real_name, prevent_name_change=prevent_name_change, confirm_email=confirm_email, contact=contact)
def post(self): req = request.get_json() expiration = req.get("expiration") if expiration: expiration = datetime.datetime.strptime(expiration, "%Y-%m-%d") user = get_current_user() token = generate_user_token(user, expiration=expiration) # Explicitly use admin view so that user's can see the value of their token schema = TokenSchema(view="admin") response = schema.dump(token) if response.errors: return {"success": False, "errors": response.errors}, 400 return {"success": True, "data": response.data}
def add_container(): if ControlUtil.frequency_limit(): return json.dumps({ 'success': False, 'msg': 'Frequency limit, You should wait at least 1 min.' }) user_id = current_user.get_current_user().id ControlUtil.remove_container(user_id) challenge_id = request.args.get('challenge_id') ControlUtil.check_challenge(challenge_id, user_id) configs = DBUtils.get_all_configs() current_count = DBUtils.get_all_alive_container_count() if int(configs.get("docker_max_container_count")) <= int( current_count): return json.dumps({ 'success': False, 'msg': 'Max container count exceed.' }) dynamic_docker_challenge = DynamicDockerChallenge.query \ .filter(DynamicDockerChallenge.id == challenge_id) \ .first_or_404() flag = "flag{" + str(uuid.uuid4()) + "}" if dynamic_docker_challenge.redirect_type == "http": ControlUtil.add_container(user_id=user_id, challenge_id=challenge_id, flag=flag) else: port = random.randint(int(configs.get("frp_direct_port_minimum")), int(configs.get("frp_direct_port_maximum"))) while True: if DBUtils.get_container_by_port(port) is None: break port = random.randint( int(configs.get("frp_direct_port_minimum")), int(configs.get("frp_direct_port_maximum"))) ControlUtil.add_container(user_id=user_id, challenge_id=challenge_id, flag=flag, port=port) return json.dumps({'success': True})
def settings(): user = get_current_user() name = user.name email = user.email 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('settings.html', name=name, email=email, website=website, affiliation=affiliation, country=country, prevent_name_change=prevent_name_change, confirm_email=confirm_email)
def delete(self, user_id): # import time; time.sleep(60) if get_current_user().id == user_id: return {'success': False, 'data': 'Cannot delete own account'} Notifications.query.filter_by(user_id=user_id).delete() Awards.query.filter_by(user_id=user_id).delete() Unlocks.query.filter_by(user_id=user_id).delete() Submissions.query.filter_by(user_id=user_id).delete() Solves.query.filter_by(user_id=user_id).delete() Tracking.query.filter_by(user_id=user_id).delete() Users.query.filter_by(id=user_id).delete() db.session.commit() db.session.close() clear_standings() return {"success": True}
def patch(): user_id = current_user.get_current_user().id challenge_id = request.args.get('challenge_id') docker_max_renew_count = int( get_config("whale:docker_max_renew_count", 5)) container = DBContainer.get_current_containers(user_id) if container is None: abort(403, 'Instance not found.', success=False) if int(container.challenge_id) != int(challenge_id): abort( 403, f'Container started but not from this challenge({container.challenge.name})', success=False) if container.renew_count >= docker_max_renew_count: abort(403, 'Max renewal count exceed.', success=False) result, message = ControlUtil.try_renew_container(user_id=user_id) return {'success': result, 'message': message}
def settings(): infos = get_infos() errors = get_errors() user = get_current_user() name = user.name email = user.email website = user.website affiliation = user.affiliation country = user.country if is_teams_mode() and get_current_team() is None: team_url = url_for("teams.private") infos.append( markup( f'In order to participate you must either <a href="{team_url}">join or create a team</a>.' ) ) tokens = UserTokens.query.filter_by(user_id=user.id).all() prevent_name_change = get_config("prevent_name_change") if get_config("verify_emails") and not user.verified: confirm_url = markup(url_for("auth.confirm")) infos.append( markup( "Your email address isn't confirmed!<br>" "Please check your email to confirm your email address.<br><br>" f'To have the confirmation email resent please <a href="{confirm_url}">click here</a>.' ) ) return render_template( "settings.html", name=name, email=email, website=website, affiliation=affiliation, country=country, tokens=tokens, prevent_name_change=prevent_name_change, infos=infos, errors=errors, )
def attempt(challenge, request): data = request.form or request.get_json() submission = data['submission'].strip() chal = KeyedChallenge.query.filter_by(id=challenge.id).first() box = nacl.secret.SecretBox( nacl.encoding.Base64Encoder.decode(chal.key)) salt = nacl.encoding.Base64Encoder.decode(chal.salt) if len(submission) < 7: return False, 'Invalid format' if submission[:5] != 'flag(': return False, 'Invalid format' if submission[-1:] != ')': return False, 'Invalid format' submission = submission[5:-1] try: flag = nacl.encoding.Base64Encoder.decode(submission) except TypeError: return False, 'Invalid format' try: decrypted_flag = box.decrypt(flag) except nacl.exceptions.CryptoError: # Verification failed return False, 'Incorrect decrypt' user = get_current_user() team = get_current_team() user_id = user.id, team_id = team.id if team else None, stored_flag = 'U' + str(user_id) + 'T' + str(team_id) + 'F' + salt if decrypted_flag == stored_flag: return True, 'Correct' else: return False, 'Incorrect'
def view_grades(): user_id = get_current_user().id if request.args.get("id") and is_admin(): try: user_id = int(request.args.get("id")) except ValueError: pass when = request.args.get("when") if when: when = datetime.datetime.fromtimestamp(int(when)) grades = compute_grades(user_id, when) for grade in grades: grade["grade"] = f'{grade["grade"] * 100.0:.2f}%' return render_template("grades.html", grades=grades)
def validate_email(self, data): email = data.get('email') if email is None: return existing_user = Users.query.filter_by(email=email).first() user_id = data.get('id') if user_id and is_admin(): if existing_user and existing_user.id != user_id: raise ValidationError('Email address has already been used', field_names=['email']) else: current_user = get_current_user() if email == current_user.email: return data else: if existing_user: raise ValidationError('Email address has already been used', field_names=['email'])
def validate_name(self, data): name = data.get('name') if name is None: return existing_user = Users.query.filter_by(name=name).first() user_id = data.get('id') if user_id and is_admin(): if existing_user and existing_user.id != user_id: raise ValidationError('User name has already been taken', field_names=['name']) else: current_user = get_current_user() if name == current_user.name: return data else: if existing_user: raise ValidationError('User name has already been taken', field_names=['name'])
def post(self, challenge_id): if authed() is False: return { 'success': True, 'data': { 'status': "authentication_required", } }, 403 user = get_current_user() like = Likes.checkUserLike(challenge_id) if like.count(): db.session.delete(like.first()) else: like = Likes(user_id=user.id, challenge_id=challenge_id) db.session.add(like) db.session.commit() return {'success': True}
def validate_password_confirmation(self, data): password = data.get('password') confirm = data.get('confirm') target_user = get_current_user() user_id = data.get('id') if is_admin(): pass else: if password and (confirm is None): raise ValidationError('Please confirm your current password', field_names=['confirm']) if password and confirm: test = verify_password(plaintext=confirm, ciphertext=target_user.password) if test is True: return data else: raise ValidationError('Your previous password is incorrect', field_names=['confirm'])
def get(self): user = get_current_user() awards = user.get_awards(admin=True) view = "user" if not is_admin() else "admin" response = AwardSchema(view=view, many=True).dump(awards) if response.errors: return {"success": False, "errors": response.errors}, 400 count = len(response.data) return { "success": True, "data": response.data, "meta": { "count": count } }
def _frequency_limited(*args, **kwargs): if is_admin(): return func(*args, **kwargs) redis_util = RedisUtils(app=current_app, user_id=get_current_user().id) if not redis_util.acquire_lock(): abort(403, 'Request Too Fast!') if "limit" not in session: session["limit"] = int(time.time()) else: if int(time.time()) - session["limit"] < 60: abort(403, 'Frequency limit, You should wait at least 1 min.') session["limit"] = int(time.time()) result = func(*args, **kwargs) redis_util.release_lock( ) # if any exception is raised, lock will not be released return result