def test_admin_config(): """Does admin config return a 200 by default""" app = create_ctfd() with app.app_context(): client = login_as_user(app, name="admin", password="******") r = client.get('/admin/config') assert r.status_code == 200
def test_admin_panel(): """Does the admin panel return a 200 by default""" app = create_ctfd() with app.app_context(): client = login_as_user(app, name="admin", password="******") r = client.get('/admin') assert r.status_code == 302 r = client.get('/admin/graphs') assert r.status_code == 200
def test_accessing_hidden_teams(): """Hidden teams should not give any data from /teams or /api/v1/teams""" app = create_ctfd(user_mode="teams") with app.app_context(): register_user(app) register_user(app, name="visible_user", email="*****@*****.**") with login_as_user(app, name="visible_user") as client: user = Users.query.filter_by(id=2).first() team = gen_team(app.db, name="visible_team", hidden=True) team.members.append(user) user.team_id = team.id app.db.session.commit() assert client.get("/teams/1").status_code == 404 assert client.get("/api/v1/teams/1").status_code == 404 assert client.get("/api/v1/teams/1/solves").status_code == 404 assert client.get("/api/v1/teams/1/fails").status_code == 404 assert client.get("/api/v1/teams/1/awards").status_code == 404 destroy_ctfd(app)
def test_api_user_change_verify_email(): """Test that users are marked unconfirmed if they change their email and verify_emails is turned on""" app = create_ctfd() with app.app_context(): set_config("verify_emails", True) register_user(app) user = Users.query.filter_by(id=2).first() user.verified = True app.db.session.commit() with login_as_user(app) as client: r = client.patch( "/api/v1/users/me", json={"email": "*****@*****.**", "confirm": "password"}, ) assert r.status_code == 200 resp = r.get_json() assert resp["data"]["email"] == "*****@*****.**" assert resp["success"] is True user = Users.query.filter_by(id=2).first() assert user.verified is False destroy_ctfd(app)
def test_anonymous_users_view_public_challenges_without_team(): """Test that if challenges are public, users without team can still view them""" app = create_ctfd(user_mode="teams") with app.app_context(): register_user(app) gen_challenge(app.db) with app.test_client() as client: r = client.get("/challenges") assert r.status_code == 302 assert r.location.startswith("http://localhost/login") set_config("challenge_visibility", "public") with app.test_client() as client: r = client.get("/challenges") assert r.status_code == 200 with login_as_user(app) as client: r = client.get("/challenges") assert r.status_code == 302 assert r.location.startswith("http://localhost/team") destroy_ctfd(app)
def test_user_can_unlock_hint(): """Test that a user can unlock a hint if they have enough points""" app = create_kmactf() with app.app_context(): with app.test_client(): register_user(app, name="user1", email="*****@*****.**") chal = gen_challenge(app.db, value=100) chal_id = chal.id gen_flag(app.db, challenge_id=chal.id, content="flag") hint = gen_hint(app.db, chal_id, cost=10) hint_id = hint.id gen_award(app.db, user_id=2, value=15) client = login_as_user(app, name="user1", password="******") user = Users.query.filter_by(name="user1").first() assert user.score == 15 with client.session_transaction(): r = client.get("/api/v1/hints/{}".format(hint_id)) resp = r.get_json() assert resp["data"].get("content") is None params = {"target": hint_id, "type": "hints"} r = client.post("/api/v1/unlocks", json=params) resp = r.get_json() assert resp["success"] is True r = client.get("/api/v1/hints/{}".format(hint_id)) resp = r.get_json() assert resp["data"].get("content") == "This is a hint" user = Users.query.filter_by(name="user1").first() assert user.score == 5 destroy_kmactf(app)
def test_unlocking_hints_with_cost_before_ctf(): """Test that hints are not unlocked if the CTF hasn't begun""" app = create_ctfd() with app.app_context(): register_user(app) chal = gen_challenge(app.db) chal_id = chal.id gen_hint(app.db, chal_id) gen_award(app.db, user_id=2) set_config('start', '1507089600' ) # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST set_config( 'end', '1507262400') # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST with freeze_time("2017-10-1"): client = login_as_user(app) r = client.get('/api/v1/hints/1') assert r.status_code == 403 assert r.get_json().get('data') is None r = client.post('/api/v1/unlocks', json={ 'target': 1, 'type': 'hints' }) assert r.status_code == 403 assert r.get_json().get('data') is None r = client.get('/api/v1/hints/1') assert r.get_json().get('data') is None assert r.status_code == 403 user = Users.query.filter_by(id=2).first() assert user.score == 100 assert Unlocks.query.count() == 0 destroy_ctfd(app)
def test_boolean_checkbox_field(): app = create_ctfd() with app.app_context(): gen_field(app.db, name="CustomField1", field_type="boolean", required=False) with app.test_client() as client: r = client.get("/register") resp = r.get_data(as_text=True) # We should have rendered a checkbox input assert "checkbox" in resp with client.session_transaction() as sess: data = { "name": "user", "email": "*****@*****.**", "password": "******", "nonce": sess.get("nonce"), "fields[1]": "y", } client.post("/register", data=data) with client.session_transaction() as sess: assert sess["id"] assert UserFieldEntries.query.count() == 1 assert UserFieldEntries.query.filter_by(id=1).first().value is True with login_as_user(app) as client: r = client.get("/settings") resp = r.get_data(as_text=True) assert "CustomField1" in resp assert "checkbox" in resp r = client.patch( "/api/v1/users/me", json={"fields": [{"field_id": 1, "value": False}]} ) assert r.status_code == 200 assert UserFieldEntries.query.count() == 1 assert UserFieldEntries.query.filter_by(id=1).first().value is False destroy_ctfd(app)
def test_teams_join_post(): """Can a user post /teams/join""" app = create_ctfd(user_mode="teams") with app.app_context(): gen_user(app.db, name="user") gen_team(app.db, name="team") with login_as_user(app) as client: r = client.get('/teams/join') assert r.status_code == 200 with client.session_transaction() as sess: data = { "name": "team", "password": "******", "nonce": sess.get('nonce') } r = client.post('/teams/join', data=data) assert r.status_code == 302 incorrect_data = data incorrect_data['password'] = "" r = client.post('/teams/join', data=incorrect_data) assert r.status_code == 200 destroy_ctfd(app)
def test_unlocking_hints_with_cost_during_ctf_with_points(): """Test that hints with a cost are unlocked if you have the points""" app = create_kmactf() with app.app_context(): register_user(app) chal = gen_challenge(app.db) chal_id = chal.id gen_hint(app.db, chal_id, cost=10) gen_award(app.db, user_id=2) client = login_as_user(app) r = client.get("/api/v1/hints/1") assert r.get_json()["data"].get("content") is None client.post("/api/v1/unlocks", json={"target": 1, "type": "hints"}) r = client.get("/api/v1/hints/1") assert r.get_json()["data"].get("content") == "This is a hint" user = Users.query.filter_by(id=2).first() assert user.score == 90 destroy_kmactf(app)
def test_api_hint_404(): """Are admin protected resources accessible by admins/non-admins""" app = create_ctfd() endpoints = ['/api/v1/configs/{}', '/api/v1/challenges/types', '/api/v1/statistics/teams', '/api/v1/flags/{}', '/api/v1/statistics/users/{}', '/api/v1/configs', '/api/v1/statistics/challenges/solves/percentages', '/api/v1/tags/{}', '/api/v1/pages', '/api/v1/files/{}', '/api/v1/challenges/{}/tags', '/api/v1/hints', '/api/v1/challenges/{}/files', '/api/v1/flags', '/api/v1/submissions/{}', '/api/v1/challenges/{}/flags', '/api/v1/awards/{}', '/api/v1/unlocks', '/api/v1/challenges/{}/hints', '/api/v1/statistics/submissions/{}', '/api/v1/flags/types/{}', '/api/v1/tags', '/api/v1/statistics/challenges/{}', '/api/v1/files', '/api/v1/flags/types', '/api/v1/submissions', '/api/v1/pages/{}'] with app.app_context(): register_user(app) client = login_as_user(app) for endpoint in endpoints: r = client.get(endpoint.format(1)) assert r.status_code == 302 assert r.location.startswith('http://localhost/login') destroy_ctfd(app)
def test_api_topics_get_admin(): """Can a user get /api/v1/topics if admin""" app = create_ctfd() with app.app_context(): gen_challenge(app.db) gen_topic(app.db, challenge_id=1) gen_topic(app.db, challenge_id=1, value="topic2") with login_as_user(app, name="admin") as client: r = client.get("/api/v1/topics") assert r.status_code == 200 assert r.get_json() == { "success": True, "data": [{ "id": 1, "value": "topic" }, { "id": 2, "value": "topic2" }], } destroy_ctfd(app)
def test_api_topics_non_admin(): """Can a user interact with /api/v1/topics if not admin""" app = create_ctfd() with app.app_context(): gen_challenge(app.db) gen_topic(app.db, challenge_id=1) with app.test_client() as client: r = client.get("/api/v1/topics", json="") assert r.status_code == 403 """Can a user post /api/v1/topics if not admin""" r = client.post("/api/v1/topics") assert r.status_code == 403 """Can a user delete /api/v1/topics if not admin""" r = client.delete("/api/v1/topics") assert r.status_code == 403 """Can a user get /api/v1/topics/<topic_id> if not admin""" r = client.get("/api/v1/topics/1", json="") assert r.status_code == 403 """Can a user delete /api/v1/topics/<topic_id> if not admin""" r = client.delete("/api/v1/topics/1", json="") assert r.status_code == 403 register_user(app) with login_as_user(app) as client: r = client.get("/api/v1/topics", json="") assert r.status_code == 403 """Can a user post /api/v1/topics if not admin""" r = client.post("/api/v1/topics") assert r.status_code == 403 """Can a user delete /api/v1/topics if not admin""" r = client.delete("/api/v1/topics") assert r.status_code == 403 """Can a user get /api/v1/topics/<topic_id> if not admin""" r = client.get("/api/v1/topics/1", json="") assert r.status_code == 403 """Can a user delete /api/v1/topics/<topic_id> if not admin""" r = client.delete("/api/v1/topics/1", json="") assert r.status_code == 403 destroy_ctfd(app)
def test_challenges_cannot_be_solved_while_paused(): """Test that challenges cannot be solved when the CTF is paused""" app = create_ctfd() with app.app_context(): set_config('paused', True) register_user(app) client = login_as_user(app) r = client.get('/challenges') assert r.status_code == 200 # Assert that there is a paused message data = r.get_data(as_text=True) assert 'paused' in data chal = gen_challenge(app.db) gen_flag(app.db, challenge_id=chal.id, content='flag') data = { "submission": 'flag', "challenge_id": chal.id } r = client.post('/api/v1/challenges/attempt', json=data) # Assert that the JSON message is correct resp = r.get_json()['data'] assert r.status_code == 403 assert resp['status'] == 'paused' assert resp['message'] == 'CTFd is paused' # There are no solves saved solves = Solves.query.count() assert solves == 0 # There are no wrong keys saved wrong_keys = Fails.query.count() assert wrong_keys == 0 destroy_ctfd(app)
def test_hidden_challenge_is_unreachable(): """Test that hidden challenges return 404 and do not insert a solve or wrong key""" app = create_ctfd() with app.app_context(): register_user(app) client = login_as_user(app) chal = gen_challenge(app.db, state='hidden') gen_flag(app.db, challenge_id=chal.id, content='flag') chal_id = chal.id assert Challenges.query.count() == 1 r = client.get('/api/v1/challenges', json='') data = r.get_json().get('data') assert data == [] r = client.get('/api/v1/challenges/1', json='') assert r.status_code == 404 data = r.get_json().get('data') assert data is None data = { "submission": 'flag', "challenge_id": chal_id } r = client.post('/api/v1/challenges/attempt', json=data) assert r.status_code == 404 r = client.post('/api/v1/challenges/attempt?preview=true', json=data) assert r.status_code == 404 assert r.get_json().get('data') is None solves = Solves.query.count() assert solves == 0 wrong_keys = Fails.query.count() assert wrong_keys == 0 destroy_ctfd(app)