├── log └── .placeholder ├── docker ├── README.md ├── create_db.sql ├── Dockerfile └── docker-compose.yml ├── t ├── checkers │ ├── timeout.pl │ ├── down.pl │ └── up.pl ├── util.t └── basic.t ├── .gitignore ├── public ├── logo.png ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 └── css │ ├── default.css │ ├── bootstrap-theme.css │ └── bootstrap-theme.css.map ├── .gitattributes ├── ansible ├── roles │ ├── monitoring │ │ ├── templates │ │ │ ├── .env.j2 │ │ │ ├── prometheus-servers.j2 │ │ │ ├── prometheus-config.yml.j2 │ │ │ ├── docker-compose.yml.j2 │ │ │ └── queries.yaml │ │ └── tasks │ │ │ └── main.yml │ ├── web │ │ ├── handlers │ │ │ └── main.yml │ │ ├── templates │ │ │ ├── nginx.conf.j2 │ │ │ └── cs.nginx.conf.j2 │ │ └── tasks │ │ │ └── main.yml │ ├── db │ │ ├── handlers │ │ │ └── main.yml │ │ ├── templates │ │ │ └── pg_cs.conf.j2 │ │ └── tasks │ │ │ └── main.yml │ └── common │ │ ├── templates │ │ └── node-compose.yml.j2 │ │ └── tasks │ │ ├── node_exporter.yml │ │ ├── main.yml │ │ └── docker.yml ├── cs-deploy.yml ├── inventory.cfg ├── group_vars │ └── all ├── cs-init.yml ├── cs-stop.yml └── cs-start.yml ├── script └── cs ├── templates ├── admin │ ├── index.html.ep │ ├── info.html.ep │ └── view.html.ep ├── main │ ├── index.html.ep │ └── team.html.ep ├── layouts │ └── default.html.ep └── scoreboard.html.ep ├── lib ├── CS │ ├── Command │ │ ├── board_reload.pm │ │ ├── board_message.pm │ │ ├── reset_db.pm │ │ ├── check_db.pm │ │ ├── add_team.pm │ │ ├── watcher.pm │ │ ├── init_db.pm │ │ └── manager.pm │ ├── Controller │ │ ├── Main.pm │ │ ├── Api.pm │ │ ├── Flags.pm │ │ └── Admin.pm │ └── Model │ │ ├── Flag.pm │ │ ├── Scoreboard.pm │ │ ├── Score.pm │ │ ├── Checker.pm │ │ └── Util.pm └── CS.pm ├── deploy ├── Dockerfile ├── README.md └── docker-compose.yml ├── cpanfile ├── LICENSE ├── cs.test.conf ├── cs.conf.example ├── .github └── workflows │ └── ci.yml ├── CONFIGURE.md ├── README.md └── cs.sql /log/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | These files are used only for development. 2 | -------------------------------------------------------------------------------- /t/checkers/timeout.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | sleep 50; 4 | -------------------------------------------------------------------------------- /docker/create_db.sql: -------------------------------------------------------------------------------- 1 | create database cs_test owner postgres; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | c_s.conf 2 | *.log 3 | *.pid 4 | *.bak 5 | *.swp 6 | .env 7 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/checksystem/HEAD/public/logo.png -------------------------------------------------------------------------------- /t/checkers/down.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | print "some error 😉\n"; 4 | exit 104; 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pl linguist-language=Perl 2 | *.pm linguist-language=Perl 3 | *.t linguist-language=Perl 4 | -------------------------------------------------------------------------------- /ansible/roles/monitoring/templates/.env.j2: -------------------------------------------------------------------------------- 1 | GF_SECURITY_ADMIN_PASSWORD={{ grafana_admin_pass | default('Passw0rd!') }} 2 | -------------------------------------------------------------------------------- /ansible/roles/web/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart nginx 2 | systemd: 3 | name: nginx 4 | state: restarted 5 | -------------------------------------------------------------------------------- /ansible/roles/db/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart postgresql 2 | systemd: 3 | name: postgresql@15-main 4 | state: restarted 5 | -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/checksystem/HEAD/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/checksystem/HEAD/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/checksystem/HEAD/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HackerDom/checksystem/HEAD/public/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /script/cs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use lib 'lib'; 7 | 8 | require Mojolicious::Commands; 9 | Mojolicious::Commands->start_app('CS'); 10 | -------------------------------------------------------------------------------- /templates/admin/index.html.ep: -------------------------------------------------------------------------------- 1 | % layout 'default'; 2 | % title '[admin] ' . app->ctf_name; 3 | 4 | % content_for r => begin 5 | Round <%= $round %> 6 | % end 7 | 8 | %= include 'scoreboard'; 9 | -------------------------------------------------------------------------------- /ansible/roles/monitoring/templates/prometheus-servers.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | - targets: 4 | {% for item in groups['cs'] %} 5 | - {{ hostvars[item]['private_ip'] }}:9100 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM perl:5.40 2 | 3 | ADD cpanfile / 4 | 5 | RUN cpanm -n --installdeps / 6 | RUN cpanm -n DDP 7 | 8 | RUN apt-get update && apt-get install -y less 9 | 10 | WORKDIR /app 11 | COPY . /app 12 | 13 | CMD ["/bin/bash"] 14 | -------------------------------------------------------------------------------- /t/checkers/up.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | my $command = shift; 4 | if ($command eq 'info') { 5 | print "vulns: 1:1:2\npublic_flag_description: user profile\n"; 6 | } else { 7 | print '{"public_flag_id":"911","password":"sEcr3t"}'; 8 | } 9 | exit 101; 10 | -------------------------------------------------------------------------------- /ansible/cs-deploy.yml: -------------------------------------------------------------------------------- 1 | - hosts: cs 2 | roles: 3 | - common 4 | 5 | - hosts: monitoring 6 | roles: 7 | - role: monitoring 8 | tags: monitoring 9 | 10 | - hosts: master 11 | roles: 12 | - web 13 | 14 | - hosts: db 15 | roles: 16 | - db 17 | -------------------------------------------------------------------------------- /lib/CS/Command/board_reload.pm: -------------------------------------------------------------------------------- 1 | package CS::Command::board_reload; 2 | use Mojo::Base 'Mojolicious::Command'; 3 | 4 | has description => 'Send reload to scoreboard via API'; 5 | 6 | sub run { 7 | my $app = shift->app; 8 | 9 | $app->pg->pubsub->notify('reload'); 10 | } 11 | 12 | 1; 13 | -------------------------------------------------------------------------------- /ansible/roles/db/templates/pg_cs.conf.j2: -------------------------------------------------------------------------------- 1 | listen_addresses = '127.0.0.1, {{ pg_cs_host }}' 2 | max_connections = {{ pg_max_connections }} 3 | shared_buffers = {{ pg_shared_buffers }} 4 | work_mem = {{ pg_work_mem }} 5 | random_page_cost = {{ pg_random_page_cost }} 6 | shared_preload_libraries = 'pg_stat_statements' 7 | -------------------------------------------------------------------------------- /lib/CS/Command/board_message.pm: -------------------------------------------------------------------------------- 1 | package CS::Command::board_message; 2 | use Mojo::Base 'Mojolicious::Command'; 3 | 4 | has description => 'Send message to scoreboard via API'; 5 | 6 | sub run { 7 | my $app = shift->app; 8 | my $msg = shift; 9 | 10 | $app->pg->pubsub->notify(message => $msg); 11 | } 12 | 13 | 1; 14 | -------------------------------------------------------------------------------- /ansible/roles/common/templates/node-compose.yml.j2: -------------------------------------------------------------------------------- 1 | version: "2.4" 2 | 3 | services: 4 | node_exporter: 5 | image: prom/node-exporter:latest 6 | command: 7 | - "--path.rootfs=/host" 8 | - "--web.listen-address={{ private_ip }}:9100" 9 | restart: unless-stopped 10 | network_mode: host 11 | pid: host 12 | volumes: 13 | - "/:/host:ro,rslave" 14 | -------------------------------------------------------------------------------- /lib/CS/Command/reset_db.pm: -------------------------------------------------------------------------------- 1 | package CS::Command::reset_db; 2 | use Mojo::Base 'Mojolicious::Command'; 3 | 4 | has description => 'Reset db'; 5 | 6 | sub run { 7 | my $app = shift->app; 8 | 9 | # Jobs 10 | $app->minion->reset({all => 1}); 11 | 12 | # Migrations 13 | $app->pg->migrations->active; 14 | $app->pg->migrations->name('cs')->migrate(0)->migrate; 15 | } 16 | 17 | 1; 18 | -------------------------------------------------------------------------------- /templates/admin/info.html.ep: -------------------------------------------------------------------------------- 1 | % layout 'default'; 2 | % title '[admin] ' . app->ctf_name; 3 | 4 |
<%= $game_status %>8 |
<%= $row->{data} %>
14 | | <%= uc $status->[0] %> | 15 | % } 16 |
| # | 24 |round | 25 |score | 26 | % for my $sid (sort { $a <=> $b } keys %{app->services}) { 27 |<%= app->services->{$sid}{name} %> | 28 | % } 29 |
|---|---|---|---|
| <%= $team->{n} %> | 35 |<%= $team->{round} %> | 36 |<%= $team->{score} %> | 37 | % for my $service (@{$team->{services}}) { 38 |
42 | SLA <%= $service->{sla} %>% FP <%= $service->{fp} %> ⚑
45 | <%= $service->{flags} %>
46 | % if (my $sflags = $service->{sflags}) {
47 | / -<%= $service->{sflags} %>
48 | % }
49 | |
51 | % }
52 |
| <%== uc $status->[0] %> | 7 | % } 8 |
| # | 15 |team | 16 |score | 17 | % for my $sid (sort { $a <=> $b } keys %{app->services}) { 18 |<%== app->services->{$sid}{name} %> | 19 | % } 20 ||
|---|---|---|---|---|
| <%== $team->{n} %><%== $suffix %> | 27 |![]() |
28 |
29 |
32 | <%== $team->{host} %>
33 | |
34 | <%== $team->{score} %> | 35 | % for my $service (@{$team->{services}}) { 36 |
40 | % if (current_route eq 'admin_index') {
41 |
42 |
44 |
45 |
46 |
47 | % }
48 | SLA <%== $service->{sla} %>% FP <%== $service->{fp} %> ⚑
51 | <%== $service->{flags} %>
52 | % if (my $sflags = $service->{sflags}) {
53 | / -<%== $service->{sflags} %>
54 | % }
55 | |
57 | % }
58 |
| round | 50 |status | 51 |result | 52 |
| <%= $result->{round} %> | 56 |<%= $result->{status} %> | 57 |
58 | %= $view_line->('Error', $result->{result}{error});
59 | % for my $state (qw/check put get_1 get_2/) {
60 | % my $r = $result->{result}{$state};
61 | % next unless $r->{command};
62 | % my $status = $checker->status2name->{$result->{status} // ''} // '';
63 | <%= $state %> [vuln_<%= $result->{result}{vuln}{n} %>] (<%= $result->{result}{$state}{ts} %>)
64 |
|
76 |