forked from glzjin/CTFd-Whale
-
Notifications
You must be signed in to change notification settings - Fork 29
/
challenge_type.py
108 lines (93 loc) · 3.66 KB
/
challenge_type.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from flask import Blueprint
from CTFd.models import (
db,
Flags,
)
from CTFd.plugins.challenges import BaseChallenge
from CTFd.plugins.dynamic_challenges import DynamicValueChallenge
from CTFd.plugins.flags import get_flag_class
from CTFd.utils import user as current_user
from .models import WhaleContainer, DynamicDockerChallenge
from .utils.control import ControlUtil
class DynamicValueDockerChallenge(BaseChallenge):
id = "dynamic_docker" # Unique identifier used to register challenges
name = "dynamic_docker" # Name of a challenge type
# Blueprint used to access the static_folder directory.
blueprint = Blueprint(
"ctfd-whale-challenge",
__name__,
template_folder="templates",
static_folder="assets",
)
challenge_model = DynamicDockerChallenge
@classmethod
def read(cls, challenge):
challenge = DynamicDockerChallenge.query.filter_by(id=challenge.id).first()
data = {
"id": challenge.id,
"name": challenge.name,
"value": challenge.value,
"initial": challenge.initial,
"decay": challenge.decay,
"minimum": challenge.minimum,
"description": challenge.description,
"category": challenge.category,
"state": challenge.state,
"max_attempts": challenge.max_attempts,
"type": challenge.type,
"type_data": {
"id": cls.id,
"name": cls.name,
"templates": cls.templates,
"scripts": cls.scripts,
},
}
return data
@classmethod
def update(cls, challenge, request):
data = request.form or request.get_json()
for attr, value in data.items():
# We need to set these to floats so that the next operations don't operate on strings
if attr in ("initial", "minimum", "decay"):
value = float(value)
if attr == 'dynamic_score':
value = int(value)
setattr(challenge, attr, value)
if challenge.dynamic_score == 1:
return DynamicValueChallenge.calculate_value(challenge)
db.session.commit()
return challenge
@classmethod
def attempt(cls, challenge, request):
data = request.form or request.get_json()
submission = data["submission"].strip()
flags = Flags.query.filter_by(challenge_id=challenge.id).all()
if len(flags) > 0:
for flag in flags:
if get_flag_class(flag.type).compare(flag, submission):
return True, "Correct"
return False, "Incorrect"
else:
user_id = current_user.get_current_user().id
q = db.session.query(WhaleContainer)
q = q.filter(WhaleContainer.user_id == user_id)
q = q.filter(WhaleContainer.challenge_id == challenge.id)
records = q.all()
if len(records) == 0:
return False, "Please solve it during the container is running"
container = records[0]
if container.flag == submission:
return True, "Correct"
return False, "Incorrect"
@classmethod
def solve(cls, user, team, challenge, request):
super().solve(user, team, challenge, request)
if challenge.dynamic_score == 1:
DynamicValueChallenge.calculate_value(challenge)
@classmethod
def delete(cls, challenge):
for container in WhaleContainer.query.filter_by(
challenge_id=challenge.id
).all():
ControlUtil.try_remove_container(container.user_id)
super().delete(challenge)