SEC.AUTH.ROLE_WILDCARD_HOST_PRIVILEGED — Reachable from anywhere, and able to do anything
- Category: security
- Severity: high
- Level: 0
- Confidence: deterministic
- Downtime class: none — the finding is about an account, not about a statement
- Stability: stable
- Suites: audit
- Applies to: MySQL 8.4
Why the combination and not either half
Plenty of accounts are reachable from anywhere for good reasons. Every server has privileged
accounts. Neither fact is worth a high on its own, and this package reports the open host by
itself at medium precisely because it is so often deliberate.
Together they are the shape an intrusion takes: an account reachable from the whole network, with nothing above it to escalate to once someone is in. One leaked or guessed credential is the entire attack — there is no second step to detect.
Bad
-- Reachable from anywhere, and able to do anything once it arrives.
CREATE USER 'deploy'@'%' IDENTIFIED BY 'a real secret';
GRANT ALL PRIVILEGES ON *.* TO 'deploy'@'%' WITH GRANT OPTION;
Good
-- Narrow the host, and grant only what the account actually uses.
CREATE USER 'deploy'@'10.0.0.0/24' IDENTIFIED BY 'a real secret';
GRANT SELECT, INSERT, UPDATE, DELETE ON app.* TO 'deploy'@'10.0.0.0/24';
The two fixes are independent, which is worth knowing when neither is easy: narrowing the host helps even if the privileges stay, and dropping the privileges helps even if the host cannot be narrowed. If the privileges genuinely are required, narrow the host — it is the half nobody has to reason about at run time.
A replication account
REPLICATION SLAVE is on the privileged side for what it reads: the binary log carries every change
the server records there. An account that holds it and nothing else far-reaching gets a sentence of
its own, which names what the account can read rather than telling you to take away SUPER or
FILE, which it never had. A replica connects from addresses somebody can name, so the fix is the
host.
Which hosts count
Only a host that admits every address: %, or a pattern of nothing but wildcards and dots such as
%.%.%.%. A pattern over names such as %.example.com is reported by
SEC.AUTH.ROLE_WILDCARD_HOST at medium, whatever the account
holds, and an address pattern such as 10.0.0.% is not reported at all, because MySQL matches an IP
wildcard value only against IP addresses.
How "privileged" is decided
From the account's own record, not from a separate grants scan. Measured on a real MySQL 8.4: an
account holding nothing but GRANT ALL PRIVILEGES ON *.* is read back carrying superuser,
create_role, create_database and replication — MySQL's far-reaching grants surface as account
attributes in the same mysql.user reading the account itself comes from.
That matters for honesty rather than for tidiness: the host and the privileges are one reading,
so they cannot disagree, and there is no second scan that could quietly fail and leave the finding
sitting at the milder weight. An account whose record could not be read is undetermined on both
rules of the pair, never silently the medium one.
Related
SEC.AUTH.ROLE_WILDCARD_HOST— the same open host on an account with ordinary privileges.SEC.PRIV.ROLE_SUPERUSER— the privilege half on its own, asked of the account the audit connected as.