Scrapes the eCTF scoreboard for rank changes.
graph TD;
R(Design repo)-->|Push|CI(GitHub CI);
CI-->|Commit hash|BS(Build dev image);
subgraph bs [Build server];
BS-->|Dev image|D(Queue / distribute image)
end
S(Slack targets channel)-->|Zipped design|SD(Slack autodownload);
ES(eCTF scoreboard)-->SR(Scoreboard alerts);
subgraph sb [Scrape bot];
DBS(Build / attack status);
SD;
SR;
end
SD-->TR(Targets repo);
SD-->|Target image|D;
SD-->DS(Discord alerting);
DBS-->DS;
SR-->DS;
D-->S1(Attack server 1);
D-->S2(Attack server 2);
D-->S3(Attack server ...);
Create a file called auth.ts
that exports your Discord token, Slack bot info, express / bolt.js server ports, and channel / message IDs:
// auth.ts
export const DISCORD_TOKEN = 'very-real-discord-token';
export const SLACK_TOKEN = 'xoxp-very-real-slack-token';
export const SLACK_SIGNING_SECRET = '...';
export const TARGETS_REPO_URL = 'https://username:[email protected]/Purdue-eCTF-2024/2024-Targets';
export const CTFD_EMAIL = '...';
export const CTFD_PASSWORD = '...';
-
DISCORD_TOKEN
— the discord bot auth token. -
SLACK_TOKEN
— the Slack auth token. -
SLACK_SIGNING_SECRET
— the Slack signing secret. -
TARGETS_REPO_URL
— the GitHub URL to the targets repository to push new targets to. If this is a private repository, make sure to include credentials with push access. -
CTFD_EMAIL
— the email of the team on CTFd. -
CTFD_PASSWORD
— the password of the team on CTFd.
Other configuration options are found in config.ts
:
-
SCOREBOARD_NOTIFY_CHANNEL_ID
— the discord channel to send scoreboard reports in. -
STATUS_CHANNEL_ID
— the discord channel to send build status updates in. -
STATUS_MESSAGE_ID
— the message to update when the status of a build changes. The ID of this message can't really be obtained until a build status message is sent in the first place; leave this field blank at first, then force-send a status message and update the ID accordingly. -
FAILURE_CHANNEL_ID
— the discord channel to send "build failed" notifications in. -
ATTACK_NOTIFY_CHANNEL_ID
— the Discord channel to send "new target dropped" notifications in. -
SLACK_TARGET_CHANNEL_ID
— the Slack channel to listen for target drops in. -
EXPRESS_PORT
— the port to run the build-integration express server on. -
BOLT_PORT
— the port to run the Slack bot on.
See the Slack autodownload section for more on how to configure the required Slack secrets.
Then, install dependencies with npm install
and run npm start
to start the bot.
To run with docker,
docker compose up -d --build
/modules/slack.ts
To set up the Slack integration, create a new Slack app in the Slack API portal.
After creating, you can copy your Slack token and signing secret into auth.ts
.
Then, add OAuth scopes in OAuth & Permissions
; you'll likely need, at minimum, channels:history
, chat:write
, and files:read
.
Finally, enable event subscriptions in Event Subscriptions
and set the request URL to your bolt-js
server URL i.e.
http://ctf.b01lers.com:8081/slack/events
Note that your server should be running at this point to respond to Slack's challenge
request.
/modules/scoreboard.ts
/modules/challenges.ts
This bot periodically fetches the eCTF scoreboard for updates, sending a report of changes each day. Alternatively, run
/report
to get a report of the day so far.
To facilitate this, the bot will need a CTFd access token generated on the account settings page (https://ectf.ctfd.io/settings).
Note that for certain privileged actions (like determining solved challenges and submitting flags), an access token is not enough and an authed session cookie is required instead.
Scrape bot will handle the session management automatically; however, it will need the login credentials of the team account to do so.
/modules/status.ts
This bot also integrates with the build server for automated build status alerting during the dev phase.
![](https://private-user-images.githubusercontent.com/60120929/327615999-3bf83b07-fc5e-4dc1-8a82-835da687e165.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzMjg4MjIsIm5iZiI6MTczOTMyODUyMiwicGF0aCI6Ii82MDEyMDkyOS8zMjc2MTU5OTktM2JmODNiMDctZmM1ZS00ZGMxLThhODItODM1ZGE2ODdlMTY1LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjEyVDAyNDg0MlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTNjNjVhNTdiMjRiZWIxNzI1Mzg3ZTYzMGUzM2E1ZTM5ZjkzNjQ1MTdmMzExYWQzZmIwM2U5OThiNzg0OTZmYWMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.zW8ZrhpphnOGNEZ9cDk-TLoNHEwH8NIlXZZ7Uz1pLiw)
![](https://private-user-images.githubusercontent.com/60120929/327616094-fa155833-c128-4e34-aef2-2ffb1f5db19f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkzMjg4MjIsIm5iZiI6MTczOTMyODUyMiwicGF0aCI6Ii82MDEyMDkyOS8zMjc2MTYwOTQtZmExNTU4MzMtYzEyOC00ZTM0LWFlZjItMmZmYjFmNWRiMTlmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjEyVDAyNDg0MlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTZjYzhkZjhkMTBkMWUzMzdmNDc2YmY2ZWI1ZTUxNGEzOWM0ZjMzMTM0MjRkOTVhYjdjZGVkNzIyMzcwZGViMTcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.s-7nvSCJdUbiR75YYC2uQGlgrAIU9EigTo2wj4Rxju4)
Make sure the build server is configured to send POST requests to this bot's exposed express endpoint properly.