")
25 | @requires_auth
26 | def endpoint_attack_report(tick):
27 | cursor = mysql.cursor()
28 |
29 | report = get_attack_report(cursor, tick)
30 | return json.dumps(report)
31 |
--------------------------------------------------------------------------------
/scoreboard/frontend/src/components/AcademicSwitch.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router';
3 | import PropTypes from 'prop-types';
4 |
5 | export default class AcademicSwitch extends Component {
6 | static propTypes = {
7 | location: PropTypes.object.isRequired
8 | }
9 |
10 | render() {
11 | return (
12 |
13 |
17 | All
18 |
19 | /
20 |
24 | Academic
25 |
26 |
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/database/settings.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding:utf-8 -*-
3 |
4 | """These are the default settings for the central database API server.
5 |
6 | You should not edit this file. You should edit /ictf/settings.py instead.
7 | """
8 |
9 | # General
10 | DEBUG = True
11 | LISTEN = "0.0.0.0"
12 | API_SECRET = "lol"
13 |
14 | # MySQL
15 | MYSQL_DATABASE_USER = "ictf"
16 | MYSQL_DATABASE_PASSWORD = ""
17 | MYSQL_DATABASE_DB = "ictf"
18 | MYSQL_DATABASE_UNIX_SOCKET = "/var/run/mysqld/mysqld.sock"
19 |
20 | # Flag Generation
21 | FLAG_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
22 | FLAG_LENGTH = 13
23 | FLAG_PREFIX = "FLG"
24 | FLAG_SUFFIX = ""
25 |
26 | # Submitting Flags
27 | MAX_INCORRECT_FLAGS_PER_TICK = 1000
28 | NUMBER_OF_TICKS_FLAG_VALID = 3
29 | ATTACKUP_HEAD_BUCKET_SIZE = 10 # The top N teams can freely attack each other
30 |
31 | # Database API
32 | USER_PASSWORD_SALT = "YOU SHOULD OVERWRITE THIS"
33 |
--------------------------------------------------------------------------------
/gamebot/provisioning/hephaestus_provisioning/ansible-provisioning.yml:
--------------------------------------------------------------------------------
1 | - hosts: localhost
2 | remote_user: root
3 | become: true
4 |
5 | vars:
6 | - ICTF_API_SECRET: "{{ lookup('file', '/opt/ictf/secrets/database-api/secret') }}"
7 |
8 | tasks:
9 |
10 | - name: ictf-database database connection settings.py configuration - set ICTF_API_ADDRESS
11 | replace:
12 | name=/opt/ictf/gamebot/settings.py
13 | regexp="(THE_API_ADDRESS_GOES_HERE)"
14 | replace="{{ ICTF_API_ADDRESS }}"
15 |
16 | - name: ictf-database database connection config.json configuration - set API_SECRET
17 | replace:
18 | name=/opt/ictf/gamebot/settings.py
19 | regexp="(THESECRETPASSPHRASEGOESHERE)"
20 | replace="{{ ICTF_API_SECRET }}"
21 |
22 | - name: logstash - config
23 | copy:
24 | src=./files/logstash.conf
25 | dest=/etc/logstash/conf.d/syslog.conf
26 | owner=root group=root mode="u=rw,g=r,o=r"
--------------------------------------------------------------------------------
/test_service/simplecalc/README.md:
--------------------------------------------------------------------------------
1 | This is a sample service written in C. Feel free to use it as starting point for your code :)
2 |
3 | Run `make` to create a bundle you can sumbit.
4 |
5 |
6 | Files
7 | =====
8 |
9 | - `service/`: the service meat -- only these files get on the VM and are seen by players, put in everything that is needed!
10 | - `scripts/`: benign functionality for your service (flag setting / retrieval), and exploit samples.
11 | - `src/`: submit this as your source (note: this is just for organizers' reference).
12 |
13 |
14 | Recommendations for C
15 | =====================
16 |
17 | Keep in mind that your service will run over the network, not on a terminal.
18 |
19 | Long story short, put a `setbuf(stdin, NULL)` before using `printf()` :)
20 |
21 | If you prefer `read()` / `write()`, see our `in()` and `out()` helpers in [utils.h](src/utils.h). If necessary, you can also use `shutdown()` and `setsockopt()` (see `man tcp`).
22 |
--------------------------------------------------------------------------------
/teamvms/provisioning/hephaestus_provisioning/ansible/roles/teamvm_base/tasks/install_team_utils.yml:
--------------------------------------------------------------------------------
1 |
2 | - name: install requirements
3 | package: name={{ item }} state=latest update_cache=yes
4 | with_items:
5 | - zip
6 | - tmux
7 | - screen
8 | - vim
9 | - emacs
10 | - nano
11 | - curl
12 | - wget
13 | - python2.7
14 | - python3
15 | - python-pip
16 | - python3-pip
17 | - ruby
18 | - perl
19 | - gcc
20 | - binutils
21 | - build-essential
22 | - tcpdump
23 | - docker.io
24 | - ansible
25 | - socat
26 | - openvpn
27 | - net-tools
28 | - iputils-ping
29 |
30 | - name: install docker-compose
31 | get_url:
32 | url: https://github.com/docker/compose/releases/download/1.25.4/docker-compose-Linux-x86_64
33 | dest: /usr/local/bin/docker-compose
34 | mode: 0755
35 |
36 | - name: add user to docker group
37 | command: usermod -aG docker ctf
--------------------------------------------------------------------------------
/scoreboard/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "db_endpoint": "THE_API_ADDRESS_GOES_HERE",
3 | "secret": "THESECRETPASSPHRASEGOESHERE",
4 | "db_port": 5000,
5 | "lock_name": "redis_cache",
6 | "redis_host": "localhost",
7 | "redis_port": 6379,
8 | "redis_db_id": 0,
9 | "polling_sleep_time": 5,
10 | "setup_sleep_time": 30,
11 | "max_requested_ticks": 30,
12 |
13 | "dynamic_endpoints": {
14 | "previous_tick": [
15 | "/services/states/tick/"
16 | ],
17 | "latest": [
18 | "/services/exploited",
19 | "/scores/firstbloods",
20 | "/scores"
21 | ]
22 | },
23 |
24 | "static_endpoints": [
25 | "/services",
26 | "/teams/info"
27 | ],
28 |
29 | "tick_endpoint": {
30 | "key": "tick_id",
31 | "e": "/game/tick/"
32 | },
33 | "game_start": {
34 | "key": "num",
35 | "stat": "/game/state"
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/scoreboard/bin/deploy:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | deploy_dir="/home/deploy/ictf-framework/scoreboard"
4 |
5 | remote_exec()
6 | {
7 | echo "[Running as $1] $2"
8 | ssh ${1}@scoreboard.ictf2015.net -x $2
9 | }
10 |
11 | service()
12 | {
13 | remote_exec root "service ictf-gunicorn $1; service ictf-poller $1; service nginx $1"
14 | }
15 |
16 |
17 | deploy()
18 | {
19 | echo "[Checking eslint errors...]"
20 | npm run eslint && remote_exec deploy "cd $deploy_dir && git pull origin master && npm install && npm run build"
21 | }
22 |
23 |
24 | case "$1" in
25 | deploy)
26 | deploy
27 | ;;
28 | start)
29 | service start
30 | ;;
31 | stop)
32 | service stop
33 | ;;
34 | restart)
35 | service restart
36 | ;;
37 | status)
38 | service status
39 | ;;
40 | *)
41 | echo "Usage: $0 [deploy|start|stop|restart|status]"
42 | exit 1
43 | esac
44 |
45 | exit 0
46 |
--------------------------------------------------------------------------------
/scriptbot/provisioning/ares_provisioning/files/docker-compose.yml.j2:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 |
3 | services:
4 |
5 | ictf_scriptbot:
6 | image: ictf_scriptbot
7 | sysctls:
8 | - net.core.somaxconn=65535
9 |
10 | volumes:
11 | - type: bind
12 | source: /var/run/docker.sock
13 | target: /var/run/docker.sock
14 |
15 | ports:
16 | - "9100:9100"
17 |
18 | environment:
19 | - SCRIPTBOT_ID={{ SCRIPTBOT_ID }}
20 | - IS_LOCAL_REGISTRY=0
21 | - API_SECRET={{ API_SECRET }}
22 | - REGISTRY_USERNAME={{ REGISTRY_USERNAME }}
23 | - REGISTRY_PASSWORD={{ REGISTRY_PASSWORD }}
24 | - REGISTRY_ENDPOINT={{ REGISTRY_ENDPOINT }}
25 | - LOGSTASH_ID=scriptbot{{ SCRIPTBOT_ID }}
26 | - RABBIT_ENDPOINT={{ DISPATCHER_IP }}
27 | - RABBIT_USERNAME=dummy
28 | - RABBIT_PASSWORD=dummy
29 |
--------------------------------------------------------------------------------
/hephaestus/docker/1_scoreboard/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ictf_base
2 |
3 | ENV DEBIAN_FRONTEND=noninteractive
4 | RUN apt-get update && apt-get install -y nginx git redis-server build-essential
5 | RUN apt-get update && apt-get install -y sudo uwsgi daemon
6 |
7 | RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
8 | RUN apt-get update && apt-get install -y nodejs
9 | RUN apt-get update && apt-get install -y python3-pip python3-virtualenv python3-dev uwsgi-plugin-python3 python3-setuptools python3-wheel
10 | #RUN pip install --upgrade pip
11 | #RUN pip --version
12 |
13 | COPY ./scoreboard /opt/ictf/scoreboard
14 |
15 | WORKDIR /opt/ictf/scoreboard
16 |
17 | RUN pip install -r requirements.txt
18 |
19 | RUN ansible-playbook provisioning/hephaestus_provisioning/ansible-provisioning.yml --become --extra-vars ICTF_USER="root" --extra-vars ICTF_FRAMEWORK_DIR_HOST="/opt/ictf" --extra-vars ICTF_API_ADDRESS="database.ictf"
20 |
21 | RUN chmod +x ./start.sh
22 |
23 | ENTRYPOINT ./start.sh
24 |
--------------------------------------------------------------------------------
/scoreboard/bin/stress_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from random import random
3 | from funkload.FunkLoadTestCase import FunkLoadTestCase
4 | from webunit.utility import Upload
5 | from funkload.utils import Data
6 |
7 | class Stress_Test(FunkLoadTestCase):
8 | def setUp(self):
9 | self.server_url = self.conf_get('main', 'url')
10 | self.setBasicAuth('team@shellphish.net', 'testing!')
11 | pass
12 |
13 | def test_simple(self):
14 | # The description should be set in the configuration file
15 | server_url = self.server_url
16 | # begin test ---------------------------------------------
17 | nb_time = self.conf_getInt('test_simple', 'nb_time')
18 | ap_list = self.conf_get('test_simple', 'ap_list').split(",")
19 | #print "aplist,", ap_list
20 | for i in range(nb_time):
21 | for ap in ap_list:
22 | self.get('https://'+server_url+ap, description='Get URL')
23 | # end test ------------
24 |
--------------------------------------------------------------------------------
/router/game/README.md:
--------------------------------------------------------------------------------
1 | # Game Router
2 |
3 | The game router should have two interfaces:
4 | - eth0 should be the public interface (reachable by the teams, so that they can access the game network)
5 | - eth1 should be the game network
6 |
7 | If the VMs are hosted by the organizers, the organizers must make sure that they have a dedicated route from the game router to their VMs.
8 | For instance, if one can reach the vulnerable VMs via eth0:
9 | ```
10 | TEAMS=""
11 | for TEAMID in ${TEAMS}; do
12 | route add 10.7.${TEAMID}.2 dev eth1
13 | done
14 | ```
15 |
16 | Otherwise the game router will try to reach them via the team's router, which will fail if the organizers host the vulnerable VM.
17 | If the organizers use the default configuration, this should work out of the box.
18 |
19 | If the teams host the vulnerable boxes themselves, the organizers need to add the following line to the ictf-in-a-box.conf (OpenVPN configuration file):
20 |
21 | ```
22 | client-to-client
23 | ```
--------------------------------------------------------------------------------
/ares/aws/util_scripts/create_random_teams.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 | import json
5 | import hashlib
6 |
7 | with open(sys.argv[1], 'r') as f:
8 | d = json.load(f)
9 |
10 | teams = []
11 | teams.append({
12 | "name": "Shellphish",
13 | "url": "-",
14 | "country": "USA",
15 | "logo": "",
16 | "email": "shellphish@pineapple.on.pizza",
17 | "validated": 1,
18 | "academic_team": 1,
19 | "id": 1,
20 | "flag_token": "aaaaaaaaaaaaaaaaaaaa",
21 | "organizer_hosted": True
22 | })
23 |
24 | for team_id in range(2, int(sys.argv[2])+1):
25 | t = dict(teams[-1])
26 | t['name'] = 'COGLIONI{}'.format(team_id)
27 | t['id'] = team_id
28 | t['flag_token'] = hashlib.md5(t['name'].encode()).hexdigest()[:20]
29 | t['email'] = t['name'].lower() + "@pineapple.on.pizza"
30 | t['organizer_hosted'] = True
31 | teams.append(t)
32 |
33 | d['teams'] = teams
34 | with open(sys.argv[1], 'w') as f:
35 | json.dump(d, f, indent=2)
36 |
--------------------------------------------------------------------------------
/database/reset_db.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """Resets the database
5 | """
6 |
7 | from __future__ import print_function
8 |
9 | import random
10 |
11 | from api import mysql
12 |
13 |
14 | # Helper functions
15 | #
16 | def _init_database():
17 | """Initialze the database tables"""
18 |
19 | database = mysql.connect()
20 | cursor = database.cursor(raw=True, buffered=False)
21 |
22 | # Wipe the database and setup new one
23 | with open("/home/ictf/ictf-framework/database/support/database.sql", "r") as file_:
24 | setup_script = file_.read()
25 |
26 | # The library returns a generator for each statement, we need to eval all
27 | # of them.
28 | list(cursor.execute(setup_script, multi=True))
29 |
30 | # Create the game
31 | game_id = random.randint(0, 1000000)
32 | cursor.execute("INSERT INTO game (id) VALUES (%s)", (game_id,))
33 |
34 | database.commit()
35 |
36 |
37 | def main(): # pylint:disable=missing-docstring
38 | _init_database()
39 |
40 | if __name__ == "__main__":
41 | main()
42 |
--------------------------------------------------------------------------------
/scoring_ictf/scoring_ictf/game_state_interface.py:
--------------------------------------------------------------------------------
1 | class GameStateInterface(object):
2 | def __init__(self):
3 | self._team_ids_to_names = None
4 | self._service_ids_to_names = None
5 |
6 | def _team_id_to_name_map(self):
7 | raise NotImplementedError
8 |
9 | def _service_id_to_name_map(self):
10 | raise NotImplementedError
11 |
12 | def _scored_events_for_tick(self, tick):
13 | raise NotImplementedError
14 |
15 | @property
16 | def team_id_to_name_map(self):
17 | if self._team_ids_to_names is None:
18 | self._team_ids_to_names = self._team_id_to_name_map()
19 | return self._team_ids_to_names
20 |
21 | @property
22 | def service_id_to_name_map(self):
23 | if self._service_ids_to_names is None:
24 | self._service_ids_to_names = self._service_id_to_name_map()
25 | return self._service_ids_to_names
26 |
27 | def scored_events_for_tick(self, tick):
28 | # TODO: maybe cache here? or do we cache in the database side?
29 | return self._scored_events_for_tick(tick)
30 |
--------------------------------------------------------------------------------
/database/dump_teams_json.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import json
5 | import mysql.connector
6 |
7 | db_pass = open('/opt/ictf/secrets/database-api/mysql', "r").read().rstrip()
8 | conn = mysql.connector.connect(user='ictf', password=db_pass, database='ictf',
9 | unix_socket='/var/run/mysqld/mysqld.sock',
10 | get_warnings=True,
11 | raise_on_warnings=True) # pylint:disable=star-args
12 | cursor = conn.cursor(dictionary=True)
13 |
14 | cursor.execute("SELECT teams.id, name, url, country, logo, email, flag_token, login_token, root_key, ctf_key, ip, port FROM teams JOIN team_vm_key ON teams.id=team_vm_key.team_id")
15 |
16 | teams = {}
17 | vals = cursor.fetchall()
18 | for row in vals:
19 | team_id = row["id"]
20 | row["logo"] = str(row["logo"])
21 |
22 | teams["team" + str(team_id)] = row
23 |
24 | with open('/opt/ictf/database/team_info.json', 'w+') as fp:
25 | json.dump({"teams": teams}, fp, indent=2)
26 |
27 | conn.close()
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/teamvms/provisioning/hephaestus_provisioning/ansible/ansible-provisioning.yml:
--------------------------------------------------------------------------------
1 | - hosts: all
2 | remote_user: root
3 | become: true
4 |
5 | vars:
6 | - GAME_CONFIG: "{{ lookup('file', '{{ GAME_CONFIG_PATH }}') | from_json }}"
7 | - SERVICES: "{{ GAME_CONFIG | json_query('services[?state==`enabled`].name') }}"
8 | - TEAM_NAMES: "{{ GAME_CONFIG | json_query('teams[].name') }}"
9 | - HOST_SERVICES_PATH: "{{ GAME_CONFIG.service_metadata.host_dir }}"
10 | - GUEST_SERVICES_PATH: "{{ GAME_CONFIG.service_metadata.guest_dir }}"
11 |
12 | # roles:
13 | # - teamvm_base
14 |
15 | tasks:
16 | - name: install base dependencies
17 | include_role:
18 | name: teamvm_base
19 | when: BASE is defined
20 |
21 | - name: install primed dependencies
22 | include_role:
23 | name: teamvm_primed
24 | vars:
25 | PRIMER_GUEST_SERVICES_PATH: "{{ GUEST_SERVICES_PATH }}"
26 | PRIMER_HOST_SERVICES_PATH: "{{ HOST_SERVICES_PATH }}"
27 | PRIMER_SERVICES: "{{ SERVICES }}"
28 | PRIMER_LOCAL: "{{ LOCAL }}"
29 | when: PRIMER is defined
30 |
--------------------------------------------------------------------------------
/teaminterface/support/nginx.conf:
--------------------------------------------------------------------------------
1 | {% if ENABLE_SSL == "1" %}
2 | server {
3 | listen 80 default_server;
4 | server_name _; # catch all names
5 |
6 | return 301 {{ ICTF_TI_SERVER_URL }};
7 | }
8 |
9 | server {
10 | listen 443 ssl;
11 | server_name _;
12 |
13 | ssl_certificate {{ SSL_CERTIFICATE_PATH }};
14 | ssl_certificate_key {{ SSL_CERTIFICATE_KEY_PATH }};
15 |
16 | return 301 {{ ICTF_TI_SERVER_URL }};
17 | }
18 | {% endif %}
19 |
20 | server {
21 | {% if ENABLE_SSL == "0" %}
22 | listen 80 default_server;
23 | server_name _; # catch all names
24 | {% endif %}
25 |
26 | {% if ENABLE_SSL == "1" %}
27 | listen 443 ssl;
28 | server_name {{ ICTF_TI_SERVER_DOMAIN }};
29 |
30 | ssl_certificate {{ SSL_CERTIFICATE_PATH }};
31 | ssl_certificate_key {{ SSL_CERTIFICATE_KEY_PATH }};
32 | {% endif %}
33 |
34 | location / {
35 | uwsgi_pass unix:///tmp/ictf-api.sock;
36 | include uwsgi_params;
37 | client_max_body_size 2G;
38 | uwsgi_read_timeout 60;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/database/support/mysql-connector-python-2.1.3/tests/data/ssl/tests_client_cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIC9TCCAd0CAQEwDQYJKoZIhvcNAQEFBQAwQjElMCMGA1UECwwcTXlTUUxDb25u
3 | ZWN0b3JQeXRob24gUm9vdCBDQTEZMBcGA1UEAwwQTXlDb25uUHkgUm9vdCBDQTAe
4 | Fw0xMzAzMjYxNTM1NTJaFw0yMjA0MTQxNTM1NTJaMD8xKTAnBgNVBAsMIE15U1FM
5 | Q29ubmVjdG9yUHl0aG9uIENsaWVudCBDZXJ0MRIwEAYDVQQDDAlsb2NhbGhvc3Qw
6 | ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXbL7sr/k/W4LwwzTKJj5i
7 | 1QtcZL0tMyBhAwuI7XQVyJBVvY7dRUM+G30ADOcUw5DscYbkkVu3L2NtsnmuyB8o
8 | 0Y5bbHpTv4xTrVfsQuDkMLe+/LwFfL7XrY1Bm13xdEn345b6edfvhre7eatCgIaG
9 | IKfFr5JDv5oN4faGEJpqYahE/WdxM7zv6xb7Wx+yqLlezldU34VcLcghi8zfDkxb
10 | Fb4cZSgko/9RT7lTUGBJSSgITnq3Re0qANah7UbqFkTM2wfltoXGerbWMYuzOfQo
11 | 5r0FiScjuvACkDALHAdUbX4UbXasArqpGovyVqHp4OWu3FWRfcCUnxAxfj3G3x79
12 | AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFi+U6Fyc1L0qCTCiMvUMQuXacnOMH4q
13 | rHm7qDKkHHcMMGsspNXvLcVKEwJrX3dhP3dZ52eKyFsOjuTkO9eU5H8V2alO8iGD
14 | Zb6vHT/pQRInoc39SVDFx1QnJ7RlC2Z99xzncHMQChSlDCC+Lft/K5am7vXFwQ3e
15 | icfLqmR5hz6nc+opnPc7WbQu/cc7PesP5uroyKScYoqAiDJ2cKQJQFPM4Cvt/KZ3
16 | 22H/yCyQNkplIcrlQRF+l+sInNlJZr36INF0o91GcucyuLQzOXUn0L5eAyFzA9RQ
17 | 8xkVztqRN++CgbGAhqIt8ERBtxBvCpNxuFpgm4dPKCTLm+r7fJcKwDI=
18 | -----END CERTIFICATE-----
19 |
--------------------------------------------------------------------------------