- HTML 43.3%
- CSS 19.9%
- TypeScript 19.1%
- JavaScript 17.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| c1_find_basic_flag | ||
| c2_api_flag | ||
| c2_api_leaks | ||
| c3_xss_exploit | ||
| c4_llm_prompt_injection | ||
| c5_sql_inject | ||
| c6_self_findBasicFlag | ||
| c7_api_medium | ||
| c7_medium | ||
| c8_commenting_blog | ||
| c8_medium | ||
| c9_student_db_hard | ||
| c10_stack_trace | ||
| c_broken_url_params | ||
| c_idor | ||
| c_jwt | ||
| c_rot13 | ||
| c_ssti | ||
| commentary | ||
| exposed-env | ||
| exposed-git | ||
| llm | ||
| stack-trace-error | ||
| student-database-easy | ||
| student-database-hard | ||
| .gitignore | ||
| db2_setup.js | ||
| db_c9 | ||
| db_setup.js | ||
| db_sqlite | ||
| Dockerfile | ||
| new_comments.txt | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| server.js | ||
| testing.txt | ||
CTF challenge service
This repository runs independently of CTFd. It contains the challenge pages, their vulnerable APIs, and the local SQLite databases.
npm install
npm start
The service listens on port 3000 by default. Set PORT to use another port.
Use GET /health to verify that it is running. There is no CTFd proxy or
required service on port 4000.
Your CTF platform can host/link the challenge routes and handle users,
submissions, and scoring. The challenge endpoints are under /api and the
individual challenge pages are exposed at routes such as /commentary,
/c2_api_flag, /c7_medium, /jwt, and /sst-inject.
Service routes
| Route | Method | Purpose |
|---|---|---|
/health |
GET | Service health check. |
/api |
GET | Lists selected API endpoints. |
/api/c2_flag |
GET | Flag 2 endpoint; requires the x-api-key header. |
/api/c2_flag/dummy |
POST | Decoy endpoint for Flag 2. |
/api/flag/c7 |
GET | Flag 7 endpoint; requires the x-api-key header. |
/api/flag/c7/dummy |
POST | Decoy endpoint for Flag 7. |
/api/posts |
GET/POST | Vulnerable XSS blog (Flag 5). |
/api/safe/posts |
GET | Sanitized blog posts. |
/api/safe/post |
POST | Sanitized blog submission. |
/api/new_comment/posts |
GET | Alternate comment store (Flag 8). |
/api/new_comment/post |
POST | Alternate comment submission (Flag 8). |
/api/ask |
POST | Prompt-injection challenge API (Flag 4). |
/search |
POST | Student database SQL injection challenge (Flag 3). |
/search_hard |
POST | Hard student database query challenge (Flag 9). |
/login |
POST | Student database authentication/query challenge. |
/api/facts |
GET | Stack-trace challenge data. |
/api/facts/:id |
GET | Stack-trace challenge detail endpoint (Flag 10). |
/jwt/login |
POST | JWT challenge login. |
/jwt/posts |
GET | JWT challenge posts. |
/api/statistics |
GET | Broken URL parameter challenge (Flag BAP). |
/api/python_comments/posts |
GET/POST | IDOR challenge post collection. |
/api/python_comments/posts/:id |
GET | IDOR challenge post detail (Flag IDOR). |
/api/ssti/preview |
POST | Server-side template injection preview. |
/api/ssti/posts |
GET/POST | SSTI challenge posts. |
/api/ssti/posts/:id |
GET | SSTI challenge post detail (Flag SSTI). |
Challenge page routes
These routes serve the browser-facing challenge pages. They are standalone and do not require a CTFd installation.
| Challenge | Page route | Category | Flag |
|---|---|---|---|
| Find the basic flag | /c1_flag_basic |
HTML/source inspection | flag{hidden_comment_flag} / flag{not_so_well_hidden} |
| API flag leak | /c2_api_flag |
Exposed API key | flag{misconfigured_api_key_exposed} |
| XSS comments | /commentary |
Stored/reflected XSS | flag{detected_xss} |
| LLM prompt injection | /llm |
Prompt injection | flag{prompt_injection_done} |
| SQL injection | /student-database-easy |
SQL injection | flag{sql_injection} |
| Self-find basic flag | /c6_self_findBasicFlag |
HTML/source inspection | Static challenge flag |
| API key challenge | /c7_medium |
API authentication | flag{apis_should_be_save} |
| Commenting blog | /c8_medium |
XSS/comment handling | flag{acquired_xss_flag} |
| Student database hard | /student-database-hard |
SQL injection/authentication | flag{sql_has_many_flaws} |
| Stack trace error | /stack-trace-error |
Information disclosure | flag{strack_traces_are_evil} |
| Exposed environment | /exposed-env |
.env exposure |
F-3NV-F1L3-3XP0S3D |
| Exposed Git repository | /exposed-git |
Git/config exposure | flag{git_should_be_in_backend} |
| JWT challenge | /jwt |
JWT validation | flag{jwt_is_easy} |
| Broken URL parameters | /statistics |
Parameter tampering | flag{authentication_done} |
| IDOR comments | /python-commentary |
IDOR | flag{1D0R_3XpL01T} |
| SSTI | /sst-inject |
Server-side template injection | flag{ssti_explored} |
| ROT13 | /rot13 |
Encoding/decoding | Flag is revealed by decoding the challenge text |
Flag inventory
The challenge server currently defines these backend flags in server.js:
FLAG_F2 flag{misconfigured_api_key_exposed}
FLAG_F3 flag{sql_injection}
FLAG_F4 flag{prompt_injection_done}
FLAG_F5 flag{detected_xss}
FLAG_F7 flag{apis_should_be_save}
FLAG_F8 flag{acquired_xss_flag}
FLAG_F9 flag{sql_has_many_flaws}
FLAG_F10 flag{strack_traces_are_evil}
FLAG_JWT flag{jwt_is_easy}
FLAG_BAP flag{authentication_done}
FLAG_IDOR flag{1D0R_3XpL01T}
FLAG_SSTI flag{ssti_explored}
Additional flags are intentionally embedded in static challenge artifacts:
c1_find_basic_flag/index.html: HTML comment flag.exposed-env: exposed.envcontent containingF-3NV-F1L3-3XP0S3D.exposed-git: exposed Git metadata containingflag{git_should_be_in_backend}.
Platform integration
The Node service owns challenge behavior and flag discovery. The custom CTF platform should own accounts, teams, flag submissions, scoring, and challenge visibility. A platform can link users to the page routes above and submit the discovered flag text to its own scoring API.
Environment Variables
| Environment Variable | Default Value |
|---|---|
| FLAG_F2 | flag{misconfigured_api_key_exposed} |
| FLAG_F3 | flag{sql_injection} |
| FLAG_F4 | flag{prompt_injection_done} |
| FLAG_F5 | flag{detected_xss} |
| FLAG_F7 | flag{apis_should_be_save} |
| FLAG_F8 | flag{acquired_xss_flag} |
| FLAG_F9 | flag{sql_has_many_flaws} |
| FLAG_F10 | flag{strack_traces_are_evil} |
| FLAG_JWT | flag{jwt_is_easy} |
| FLAG_BAP | flag{authentication_done} |
| FLAG_IDOR | flag{1D0R_3XpL01T} |
| FLAG_SSTI | flag{ssti_explored} |
| FLAG_GIT | flag{git_exposed} |
FLAG_F2=flag{misconfigured_api_key_exposed}
FLAG_F3=flag{sql_injection}
FLAG_F4=flag{prompt_injection_done}
FLAG_F5=flag{detected_xss}
FLAG_F7=flag{apis_should_be_save}
FLAG_F8=flag{acquired_xss_flag}
FLAG_F9=flag{sql_has_many_flaws}
FLAG_F10=flag{strack_traces_are_evil}
FLAG_JWT=flag{jwt_is_easy}
FLAG_BAP=flag{authentication_done}
FLAG_IDOR=flag{1D0R_3XpL01T}
FLAG_SSTI=flag{ssti_explored}
FLAG_GIT=flag{git_exposed}