mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 14:04:20 +01:00
1423 model filter bypass (#1451)
* Add `view=admin` GET param to `/api/v1/users`, `/api/v1/teams`, and `/api/v1/challenges` to bypass filtering for admins * Closes #1423 #1445 * Related to #1165
This commit is contained in:
@@ -47,31 +47,36 @@ class ChallengeList(Resource):
|
||||
# This can return None (unauth) if visibility is set to public
|
||||
user = get_current_user()
|
||||
|
||||
challenges = (
|
||||
Challenges.query.filter(
|
||||
and_(Challenges.state != "hidden", Challenges.state != "locked")
|
||||
)
|
||||
.order_by(Challenges.value)
|
||||
.all()
|
||||
)
|
||||
|
||||
if user:
|
||||
solve_ids = (
|
||||
Solves.query.with_entities(Solves.challenge_id)
|
||||
.filter_by(account_id=user.account_id)
|
||||
.order_by(Solves.challenge_id.asc())
|
||||
# Admins can request to see everything
|
||||
if is_admin() and request.args.get("view") == "admin":
|
||||
challenges = Challenges.query.order_by(Challenges.value).all()
|
||||
solve_ids = set([challenge.id for challenge in challenges])
|
||||
else:
|
||||
challenges = (
|
||||
Challenges.query.filter(
|
||||
and_(Challenges.state != "hidden", Challenges.state != "locked")
|
||||
)
|
||||
.order_by(Challenges.value)
|
||||
.all()
|
||||
)
|
||||
solve_ids = set([value for value, in solve_ids])
|
||||
|
||||
# TODO: Convert this into a re-useable decorator
|
||||
if is_admin():
|
||||
pass
|
||||
if user:
|
||||
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([value for value, in solve_ids])
|
||||
|
||||
# TODO: Convert this into a re-useable decorator
|
||||
if is_admin():
|
||||
pass
|
||||
else:
|
||||
if config.is_teams_mode() and get_current_team() is None:
|
||||
abort(403)
|
||||
else:
|
||||
if config.is_teams_mode() and get_current_team() is None:
|
||||
abort(403)
|
||||
else:
|
||||
solve_ids = set()
|
||||
solve_ids = set()
|
||||
|
||||
response = []
|
||||
tag_schema = TagSchema(view="user", many=True)
|
||||
|
||||
@@ -22,7 +22,11 @@ teams_namespace = Namespace("teams", description="Endpoint to retrieve Teams")
|
||||
class TeamList(Resource):
|
||||
@check_account_visibility
|
||||
def get(self):
|
||||
teams = Teams.query.filter_by(hidden=False, banned=False)
|
||||
if is_admin() and request.args.get("view") == "admin":
|
||||
teams = Teams.query.filter_by()
|
||||
else:
|
||||
teams = Teams.query.filter_by(hidden=False, banned=False)
|
||||
|
||||
user_type = get_current_user_type(fallback="user")
|
||||
view = copy.deepcopy(TeamSchema.views.get(user_type))
|
||||
view.remove("members")
|
||||
|
||||
@@ -31,7 +31,11 @@ users_namespace = Namespace("users", description="Endpoint to retrieve Users")
|
||||
class UserList(Resource):
|
||||
@check_account_visibility
|
||||
def get(self):
|
||||
users = Users.query.filter_by(banned=False, hidden=False)
|
||||
if is_admin() and request.args.get("view") == "admin":
|
||||
users = Users.query.filter_by()
|
||||
else:
|
||||
users = Users.query.filter_by(banned=False, hidden=False)
|
||||
|
||||
response = UserSchema(view="user", many=True).dump(users)
|
||||
|
||||
if response.errors:
|
||||
|
||||
@@ -135,6 +135,25 @@ def test_api_challenges_get_admin():
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_api_challenges_get_hidden_admin():
|
||||
"""Can an admin see hidden challenges in API list response"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
gen_challenge(app.db, state="hidden")
|
||||
gen_challenge(app.db)
|
||||
|
||||
with login_as_user(app, "admin") as admin:
|
||||
challenges_list = admin.get("/api/v1/challenges", json="").get_json()[
|
||||
"data"
|
||||
]
|
||||
assert len(challenges_list) == 1
|
||||
challenges_list = admin.get(
|
||||
"/api/v1/challenges?view=admin", json=""
|
||||
).get_json()["data"]
|
||||
assert len(challenges_list) == 2
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_api_challenges_post_admin():
|
||||
"""Can a user post /api/v1/challenges if admin"""
|
||||
app = create_ctfd()
|
||||
|
||||
@@ -696,6 +696,9 @@ def test_api_accessing_hidden_banned_users():
|
||||
app.db.session.commit()
|
||||
|
||||
with login_as_user(app, name="visible_user") as client:
|
||||
list_teams = client.get("/api/v1/teams").get_json()["data"]
|
||||
assert len(list_teams) == 0
|
||||
|
||||
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
|
||||
@@ -707,6 +710,10 @@ def test_api_accessing_hidden_banned_users():
|
||||
assert client.get("/api/v1/teams/2/awards").status_code == 404
|
||||
|
||||
with login_as_user(app, name="admin") as client:
|
||||
# Admins see hidden teams in lists
|
||||
list_users = client.get("/api/v1/teams?view=admin").get_json()["data"]
|
||||
assert len(list_users) == 2
|
||||
|
||||
assert client.get("/api/v1/teams/1").status_code == 200
|
||||
assert client.get("/api/v1/teams/1/solves").status_code == 200
|
||||
assert client.get("/api/v1/teams/1/fails").status_code == 200
|
||||
|
||||
@@ -764,12 +764,19 @@ def test_api_accessing_hidden_users():
|
||||
app.db.session.commit()
|
||||
|
||||
with login_as_user(app, name="visible_user") as client:
|
||||
list_users = client.get("/api/v1/users").get_json()["data"]
|
||||
assert len(list_users) == 1
|
||||
|
||||
assert client.get("/api/v1/users/3").status_code == 404
|
||||
assert client.get("/api/v1/users/3/solves").status_code == 404
|
||||
assert client.get("/api/v1/users/3/fails").status_code == 404
|
||||
assert client.get("/api/v1/users/3/awards").status_code == 404
|
||||
|
||||
with login_as_user(app, name="admin") as client:
|
||||
# Admins see the user in lists
|
||||
list_users = client.get("/api/v1/users?view=admin").get_json()["data"]
|
||||
assert len(list_users) == 3
|
||||
|
||||
assert client.get("/api/v1/users/3").status_code == 200
|
||||
assert client.get("/api/v1/users/3/solves").status_code == 200
|
||||
assert client.get("/api/v1/users/3/fails").status_code == 200
|
||||
@@ -788,12 +795,19 @@ def test_api_accessing_banned_users():
|
||||
app.db.session.commit()
|
||||
|
||||
with login_as_user(app, name="visible_user") as client:
|
||||
list_users = client.get("/api/v1/users").get_json()["data"]
|
||||
assert len(list_users) == 1
|
||||
|
||||
assert client.get("/api/v1/users/3").status_code == 404
|
||||
assert client.get("/api/v1/users/3/solves").status_code == 404
|
||||
assert client.get("/api/v1/users/3/fails").status_code == 404
|
||||
assert client.get("/api/v1/users/3/awards").status_code == 404
|
||||
|
||||
with login_as_user(app, name="admin") as client:
|
||||
# Admins see the user in lists
|
||||
list_users = client.get("/api/v1/users?view=admin").get_json()["data"]
|
||||
assert len(list_users) == 3
|
||||
|
||||
assert client.get("/api/v1/users/3").status_code == 200
|
||||
assert client.get("/api/v1/users/3/solves").status_code == 200
|
||||
assert client.get("/api/v1/users/3/fails").status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user