Skip to content

Commit c34e885

Browse files
author
Markus Bauer
committed
Updates from saarCTF 2022
1 parent 87337c5 commit c34e885

File tree

83 files changed

+5534
-9392
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+5534
-9392
lines changed

.gitlab-ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
image: debian:buster
1+
image: debian:bullseye
22

33
variables:
44
# Initialize submodules
@@ -33,9 +33,9 @@ cache:
3333
- .cache
3434

3535
services:
36-
- name: postgres:11
37-
- name: redis:5.0-alpine
38-
- name: rabbitmq:3.7-management-alpine
36+
- name: postgres:13
37+
- name: redis:6.0-alpine
38+
- name: rabbitmq:3.8-management-alpine
3939

4040
flag-submission:
4141
before_script:

.idea/codeStyles/Project.xml

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/saarctf.iml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

checker_runner/checker_execution.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def execute_checker(package: str, script: str, service_id: int, team_id: int, ro
4545
:return: (db-status, message) The (db) status of this execution, and an error message (if applicable)
4646
"""
4747
import pwnlib
48+
import pwnlib.exception
4849

4950
team = gamelib.Team(team_id, '#' + str(team_id), team_id_to_vulnbox_ip(team_id))
5051
try:
@@ -72,7 +73,7 @@ def execute_checker(package: str, script: str, service_id: int, team_id: int, ro
7273
gamelogger.GameLogger.log(f'----- retrieve_flags({round - 1}) -----')
7374
checker.retrieve_flags(team, round - 1)
7475
if result: result.retrieved = True
75-
elif round == -1:
76+
elif round <= -1:
7677
# Test run - retrieve the flag we just have set
7778
gamelogger.GameLogger.log(f'----- retrieve_flags({round}) -----')
7879
checker.retrieve_flags(team, round)
@@ -99,6 +100,9 @@ def execute_checker(package: str, script: str, service_id: int, team_id: int, ro
99100
except requests.ConnectionError as e:
100101
traceback.print_exc()
101102
return 'OFFLINE', 'Connection timeout'
103+
except requests.exceptions.Timeout as e:
104+
traceback.print_exc()
105+
return 'OFFLINE', 'Connection timeout'
102106
except pwnlib.exception.PwnlibException as e:
103107
if 'Could not connect to' in e.args[0]:
104108
return 'OFFLINE', str(e.args[0])

checker_runner/package_loader.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ def load_module_from_package(cls, package: str, filename: str) -> ModuleType:
6565
# Import module
6666
cls.ensure_package_exists(package)
6767
spec = importlib.util.spec_from_file_location(modulename, CHECKER_PACKAGES_PATH + '/' + package + '/' + filename)
68+
if spec is None:
69+
raise Exception('Spec/Loader is not present')
6870
module = importlib.util.module_from_spec(spec)
6971
if spec.loader is None:
7072
raise Exception('Loader is not present')

ci/install_dependencies.sh

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ set -euxo pipefail
55
apt-get update
66
apt-get install -y \
77
curl
8-
curl -sL https://deb.nodesource.com/setup_12.x | bash
8+
#curl -sL https://deb.nodesource.com/setup_12.x | bash
99
apt-get -y install --no-install-recommends \
10-
clang-7 \
10+
clang-11 \
1111
cmake \
1212
g++ \
1313
git \
@@ -16,15 +16,23 @@ apt-get -y install --no-install-recommends \
1616
libpq-dev \
1717
libssl-dev \
1818
nodejs \
19-
postgresql-client-11 \
19+
postgresql-client-13 \
2020
postgresql-server-dev-all \
2121
psmisc \
2222
python2.7 \
23+
python3 \
2324
python3-dev \
2425
python3-pip \
2526
python3-setuptools \
2627
python3-wheel \
27-
python3-cryptography
28+
python3-cryptography \
29+
python3-redis python3-psycopg2 \
30+
python3-flask python3-flask-api python3-flask-migrate python3-flask-restful \
31+
python3-sqlalchemy \
32+
python3-setproctitle python3-filelock python3-htmlmin python3-ujson \
33+
nodejs npm
34+
35+
ln -s /usr/bin/nodejs /usr/local/bin/node
2836

2937
# Install pip dependencies
3038
python3 -m pip install -r requirements.txt

ci/test-demo-checker.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ def spawn_gamseserver_components() -> t.List[process]:
109109
"--hostname=ident@%h",
110110
],
111111
stderr=stderr,
112+
# stdout must be a pipe, not a pty. but stderr must also be captured. pwntools can't do this, so we work around:
113+
stdout=subprocess.PIPE,
114+
preexec_fn=lambda: os.dup2(1, 2)
112115
)
113116

114117
# Ensure all processes are started

ci/test-flag-submission.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ flask run --host=0.0.0.0 &
1111
# Build flag submission server
1212
mkdir flag-submission-server/build
1313
pushd flag-submission-server/build
14-
cmake -DCMAKE_BUILD_TYPE=Release ..
14+
cmake -DCMAKE_BUILD_TYPE=Release -DPostgreSQL_ADDITIONAL_VERSIONS=13 ..
1515
make
1616
popd
1717

config.sample.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
"scoreboard_path": "/dev/shm/scoreboard",
2727
"checker_packages_path": "/dev/shm/packages",
2828
"logo_input_path": "...",
29+
"patches_path": "/dev/shm/patches",
30+
"patches_public_path": "/dev/shm/patches-webroot",
2931
"flower_url": "http://localhost:5555/",
3032
"coder_url": "",
3133
"scoreboard_url": "",
@@ -45,6 +47,7 @@
4547
"team_range": [127, [200, 256, 0], [1, 200, 0], 0, 24],
4648
"vpn_host": "10.32.250.1",
4749
"vpn_peer_ips": [10, [200, 256, 48], [1, 200, 0], 1],
48-
"gameserver_ip": "10.32.250.2"
50+
"gameserver_ip": "10.32.250.2",
51+
"gameserver_range": "10.32.250.0/24"
4952
}
5053
}

controlserver/app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import controlserver.endpoints.flags
4848
import controlserver.endpoints.influx
4949
import controlserver.endpoints.services
50+
import controlserver.endpoints.patches
5051
from controlserver.models import init_models
5152
from controlserver.model_admin import register_admin
5253

@@ -57,6 +58,7 @@
5758
app.register_blueprint(controlserver.endpoints.flags.app)
5859
app.register_blueprint(controlserver.endpoints.influx.app)
5960
app.register_blueprint(controlserver.endpoints.services.app)
61+
app.register_blueprint(controlserver.endpoints.patches.app)
6062
app.register_blueprint(controlserver.endpoints.api.app)
6163
init_models(app)
6264
register_admin(app)

controlserver/dispatcher.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def __init__(self):
4040
def dispatch_checker_scripts(self, roundnumber: int):
4141
redis = get_redis_connection()
4242
if CONFIG.get('dispatcher_check_vpn_status', False):
43-
teams = Team.query.filter(Team.vpn_connected == True).all()
43+
teams = Team.query.filter((Team.vpn_connected == True) | (Team.vpn2_connected == True)).all()
4444
else:
4545
teams = Team.query.all()
4646
services = Service.query.order_by(Service.id).filter(Service.checker_enabled == True).all()
@@ -209,7 +209,7 @@ def create_flagid_json(self, teams: List[Team], services: List[Service], roundnu
209209
'id': team.id,
210210
'name': team.name,
211211
'ip': team.vulnbox_ip,
212-
'online': team.vpn_connected
212+
'online': team.vpn_connected or team.vpn2_connected
213213
} for team in teams]
214214
}
215215
for service in services:

controlserver/endpoints/api.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@ def api_grafana_warning():
1616
return 'Invalid', 500
1717
if data['state'] != 'alerting':
1818
return 'We only want alerts', 500
19-
text = data['message'] + '\nRule: ' + data['ruleName'] + '\n' + data['ruleUrl']
20-
log('Grafana', data['title'], text, LogMessage.WARNING)
19+
if 'ruleName' in data:
20+
text = data['message'] + '\nRule: ' + data['ruleName'] + '\n' + data['ruleUrl']
21+
log('Grafana', data['title'], text, LogMessage.WARNING)
22+
elif 'alerts' in data:
23+
for alert in data['alerts']:
24+
if alert['status'] != 'firing':
25+
continue
26+
title = '[Grafana] ' + alert['labels']['alertname']
27+
if 'rulename' in alert['labels']:
28+
title += ' / ' + alert['labels']['rulename']
29+
text = []
30+
if 'dashboardURL' in alert and alert['dashboardURL']:
31+
text.append('Dashboard: ' + alert['dashboardURL'])
32+
if 'panelURL' in alert and alert['panelURL']:
33+
text.append('Panel: ' + alert['panelURL'])
34+
log('Grafana', title, '\n'.join(text), LogMessage.WARNING)
35+
else:
36+
text = data['title'] + '\n' + data['message']
37+
log('Grafana', data['title'], text, LogMessage.WARNING)
2138
return 'OK'

controlserver/endpoints/pages.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,11 @@ def overview_components():
117117
@app.route('/overview/vpn')
118118
def overview_vpn():
119119
vpn = VPNControl()
120-
teams = [{'id': team.id, 'name': team.name, 'network': team_id_to_network_range(team.id), 'tick': tick} for team, tick in vpn.get_banned_teams()]
121-
teams_online = Team.query.filter(Team.vpn_connected == True).count()
122-
teams_online_once = Team.query.filter(Team.vpn_connected == False, Team.vpn_last_connect != None).count()
123-
teams_offline = Team.query.filter(Team.vpn_connected == False, Team.vpn_last_connect == None).count()
120+
banned_teams = [{'id': team.id, 'name': team.name, 'network': team_id_to_network_range(team.id), 'tick': tick} for team, tick in vpn.get_banned_teams()]
121+
open_teams = [{'id': team.id, 'name': team.name, 'network': team_id_to_network_range(team.id)} for team in vpn.get_open_teams()]
122+
teams_online = Team.query.filter((Team.vpn_connected == True) | (Team.vpn2_connected == True)).count()
123+
teams_online_once = Team.query.filter((Team.vpn_connected == False) & (Team.vpn2_connected == False), Team.vpn_last_connect != None).count()
124+
teams_offline = Team.query.filter((Team.vpn_connected == False) & (Team.vpn2_connected == False), Team.vpn_last_connect == None).count()
124125

125126
# format: dt_bytes, dt_syns, dg_bytes, dg_syns, ut_bytes, ut_syns, ug_bytes, ug_syns
126127
# list of last X time points, ascending
@@ -134,7 +135,7 @@ def overview_vpn():
134135
trafficstats.append(list(map(int, line[1:])))
135136

136137
return jsonify({
137-
'state': vpn.get_state().value, 'banned': teams,
138+
'state': vpn.get_state().value, 'banned': banned_teams, 'permissions': open_teams,
138139
'teams_online': teams_online, 'teams_online_once': teams_online_once, 'teams_offline': teams_offline,
139140
'traffic_stats': trafficstats[::-1],
140141
'traffic_stats_keys': trafficstats_keys[::-1]
@@ -150,6 +151,10 @@ def overview_set_vpn():
150151
vpn.ban_team(request.json['ban']['team_id'], request.json['ban']['tick'])
151152
if 'unban' in request.json:
152153
vpn.unban_team(request.json['unban'])
154+
if 'add_permission' in request.json:
155+
vpn.add_permission_team(request.json['add_permission'])
156+
if 'remove_permission' in request.json:
157+
vpn.remove_permission_team(request.json['remove_permission'])
153158
return 'OK'
154159

155160

0 commit comments

Comments
 (0)