Skip to content

Commit 93c3a13

Browse files
authored
Merge pull request #40 from Jacute/dev
v0.2.0
2 parents f925c94 + d3f503c commit 93c3a13

File tree

139 files changed

+7673
-355
lines changed

Some content is hidden

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

139 files changed

+7673
-355
lines changed

.env

Lines changed: 0 additions & 2 deletions
This file was deleted.

.github/workflows/tests.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: tests
2+
3+
on:
4+
push:
5+
branches: [ "**" ]
6+
pull_request:
7+
branches: [ master, dev ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Set up Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version: '1.25.3'
19+
20+
- name: Build jacfarm-api
21+
run: cd ./jacfarm-api && go build -v ./...
22+
23+
- name: Build config_loader
24+
run: cd ./workers/config_loader && go build -v ./...
25+
26+
- name: Build exploit-runner
27+
run: cd ./workers/exploit_runner && go build -v ./...
28+
29+
- name: Build flag-sender
30+
run: cd ./workers/flag_sender && go build -v ./...
31+
32+
tests:
33+
runs-on: ubuntu-latest
34+
steps:
35+
- uses: actions/checkout@v4
36+
37+
- name: Set up Go
38+
uses: actions/setup-go@v5
39+
with:
40+
go-version: '1.25.3'
41+
42+
- name: Install gocovmerge
43+
run: go install github.com/wadey/gocovmerge@latest
44+
45+
- name: Run tests on jacfarm-api
46+
run: make coverage
47+
48+
# --- Upload to Codecov ---
49+
- name: Upload coverage reports to Codecov
50+
uses: codecov/codecov-action@v5
51+
with:
52+
token: ${{ secrets.CODECOV_TOKEN }}
53+
slug: Jacute/JacFARM
54+
files: coverage.out
55+
56+
# --- Upload to Coveralls ---
57+
- name: Upload coverage to Coveralls
58+
uses: coverallsapp/github-action@v2
59+
with:
60+
github-token: ${{ secrets.GITHUB_TOKEN }}
61+
path-to-lcov: coverage.out

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ todo
22
database.db
33
error_writer
44
coverage.html
5-
volumes
5+
volumes
6+
backend.sh
7+
.env

Makefile

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.PHONY: help up down clean-db clean-all reset coverage
2+
13
# Цвета
24
GREEN := \033[0;32m
35
PURPLE := \033[0;35m
@@ -18,13 +20,26 @@ up: ## Start services
1820
@echo "$(GREEN)[$(PURPLE)start$(GREEN)]$(RED) Starting services$(RESET)"
1921
@mkdir -p volumes/exploits
2022
@sudo chown -R 1000:1000 ./volumes/exploits
21-
@echo "JACFARM_API_KEY=$(JACFARM_API_KEY)" > .env
22-
@echo "ADMIN_PASS=$(ADMIN_PASS)" >> .env
23-
@echo "$(PURPLE)Farm api key$(RESET) - $(JACFARM_API_KEY)"
24-
@echo "$(PURPLE)Farm admin creds$(RESET) - admin:$(ADMIN_PASS)"
23+
@touch .env
24+
25+
@if grep -q '^JACFARM_API_KEY=' .env; then \
26+
printf "$(PURPLE)Farm api key$(RESET) - %s\n" "$$(grep '^JACFARM_API_KEY=' .env | cut -d'=' -f2-)"; \
27+
else \
28+
echo "JACFARM_API_KEY=$(JACFARM_API_KEY)" >> .env; \
29+
printf "$(PURPLE)Farm api key$(RESET) - %s\n" "$(JACFARM_API_KEY)"; \
30+
fi
31+
32+
@if grep -q '^ADMIN_PASS=' .env; then \
33+
printf "$(PURPLE)Farm creds$(RESET) - admin:%s\n" "$$(grep '^ADMIN_PASS=' .env | cut -d'=' -f2-)"; \
34+
else \
35+
echo "ADMIN_PASS=$(ADMIN_PASS)" >> .env; \
36+
printf "$(PURPLE)Farm creds$(RESET) - admin:%s\n" "$(ADMIN_PASS)"; \
37+
fi
38+
2539
@sudo docker compose --env-file .env up --build -d
2640
@echo "$(GREEN)Services started$(RESET)"
2741

42+
2843
down: ## Stop services
2944
@echo "$(GREEN)[$(PURPLE)stop$(GREEN)]$(RED) Stopping services$(RESET)"
3045
@sudo docker compose down
@@ -39,3 +54,37 @@ clean-all: ## Remove all volumes (db, rabbitmq, exploits)
3954
@rm .env
4055

4156
reset: down clean-all up ## Full reset: stop, clean and restart
57+
58+
coverage:
59+
@echo "$(GREEN)Running tests$(RESET)"
60+
61+
@cd jacfarm-api && \
62+
PKGS=$$(go list ./... | grep -vE 'mocks|cmd/jacfarm-api' || true) && \
63+
if [ -z "$$PKGS" ]; then echo "No packages found in jacfarm-api"; exit 0; fi && \
64+
CSV=$$(echo $$PKGS | tr ' ' ',') && \
65+
echo "Running go test for: $$PKGS" && \
66+
go test -v -race -coverpkg=$$CSV -covermode=atomic -coverprofile=../jacfarm-api.out $$PKGS
67+
68+
@cd workers/config_loader && \
69+
PKGS=$$(go list ./... | grep -vE 'mocks|cmd/config_loader' || true) && \
70+
if [ -z "$$PKGS" ]; then echo "No packages found in config_loader"; exit 0; fi && \
71+
CSV=$$(echo $$PKGS | tr ' ' ',') && \
72+
echo "Running go test for: $$PKGS" && \
73+
go test -v -race -coverpkg=$$CSV -covermode=atomic -coverprofile=../../config_loader.out $$PKGS
74+
75+
@cd workers/exploit_runner && \
76+
PKGS=$$(go list ./... | grep -vE 'mocks|cmd/exploit_runner' || true) && \
77+
if [ -z "$$PKGS" ]; then echo "No packages found in exploit_runner"; exit 0; fi && \
78+
CSV=$$(echo $$PKGS | tr ' ' ',') && \
79+
echo "Running go test for: $$PKGS" && \
80+
go test -v -race -coverpkg=$$CSV -covermode=atomic -coverprofile=../../exploit_runner.out $$PKGS
81+
82+
@cd workers/flag_sender && \
83+
PKGS=$$(go list ./... | grep -vE 'mocks|cmd/flag_sender' || true) && \
84+
if [ -z "$$PKGS" ]; then echo "No packages found in flag_sender"; exit 0; fi && \
85+
CSV=$$(echo $$PKGS | tr ' ' ',') && \
86+
echo "Running go test for: $$PKGS" && \
87+
go test -v -race -coverpkg=$$CSV -covermode=atomic -coverprofile=../../flag_sender.out $$PKGS
88+
89+
gocovmerge jacfarm-api.out config_loader.out exploit_runner.out flag_sender.out > coverage.out
90+
rm exploit_runner.out flag_sender.out jacfarm-api.out config_loader.out

README.md

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,79 @@
11
# JacFARM
22

3-
Exploit farm for attack-defense CTF competition
3+
<p align="center">
4+
<picture>
5+
<img alt="JacFARM Logo" src="https://raw.githubusercontent.com/Jacute/JacFARM/refs/heads/master/docs/logo.png" width="300">
6+
</picture>
7+
</p>
8+
<p align="center">
9+
<strong>Exploit farm for attack-defense CTF competition</strong>
10+
</p>
11+
<p align="center">
12+
<a href="#quick-start">Quick Start</a> •
13+
<a href="#features">Features</a> •
14+
<a href="#components">Components</a>
15+
</p>
16+
<p align="center">
17+
<a href="https://github.com/Jacute/JacFARM/actions"><img src="https://github.com/Jacute/JacFARM/actions/workflows/tests.yml/badge.svg" alt="CI Status"></a>
18+
<a href="https://codecov.io/gh/ollelogdahl/concord"><img alt="Codecov" src="https://codecov.io/gh/Jacute/JacFARM/master/master/graph/badge.svg"></a>
19+
<a href="#"><img alt="Coveralls" src="https://coveralls.io/repos/github/Jacute/JacFARM/badge.svg?branch=master"></a>
20+
<a href="https://github.com/Jacute/JacFARM/releases"><img alt="Release" src="https://img.shields.io/github/v/release/Jacute/JacFARM"></a>
21+
</p>
22+
23+
## Quick start
24+
25+
### Dependencies
26+
27+
- Docker
28+
- Docker Compose
29+
- Make
30+
31+
### Start
32+
33+
1. Configure *config.yml* for your competition. A detailed description of the quick configuration is [here](./docs/config.md)
34+
35+
2. Start the farm
36+
```bash
37+
make up
38+
```
39+
40+
Credentials for basic auth and the token for sending flags via start_exploit.py will be printed to stdout.
41+
42+
3. After the game ends, turn off the farm and clean the database and queue
43+
```bash
44+
make down
45+
make clean-all
46+
```
47+
48+
## Features
49+
50+
- Uploading exploits in ui
51+
- Real-time configuration farm options like number of concurrently running exploits, the size of the flag sending batch, team ip addresses, etc
52+
- The ability to [change the plugin for sending flags to jury](./docs/flag_sender/flag_sender.md).
53+
- There are already two sending plugins: [forcad_http](./workers/flag_sender/plugins/forcad_http/client.go) and [saarctf_tcp](./workers/flag_sender/plugins/saarctf_tcp/client.go).
54+
- Different [exploit types](./docs/exploit_runner/exploit_runner.md):
55+
- Python (one file)
56+
- Python (zip)
57+
- Bash script
58+
- Binary
59+
- View logs of running exploits and sending flags on ui
60+
- Configuring vulnboxes ip addresses using [various methods](./docs/config.md)
461

562
## Components
663

7-
### Arch Diagram
64+
### Client
65+
66+
- **Frontend** - ui for
67+
- viewing flags with any filters
68+
- adding exploits of different types via '+' button
69+
- deleting or updating exploits by right mouse button
70+
- adding teams
71+
- updating farm config
72+
- viewing logs
73+
74+
![](./docs/img/frontend.png)
875

9-
![](./docs/img/diagram.jpg)
76+
- **start_exploit.py** - python cli tool for starting exploits on local machine (TODO)
1077

1178
### Server
1279

@@ -15,8 +82,14 @@ Exploit farm for attack-defense CTF competition
1582
- **JacFARM API** - API for frontend and cli start_exploit.py.
1683
- **Config Loader** - loads config into db from config.yml on start. Next configuration editing is available through the frontend.
1784

18-
### Client
85+
#### Plugins
1986

20-
- **start_exploit.py** - python cli tool for starting exploits on local machine (TODO)
21-
- **Frontend**
22-
![](./docs/img/frontend.png)
87+
**Plugin** - is a function in a farm that sends flags to the jury system.
88+
89+
⚠️ Farm contains two plugins for [ForcAD](https://github.com/pomo-mondreganto/ForcAD) and saarCTF jury systems. If you write plugins for other jury systems, you can create a pull request to add them into repository.
90+
91+
[Plugin example for ForcAD](./workers/flag_sender/plugins/forcad_http/client.go)
92+
93+
### Arch Diagram
94+
95+
![](./docs/img/diagram.jpg)

config.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ exploit_runner:
33
- 10.10.1.2
44
- 10.10.2.2
55
- 10.10.3.2
6+
team_ip_cidrs:
7+
- "10.228.79.0/24"
8+
- "10.229.79.0/24"
9+
team_ip_ranges:
10+
- "10.200.78.2-10.200.78.200"
11+
- "10.200.78.221-10.200.78.233"
12+
team_ip_from_N: # N - range(n_start, n_end); X = N / block + offset_x, Y = N % block + offset_y
13+
n_start: 0
14+
n_end: 2000
15+
offset_x: 32
16+
offset_y: 0
17+
block: 200
18+
ip_template: "10.{X}.{Y}.2"
619
flag_format: '[A-Z0-9]{31}='
720
run_duration: 10s
821
exploit_directory: ./exploits
@@ -15,7 +28,7 @@ flag_sender:
1528
jury_flag_url_or_host: http://10.10.10.10/flags # url for http, host for tcp
1629
token: asd123
1730
flag_ttl: 5m
18-
submit_timeout: 10s
31+
submit_timeout: 30s
1932
submit_period: 5s
2033
submit_limit: 50
2134
plugin_directory: ./plugins

0 commit comments

Comments
 (0)