def gen_award(db, user_id, team_id=None, name="award_name", value=100): award = Awards(user_id=user_id, team_id=team_id, name=name, value=value) award.date = datetime.datetime.utcnow() db.session.add(award) db.session.commit() clear_standings() return award
def delete(self, award_id): award = Awards.query.filter_by(id=award_id).first_or_404() db.session.delete(award) db.session.commit() db.session.close() # Delete standings cache because awards can change scores clear_standings() return {"success": True}
def patch(self): req = request.get_json() for key, value in req.items(): set_config(key=key, value=value) clear_config() clear_standings() return {"success": True}
def delete(self, submission_id): submission = Submissions.query.filter_by( id=submission_id).first_or_404() db.session.delete(submission) db.session.commit() db.session.close() # Delete standings cache clear_standings() return {"success": True}
def delete(self, config_key): config = Configs.query.filter_by(key=config_key).first_or_404() db.session.delete(config) db.session.commit() db.session.close() clear_config() clear_standings() return {"success": True}
def delete(self, team_id): team = Teams.query.filter_by(id=team_id).first_or_404() for member in team.members: member.team_id = None db.session.delete(team) db.session.commit() db.session.close() clear_standings() return {"success": True}
def delete(self, user_id): 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 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() clear_standings() response = schema.dump(response.data) return {"success": True, "data": response.data}
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 post(self): req = request.get_json() schema = ConfigSchema() response = schema.load(req) if response.errors: return {"success": False, "errors": response.errors}, 400 db.session.add(response.data) db.session.commit() response = schema.dump(response.data) db.session.close() clear_config() clear_standings() return {"success": True, "data": response.data}
def post(self): req = request.get_json() Model = Submissions.get_child(type=req.get("type")) schema = SubmissionSchema(instance=Model()) response = schema.load(req) if response.errors: return {"success": False, "errors": response.errors}, 400 db.session.add(response.data) db.session.commit() response = schema.dump(response.data) db.session.close() # Delete standings cache clear_standings() return {"success": True, "data": response.data}
def post(self): req = request.get_json() schema = AwardSchema() response = schema.load(req, session=db.session) if response.errors: return {"success": False, "errors": response.errors}, 400 db.session.add(response.data) db.session.commit() response = schema.dump(response.data) db.session.close() # Delete standings cache because awards can change scores clear_standings() return {"success": True, "data": response.data}
def patch(self, team_id): team = Teams.query.filter_by(id=team_id).first_or_404() data = request.get_json() data["id"] = team_id schema = TeamSchema(view="admin", instance=team, partial=True) response = schema.load(data) if response.errors: return {"success": False, "errors": response.errors}, 400 response = schema.dump(response.data) db.session.commit() db.session.close() clear_standings() return {"success": True, "data": response.data}
def post(self): req = request.get_json() view = TeamSchema.views.get(session.get("type", "self")) schema = TeamSchema(view=view) response = schema.load(req) if response.errors: return {"success": False, "errors": response.errors}, 400 db.session.add(response.data) db.session.commit() response = schema.dump(response.data) db.session.close() clear_standings() return {"success": True, "data": response.data}
def gen_solve( db, user_id, team_id=None, challenge_id=None, ip="127.0.0.1", provided="rightkey", **kwargs ): solve = Solves( user_id=user_id, team_id=team_id, challenge_id=challenge_id, ip=ip, provided=provided, **kwargs ) solve.date = datetime.datetime.utcnow() db.session.add(solve) db.session.commit() clear_standings() return solve
def test_scoreboard_is_cached(): """Test that /api/v1/scoreboard is properly cached and cleared""" app = create_kmactf() with app.app_context(): # create user1 register_user(app, name="user1", email="*****@*****.**") # create challenge chal = gen_challenge(app.db, value=100) gen_flag(app.db, challenge_id=chal.id, content="flag") chal_id = chal.id # create a solve for the challenge for user1. (the id is 2 because of the admin) gen_solve(app.db, user_id=2, challenge_id=chal_id) with login_as_user(app, "user1") as client: # No cached data assert app.cache.get("view/api.scoreboard_scoreboard_list") is None assert app.cache.get( "view/api.scoreboard_scoreboard_detail") is None # Load and check cached data client.get("/api/v1/scoreboard") assert app.cache.get("view/api.scoreboard_scoreboard_list") client.get("/api/v1/scoreboard/top/10") assert app.cache.get("view/api.scoreboard_scoreboard_detail") # Check scoreboard page assert app.cache.get("view/scoreboard.listing") is None client.get("/scoreboard") assert app.cache.get("view/scoreboard.listing") # Empty standings and check that the cached data is gone clear_standings() assert app.cache.get("view/api.scoreboard_scoreboard_list") is None assert app.cache.get( "view/api.scoreboard_scoreboard_detail") is None assert app.cache.get("view/scoreboard.listing") is None destroy_kmactf(app)
def post(self): req = request.get_json() schema = UserSchema("admin") response = schema.load(req) if response.errors: return {"success": False, "errors": response.errors}, 400 db.session.add(response.data) db.session.commit() if request.args.get("notify"): name = response.data.name email = response.data.email password = req.get("password") user_created_notification(addr=email, name=name, password=password) clear_standings() response = schema.dump(response.data) return {"success": True, "data": response.data}
def patch(self, config_key): config = Configs.query.filter_by(key=config_key).first() data = request.get_json() if config: schema = ConfigSchema(instance=config, partial=True) response = schema.load(data) else: schema = ConfigSchema() data["key"] = config_key response = schema.load(data) db.session.add(response.data) if response.errors: return response.errors, 400 db.session.commit() response = schema.dump(response.data) db.session.close() clear_config() clear_standings() return {"success": True, "data": response.data}
def post(self): if authed() is False: return { "success": True, "data": { "status": "authentication_required" } }, 403 if request.content_type != "application/json": request_data = request.form else: request_data = request.get_json() challenge_id = request_data.get("challenge_id") if current_user.is_admin(): preview = request.args.get("preview", False) if preview: challenge = Challenges.query.filter_by( id=challenge_id).first_or_404() chal_class = get_chal_class(challenge.type) status, message = chal_class.attempt(challenge, request) return { "success": True, "data": { "status": "correct" if status else "incorrect", "message": message, }, } if ctf_paused(): return ( { "success": True, "data": { "status": "paused", "message": "{} is paused".format(config.ctf_name()), }, }, 403, ) user = get_current_user() team = get_current_team() # TODO: Convert this into a re-useable decorator if config.is_teams_mode() and team is None: abort(403) fails = Fails.query.filter_by(account_id=user.account_id, challenge_id=challenge_id).count() challenge = Challenges.query.filter_by(id=challenge_id).first_or_404() if challenge.state == "hidden": abort(404) if challenge.state == "locked": abort(403) if challenge.requirements: requirements = challenge.requirements.get("prerequisites", []) solve_ids = (Solves.query.with_entities( Solves.challenge_id).filter_by( account_id=user.account_id).order_by( Solves.challenge_id.asc()).all()) solve_ids = set([solve_id for solve_id, in solve_ids]) prereqs = set(requirements) if solve_ids >= prereqs: pass else: abort(403) chal_class = get_chal_class(challenge.type) # Anti-bruteforce / submitting Flags too quickly kpm = current_user.get_wrong_submissions_per_minute(user.account_id) if kpm > 10: if ctftime(): chal_class.fail(user=user, team=team, challenge=challenge, request=request) log( "submissions", "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [TOO FAST]", submission=request_data["submission"].encode("utf-8"), challenge_id=challenge_id, kpm=kpm, ) # Submitting too fast return ( { "success": True, "data": { "status": "ratelimited", "message": "You're submitting flags too fast. Slow down.", }, }, 429, ) solves = Solves.query.filter_by(account_id=user.account_id, challenge_id=challenge_id).first() # Challenge not solved yet if not solves: # Hit max attempts max_tries = challenge.max_attempts if max_tries and fails >= max_tries > 0: return ( { "success": True, "data": { "status": "incorrect", "message": "You have 0 tries remaining", }, }, 403, ) status, message = chal_class.attempt(challenge, request) if status: # The challenge plugin says the input is right if ctftime() or current_user.is_admin(): chal_class.solve(user=user, team=team, challenge=challenge, request=request) clear_standings() log( "submissions", "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [CORRECT]", submission=request_data["submission"].encode("utf-8"), challenge_id=challenge_id, kpm=kpm, ) return { "success": True, "data": { "status": "correct", "message": message }, } else: # The challenge plugin says the input is wrong if ctftime() or current_user.is_admin(): chal_class.fail(user=user, team=team, challenge=challenge, request=request) clear_standings() log( "submissions", "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [WRONG]", submission=request_data["submission"].encode("utf-8"), challenge_id=challenge_id, kpm=kpm, ) if max_tries: # Off by one since fails has changed since it was gotten attempts_left = max_tries - fails - 1 tries_str = "tries" if attempts_left == 1: tries_str = "try" # Add a punctuation mark if there isn't one if message[-1] not in "!().;?[]{}": message = message + "." return { "success": True, "data": { "status": "incorrect", "message": "{} You have {} {} remaining.".format( message, attempts_left, tries_str), }, } else: return { "success": True, "data": { "status": "incorrect", "message": message }, } # Challenge already solved else: log( "submissions", "[{date}] {name} submitted {submission} on {challenge_id} with kpm {kpm} [ALREADY SOLVED]", submission=request_data["submission"].encode("utf-8"), challenge_id=challenge_id, kpm=kpm, ) return { "success": True, "data": { "status": "already_solved", "message": "You already solved this", }, }