-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathctfd.py
More file actions
129 lines (95 loc) · 3.7 KB
/
ctfd.py
File metadata and controls
129 lines (95 loc) · 3.7 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import requests
import logging
class CTFd:
def __init__(self, api_key, url):
self._api_key = api_key
self._url = url
self._session = requests.Session()
self._logger = logging.getLogger(__name__)
def delete_flag(self, id):
return self._request(f'flags/{id}', 'DELETE')
def delete_hint(self, id):
return self._request(f'hints/{id}', 'DELETE')
def delete_tag(self, id):
return self._request(f'tags/{id}', 'DELETE')
def get_challenge(self, id):
return self._request(f'challenges/{id}')
def get_challenge_flags(self, id):
return self._request(f'challenges/{id}/flags')
def get_challenge_hints(self, id):
return self._request(f'challenges/{id}/hints')
def get_challenge_list(self):
return self._request('challenges?view=admin')
def get_challenge_requirements(self, id):
return self._request(f'challenges/{id}/requirements')
def get_challenge_tags(self, id):
return self._request(f'challenges/{id}/tags')
def get_challenge_types(self):
return self._request('challenges/types')
def get_config_list(self):
return self._request('configs')
def get_field_list(self):
return self._request('fields')
def get_file_list(self):
return self._request('files')
def get_page_details(self, id):
return self._request(f'pages/{id}')
def get_page_list(self):
return self._request('pages')
def get_tag_list(self, value=None):
if value:
return self._request(f'tags?value={value}')
else:
return self._request('tags')
def get_token_list(self):
return self._request('tokens')
def patch_challenge(self, json, id):
return self._request(f'challenges/{id}', 'PATCH', json)
def patch_config_list(self, json):
return self._request('configs', 'PATCH', json)
def patch_page(self, json, id):
return self._request(f'pages/{id}', 'PATCH', json)
def post_challenge(self, json):
return self._request(f'challenges', 'POST', json)
def post_config_list(self, json):
return self._request('configs/fields', 'POST', json)
def post_tag(self, json):
return self._request(f'tags', 'POST', json)
def post_file(self, files):
return self._request(f'files', 'POST', files=files)
def post_flag(self, json):
return self._request(f'flags', 'POST', json)
def post_hint(self, json):
return self._request(f'hints', 'POST', json)
def post_page(self, json):
return self._request(f'pages', 'POST', json)
def _request(self, path, method='GET', json=None, files=None):
self._logger.debug(f'Hitting CTFd API endpoint {path} with {method} method.')
headers = {
"Authorization": f"Token {self._api_key}",
"Content-Type": "application/json"
}
# if using files variable the correct Content-Type will be added by the requests library
if files:
del headers['Content-Type']
# when called to download a file the full URL is passed in
if "http" in path:
results = self._session.request(
method,
path,
headers=headers,
stream=True
)
return results
path = f"{self._url}/api/v1/{path}"
results = self._session.request(
method,
path,
headers=headers,
json=json,
files=files
)
try:
return results.json()
except ValueError:
raise Exception(f'CTFd API call unexpectedly returned a non-JSON object. Message: {results.text}')