def test_export_ctf(): """Test that CTFd can export the database""" app = create_ctfd() if not app.config.get("SQLALCHEMY_DATABASE_URI").startswith("sqlite"): with app.app_context(): register_user(app) chal1 = gen_challenge(app.db, name=text_type("🐺")) gen_challenge(app.db, name=text_type("🐺"), requirements={"prerequisites": [1]}) chal_id = chal1.id gen_hint(app.db, chal_id) client = login_as_user(app) with client.session_transaction(): data = {"target": 1, "type": "hints"} r = client.post("/api/v1/unlocks", json=data) output = r.get_data(as_text=True) json.loads(output) app.db.session.commit() backup = export_ctf() with open("export.test_export_ctf.zip", "wb") as f: f.write(backup.read()) export = zipfile.ZipFile("export.test_export_ctf.zip", "r") data = json.loads(export.read("db/challenges.json")) assert data["results"][1]["requirements"] == {"prerequisites": [1]} os.remove("export.test_export_ctf.zip") destroy_ctfd(app)
def penalty(team1, team2, chal, request): provided_key = request.form['key'].strip() cp1 = CheatPenalty(teamid=team1.id, chalid=chal.id, ip=utils.get_ip(request), flag=provided_key, penalty=chal.penalty) cp2 = CheatPenalty(teamid=team2.id, chalid=chal.id, ip=utils.get_ip(request), flag=provided_key, penalty=chal.penalty) award1 = Awards(teamid=team1.id, name=text_type('Cheating Penalty for {}'.format(chal.name)), value=(-chal.penalty)) award2 = Awards(teamid=team2.id, name=text_type('Cheating Penalty for {}'.format(chal.name)), value=(-chal.penalty)) db.session.add(award1) db.session.add(award2) db.session.add(cp1) db.session.add(cp2) db.session.commit() db.session.close()
def test_that_view_challenges_unregistered_works(): """Test that view_challenges_unregistered works""" app = create_ctfd() with app.app_context(): chal = gen_challenge(app.db, name=text_type("ЁЯР║")) chal_id = chal.id gen_hint(app.db, chal_id) client = app.test_client() r = client.get("/api/v1/challenges", json="") assert r.status_code == 403 r = client.get("/api/v1/challenges") assert r.status_code == 302 set_config("challenge_visibility", "public") client = app.test_client() r = client.get("/api/v1/challenges") assert r.get_json()["data"] r = client.get("/api/v1/challenges/1/solves") assert r.get_json().get("data") is not None data = {"submission": "not_flag", "challenge_id": chal_id} r = client.post("/api/v1/challenges/attempt", json=data) assert r.status_code == 403 assert r.get_json().get("data").get( "status") == "authentication_required" assert r.get_json().get("data").get("message") is None destroy_ctfd(app)
def solve(team, chal, request): """ This method is used to insert Solves into the database in order to mark a challenge as solved. :param team: The Team object from the database :param chal: The Challenge object from the database :param request: The request the user submitted :return: """ chal = CommunityChallengeModel.query.filter_by(id=chal.id).first() solve_count = Solves.query.join(Teams, Solves.teamid == Teams.id).filter( Solves.chalid == chal.id, Teams.banned == False).count() # if this is the first validation, we give the bonus points to the chal's owner if solve_count == 0: award = Awards( teamid=chal.owner, name=text_type( 'Bonus points for submitting challenge {}'.format( chal.name)), value=chal.value) db.session.add(award) provided_key = request.form['key'].strip() solve = Solves(teamid=team.id, chalid=chal.id, ip=utils.get_ip(req=request), flag=provided_key) db.session.add(solve) db.session.commit() db.session.close()
def test_that_view_challenges_unregistered_works(): '''Test that view_challenges_unregistered works''' app = create_ctfd() with app.app_context(): chal = gen_challenge(app.db, name=text_type('ЁЯР║')) chal_id = chal.id gen_hint(app.db, chal_id) client = app.test_client() r = client.get('/api/v1/challenges', json='') assert r.status_code == 403 r = client.get('/api/v1/challenges') assert r.status_code == 302 set_config('challenge_visibility', 'public') client = app.test_client() r = client.get('/api/v1/challenges') assert r.get_json()['data'] r = client.get('/api/v1/challenges/1/solves') assert r.get_json().get('data') is not None data = { "submission": 'not_flag', "challenge_id": chal_id } r = client.post('/api/v1/challenges/attempt'.format(chal_id), json=data) assert r.status_code == 403 assert r.get_json().get('data').get('status') == "authentication_required" assert r.get_json().get('data').get('message') is None destroy_ctfd(app)
def hints_view(hintid): if not utils.ctf_started(): abort(403) hint = Hints.query.filter_by(id=hintid).first_or_404() chal = Challenges.query.filter_by(id=hint.chal).first() unlock = Unlocks.query.filter_by(model='hints', itemid=hintid, teamid=session['id']).first() if request.method == 'GET': if unlock: return jsonify({ 'hint': hint.hint, 'chal': hint.chal, 'cost': hint.cost }) else: return jsonify({'chal': hint.chal, 'cost': hint.cost}) elif request.method == 'POST': if not unlock and utils.ctftime(): team = Teams.query.filter_by(id=session['id']).first() if team.score() < hint.cost: return jsonify({'errors': 'Not enough points'}) unlock = Unlocks(model='hints', teamid=session['id'], itemid=hint.id) award = Awards(teamid=session['id'], name=text_type('Hint for {}'.format(chal.name)), value=(-hint.cost)) db.session.add(unlock) db.session.add(award) db.session.commit() json_data = { 'hint': hint.hint, 'chal': hint.chal, 'cost': hint.cost } db.session.close() return jsonify(json_data) elif utils.ctf_ended(): json_data = { 'hint': hint.hint, 'chal': hint.chal, 'cost': hint.cost } db.session.close() return jsonify(json_data) else: json_data = { 'hint': hint.hint, 'chal': hint.chal, 'cost': hint.cost } db.session.close() return jsonify(json_data)
def hints_view(hintid): if utils.ctf_started() is False: if utils.is_admin() is False: abort(403) hint = Hints.query.filter_by(id=hintid).first_or_404() chal = Challenges.query.filter_by(id=hint.chal).first() unlock = Unlocks.query.filter_by(model='hints', itemid=hintid, teamid=session['id']).first() if request.method == 'GET': if unlock: return jsonify({ 'hint': hint.hint, 'chal': hint.chal, 'cost': hint.cost }) else: return jsonify({'chal': hint.chal, 'cost': hint.cost}) elif request.method == 'POST': if unlock is None: # The user does not have an unlock. if utils.ctftime() or ( utils.ctf_ended() and utils.view_after_ctf()) or utils.is_admin() is True: # It's ctftime or the CTF has ended (but we allow views after) team = Teams.query.filter_by(id=session['id']).first() if team.score() < hint.cost: return jsonify({'errors': get_tip('NOT_ENOUGH_POINT')}) unlock = Unlocks(model='hints', teamid=session['id'], itemid=hint.id) award = Awards(teamid=session['id'], name=text_type( get_tip('HIT_FOR').format(chal.name)), value=(-hint.cost)) db.session.add(unlock) db.session.add(award) db.session.commit() json_data = { 'hint': hint.hint, 'chal': hint.chal, 'cost': hint.cost } db.session.close() return jsonify(json_data) elif utils.ctf_ended(): # The CTF has ended. No views after. abort(403) else: # The user does have an unlock, we should give them their hint. json_data = { 'hint': hint.hint, 'chal': hint.chal, 'cost': hint.cost } db.session.close() return jsonify(json_data)
def test_unlocking_hint_for_unicode_challenge(): """Test that hints for challenges with unicode names can be unlocked""" app = create_ctfd() with app.app_context(): register_user(app) chal = gen_challenge(app.db, name=text_type('🐺')) chal_id = chal.id gen_hint(app.db, chal_id) client = login_as_user(app) r = client.get('/api/v1/hints/1') assert r.status_code == 200 resp = r.get_json()['data'] assert resp.get('content') == 'This is a hint' destroy_ctfd(app)
def test_export_ctf(): """Test that CTFd can export the database""" app = create_ctfd() if not app.config.get('SQLALCHEMY_DATABASE_URI').startswith('sqlite'): with app.app_context(): register_user(app) chal = gen_challenge(app.db, name=text_type('🐺')) chal_id = chal.id gen_hint(app.db, chal_id) client = login_as_user(app) with client.session_transaction(): data = {"target": 1, "type": "hints"} r = client.post('/api/v1/unlocks', json=data) output = r.get_data(as_text=True) json.loads(output) app.db.session.commit() backup = export_ctf() with open('export.zip', 'wb') as f: f.write(backup.read()) os.remove('export.zip') destroy_ctfd(app)