diff --git a/README.md b/README.md index 5068544..2516ccd 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,24 @@ some opinionated choices for the frontend. This has a few nice implications: - filters based on libmagic, e.g. quickly filter flows containing PDF documents or PNG images, - no heavy build tools needed, Shovel is easy to tweak. -Moreover, Shovel is batteries-included with Grafana visualizations and some Suricata alert rules. +Moreover, Shovel is batteries-included with some Suricata alert rules. + +``` + ┌────────────────────────┐ + │ Suricata with: │ eve.db ┌───────────────┐ +pcap │ - Eve SQLite plugin ├────────────►│ │ +─────►│ - TCP payloads plugin │ payload.db │ Python webapp │ + │ - UDP payloads plugin ├────────────►│ │ + └────────────────────────┘ └────▲──────────┘ + .env │ + ──────┘ +``` ## Setup ### 0. Before the Capture-the-Flag event begins -Copy `example.env` to `.env` and tweak the configuration parameters. +Copy `example.env` to `.env` and update the configuration parameters. Also add the flag format in `suricata/rules/suricata.rules` if needed. If you are playing a CTF using an IPv6 network, you might want to [enable IPv6 support in Docker deamon](https://docs.docker.com/config/daemon/ipv6/) before the CTF starts. diff --git a/grafana/Dockerfile b/grafana/Dockerfile deleted file mode 100644 index 7922a24..0000000 --- a/grafana/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (C) 2024 ANSSI -# SPDX-License-Identifier: CC0-1.0 -FROM grafana/grafana-oss:10.1.2 -ENV GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES=false \ - GF_ANALYTICS_CHECK_FOR_UPDATES=false \ - GF_ANALYTICS_REPORTING_ENABLED=false \ - GF_AUTH_ANONYMOUS_ENABLED=true \ - GF_AUTH_ANONYMOUS_HIDE_VERSION=true \ - GF_INSTALL_PLUGINS=frser-sqlite-datasource \ - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/var/lib/grafana/dashboards/home.json -COPY ./provisioning /etc/grafana/provisioning -COPY ./dashboards /var/lib/grafana/dashboards diff --git a/grafana/dashboards/home.json b/grafana/dashboards/home.json deleted file mode 100644 index 478d167..0000000 --- a/grafana/dashboards/home.json +++ /dev/null @@ -1,401 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 2, - "id": 1, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "purple", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 40, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "decimals": 0, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 10, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "queryText": "SELECT ($__unixEpochGroupSeconds(ts_start / 1000, 180) - (SELECT ts_start / 1000 FROM ctf_config))/180 as tick, COUNT(*) as count FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nGROUP BY tick", - "queryType": "table", - "rawQueryText": "SELECT ($__unixEpochGroupSeconds(ts_start / 1000, 180) - (SELECT ts_start / 1000 FROM ctf_config))/180 as tick, COUNT(*) as count FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nGROUP BY tick", - "refId": "A", - "timeColumns": [] - } - ], - "title": "Flows per tick", - "type": "trend" - }, - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "red", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 40, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 7 - }, - "id": 3, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "queryText": "SELECT ($__unixEpochGroupSeconds(ts_start / 1000, 180) - (SELECT ts_start / 1000 FROM ctf_config))/180 as tick, COUNT(*) as flag_out_count FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nAND id IN (SELECT flow_id FROM alert WHERE tag = \"FLAG OUT\")\nGROUP BY tick", - "queryType": "table", - "rawQueryText": "SELECT ($__unixEpochGroupSeconds(ts_start / 1000, 180) - (SELECT ts_start / 1000 FROM ctf_config))/180 as tick, COUNT(*) as flag_out_count FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nAND id IN (SELECT flow_id FROM alert WHERE tag = \"FLAG OUT\")\nGROUP BY tick", - "refId": "A", - "timeColumns": [] - } - ], - "title": "FLAG OUT per tick", - "transformations": [], - "type": "trend" - }, - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "fixedColor": "green", - "mode": "fixed" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 40, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 7 - }, - "id": 11, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "queryText": "SELECT ($__unixEpochGroupSeconds(ts_start / 1000, 180) - (SELECT ts_start / 1000 FROM ctf_config))/180 as tick, COUNT(*) as flag_in_count FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nAND id IN (SELECT flow_id FROM alert WHERE tag = \"FLAG IN\")\nGROUP BY tick", - "queryType": "table", - "rawQueryText": "SELECT ($__unixEpochGroupSeconds(ts_start / 1000, 180) - (SELECT ts_start / 1000 FROM ctf_config))/180 as tick, COUNT(*) as flag_in_count FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nAND id IN (SELECT flow_id FROM alert WHERE tag = \"FLAG IN\")\nGROUP BY tick", - "refId": "A", - "timeColumns": [] - } - ], - "title": "FLAG IN per tick", - "transformations": [], - "type": "trend" - }, - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-GrYlRd" - }, - "custom": { - "fillOpacity": 100, - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineWidth": 0 - }, - "displayName": "${__field.labels.dest_ipport}", - "mappings": [], - "noValue": "0", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 13, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 5, - "options": { - "colWidth": 1, - "legend": { - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "rowHeight": 0.8, - "showValue": "auto", - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "frser-sqlite-datasource", - "uid": "P2D2EEF3E092AF52B" - }, - "queryText": "SELECT $__unixEpochGroupSeconds(ts_start / 1000, 180) as time, COUNT(*) as flag_out_count, dest_ipport FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nAND id IN (SELECT flow_id FROM alert WHERE tag = \"FLAG OUT\")\nGROUP BY time, dest_ipport", - "queryType": "time series", - "rawQueryText": "SELECT $__unixEpochGroupSeconds(ts_start / 1000, 180) as time, COUNT(*) as flag_out_count, dest_ipport FROM flow\nWHERE ts_start >= $__from and ts_start < $__to\nAND id IN (SELECT flow_id FROM alert WHERE tag = \"FLAG OUT\")\nGROUP BY time, dest_ipport", - "refId": "A", - "timeColumns": [ - "time", - "ts" - ] - } - ], - "title": "FLAG OUT per service per tick", - "type": "status-history" - } - ], - "refresh": "10s", - "schemaVersion": 38, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "1970-01-01T12:00:00.000Z", - "to": "2100-01-01T12:00:00.000Z" - }, - "timepicker": {}, - "timezone": "", - "title": "Home", - "uid": "WdNSDiRIz", - "version": 9, - "weekStart": "" -} \ No newline at end of file diff --git a/grafana/provisioning/dashboards/default.yml b/grafana/provisioning/dashboards/default.yml deleted file mode 100644 index 651b4fe..0000000 --- a/grafana/provisioning/dashboards/default.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (C) 2024 ANSSI -# SPDX-License-Identifier: CC0-1.0 -apiVersion: 1 - -providers: - - name: dashboards - type: file - allowUiUpdates: true - options: - path: /var/lib/grafana/dashboards diff --git a/grafana/provisioning/datasources/sql.yml b/grafana/provisioning/datasources/sql.yml deleted file mode 100644 index aa61a6b..0000000 --- a/grafana/provisioning/datasources/sql.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (C) 2024 ANSSI -# SPDX-License-Identifier: CC0-1.0 -apiVersion: 1 - -datasources: - - name: SQLite - type: frser-sqlite-datasource - jsonData: - path: /webapp/database/database.db - isDefault: true