Fix challenge requirement visibility; add challenge requirements test; mark solves after loading chals (#755)

* Fix challenge requirement visibility
* Add challenge requirements test
* Mark solves after loading chals
selenium-screenshot-testing
Kevin Chung 2018-11-25 22:23:05 -05:00 committed by GitHub
parent ae90537a59
commit 821c5552c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 101 deletions

View File

@ -160,6 +160,40 @@ class Challenge(Resource):
chal_class = get_chal_class(chal.type)
requirements = chal.requirements
if requirements:
if current_user.authed():
user = get_current_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])
prereqs = set(requirements.get('prerequisites', []))
anonymize = requirements.get('anonymize')
if solve_ids >= prereqs:
pass
else:
if anonymize:
return {
'success': True,
'data': {
'id': chal.id,
'type': 'hidden',
'name': '???',
'value': 0,
'category': '???',
'tags': [],
'template': '',
'script': ''
}
}
abort(403)
else:
abort(403)
tags = [
tag['value'] for tag in TagSchema(
"user", many=True).dump(
@ -286,6 +320,7 @@ class ChallengeAttempt(Resource):
.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.get('prerequisites', []))
if solve_ids >= prereqs:

View File

@ -69,7 +69,9 @@ function updateChalWindow(obj) {
$('#submit-key').prop('disabled', true);
window.challenge.submit(function (data) {
renderSubmissionResponse(data);
loadchals();
loadchals(function () {
marksolves();
});
});
});
@ -161,8 +163,6 @@ function renderSubmissionResponse(response, cb) {
answer_input.removeClass("too-fast");
}, 3000);
}
marksolves();
// updatesolves();
setTimeout(function () {
$('.alert').slideUp();
$('#submit-key').removeClass("disabled-button");

View File

@ -297,52 +297,6 @@ def test_challenge_kpm_limit():
destroy_ctfd(app)
# def test_submitting_flags_with_large_ips():
# """Test that users with high octect IP addresses can submit flags"""
# app = create_ctfd()
# with app.app_context():
# register_user(app)
# client = login_as_user(app)
#
# # SQLite doesn't support BigInteger well so we can't test it properly
# ip_addresses = ['172.18.0.1', '255.255.255.255', '2001:0db8:85a3:0000:0000:8a2e:0370:7334']
# for ip_address in ip_addresses:
# # Monkeypatch get_ip
# def get_ip_fake(req=None):
# return ip_address
# utils.get_ip = get_ip_fake
#
# # Generate challenge and flag
# chal = gen_challenge(app.db)
# chal_id = chal.id
# flag = gen_flag(app.db, chal=chal.id, flag=u'correct_key')
#
# # Submit wrong_key
# with client.session_transaction() as sess:
# data = {
# "key": 'wrong_key',
# "nonce": sess.get('nonce')
# }
# r = client.post('/api/v1/challenges/attempt'.format(chal_id), json=data)
# assert r.status_code == 200
# resp = json.loads(r.data.decode('utf8'))
# assert resp.get('status') == 0 and resp.get('message') == "Incorrect"
# assert Fails.query.filter_by(ip=ip_address).first()
#
# # Submit correct key
# with client.session_transaction() as sess:
# data = {
# "key": 'correct_key',
# "nonce": sess.get('nonce')
# }
# r = client.post('/api/v1/challenges/attempt'.format(chal_id), json=data)
# assert r.status_code == 200
# resp = json.loads(r.data.decode('utf8'))
# assert resp.get('status') == 1 and resp.get('message') == "Correct"
# assert Solves.query.filter_by(ip=ip_address).first()
# destroy_ctfd(app)
def test_that_view_challenges_unregistered_works():
'''Test that view_challenges_unregistered works'''
app = create_ctfd()
@ -449,6 +403,71 @@ def test_hidden_challenge_is_unsolveable():
destroy_ctfd(app)
def test_challenge_with_requirements_is_unsolveable():
"""Test that a challenge with a requirement is unsolveable without first solving the requirement"""
app = create_ctfd()
with app.app_context():
register_user(app)
client = login_as_user(app)
chal1 = gen_challenge(app.db)
flag1 = gen_flag(app.db, challenge_id=chal1.id, content='flag')
requirements = {
'prerequisites': [1]
}
chal2 = gen_challenge(app.db, requirements=requirements)
app.db.session.commit()
flag2 = gen_flag(app.db, challenge_id=chal2.id, content='flag')
r = client.get('/api/v1/challenges')
challenges = r.get_json()['data']
assert len(challenges) == 1
assert challenges[0]['id'] == 1
r = client.get('/api/v1/challenges/2')
assert r.status_code == 403
assert r.get_json().get('data') is None
# Attempt to solve hidden Challenge 2
data = {
"submission": 'flag',
"challenge_id": 2
}
r = client.post('/api/v1/challenges/attempt', json=data)
assert r.status_code == 403
assert r.get_json().get('data') is None
# Solve Challenge 1
data = {
"submission": 'flag',
"challenge_id": 1
}
r = client.post('/api/v1/challenges/attempt', json=data)
resp = r.get_json()['data']
assert resp['status'] == 'correct'
# Challenge 2 should now be visible
r = client.get('/api/v1/challenges')
challenges = r.get_json()['data']
assert len(challenges) == 2
r = client.get('/api/v1/challenges/2')
assert r.status_code == 200
assert r.get_json().get('data')['id'] == 2
# Attempt to solve the now-visible Challenge 2
data = {
"submission": 'flag',
"challenge_id": 2
}
r = client.post('/api/v1/challenges/attempt', json=data)
assert r.status_code == 200
assert resp['status'] == 'correct'
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()
@ -488,55 +507,3 @@ def test_challenges_cannot_be_solved_while_paused():
wrong_keys = Fails.query.count()
assert wrong_keys == 0
destroy_ctfd(app)
# def test_challenge_solves_can_be_seen():
# """Test that the /solves endpoint works properly for users"""
# app = create_ctfd()
# with app.app_context():
# register_user(app)
#
# with app.test_client() as client:
# r = client.get('/solves')
# assert r.location.startswith("http://localhost/login?next=")
# assert r.status_code == 302
#
# client = login_as_user(app)
#
# r = client.get('/solves')
# data = r.get_data(as_text=True)
# data = json.loads(data)
#
# assert len(data['solves']) == 0
#
# chal = gen_challenge(app.db)
# chal_id = chal.id
# flag = gen_flag(app.db, chal=chal_id, flag='flag')
# with client.session_transaction() as sess:
# data = {
# "key": 'flag',
# "nonce": sess.get('nonce')
# }
# r = client.post('/api/v1/challenges/attempt'.format(chal_id), json=data)
#
# data = r.get_data(as_text=True)
# data = json.loads(data)
#
# r = client.get('/solves')
# data = r.get_data(as_text=True)
# data = json.loads(data)
#
# assert len(data['solves']) > 0
#
# team = Teams.query.filter_by(id=2).first()
# team.banned = True
# db.session.commit()
#
# r = client.get('/solves')
# data = r.get_data(as_text=True)
# data = json.loads(data)
#
# team = Teams.query.filter_by(id=2).first()
# assert team.banned
# assert len(data['solves']) > 0
# destroy_ctfd(app)