A Grafana user can change their email post-signup without re-verifying — the digital equivalent of changing your name tag at a conference without showing ID again
CVE-2023-6152 is an incorrect authorization flaw in Grafana's basic-auth flow. verify_email_enabled only fires at signup — once a user is inside, they can edit their profile email to *anything*, including addresses they don't control, and Grafana will happily accept it. Grafana also permits using the email field as a login name with no verification. Affects Grafana 9.5.x < 9.5.16, 10.0.x < 10.0.11, 10.1.x < 10.1.7, 10.2.x < 10.2.4, and 10.3.x < 10.3.3. Fixed in those respective patch releases (Feb 2024).
Vendor rated this MEDIUM (CVSS 5.4) and that's *generous*. The impact is C:N/I:L/A:L — no confidentiality loss, minor integrity/availability. The attacker must already be an authenticated Grafana user with basic-auth enabled (most enterprise Grafana deployments are behind SSO/OAuth/LDAP, where this code path doesn't apply). The realistic outcome is squatting on someone else's email as a login handle, or spoofing notifications — annoying, not catastrophic. MEDIUM overstates it for the enterprise fleet; LOW is the honest read.
3 steps from start to impact.
Attacker obtains authenticated Grafana account
auth.basic enabled and verify_email_enabled=true (the code path that gates on signup verification). Any Viewer-level role is sufficient. No exploit tooling needed — this is just the Grafana signup form or an admin-created account.- Grafana instance uses basic-auth (not SSO-only)
- Signup is open OR attacker has any account
- Most enterprise deployments disable open signup (
allow_sign_up=false) - Enterprise deployments typically front Grafana with Okta/Azure AD/LDAP, not basic-auth
grafana.log catches new-user events.Change profile email to a victim address
/profile and updates the email field to [email protected]. The server accepts the change without sending a confirmation email to the new address. No tool needed — plain HTTP PUT /api/user. Public PoC is a one-line curl.- Authenticated session cookie or API token
- None on affected versions — this is the bug
user_updated event; correlating email-field changes against known-good addresses is trivial in Splunk/Elastic.Abuse squatted identity
- Grafana configured to allow email-as-login
- No integrity impact outside Grafana
- Alerts/dashboards ACLs remain enforced by role, not email
The supporting signals.
| In-the-wild exploitation | None observed. Not in CISA KEV. No public campaign reporting from Mandiant, CrowdStrike, or Unit 42. |
|---|---|
| Proof-of-concept | Trivial — described in the GHSA-3hv4-r2fm-h27f advisory itself; single API call to PUT /api/user. |
| EPSS | ~0.05% (bottom quartile). Very low predicted exploitation probability. |
| CISA KEV | Not listed. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L = 5.4 MEDIUM. Note C:N — zero confidentiality impact. |
| Affected versions | Grafana 9.5.x < 9.5.16, 10.0.x < 10.0.11, 10.1.x < 10.1.7, 10.2.x < 10.2.4, 10.3.x < 10.3.3. |
| Fixed versions | 9.5.16, 10.0.11, 10.1.7, 10.2.4, 10.3.3. RHEL/Amazon Linux Grafana packages received backports; check rpm -q --changelog grafana. |
| Exposure data | Shodan shows ~110k internet-facing Grafana instances, but only a minority run basic-auth with open signup — the exploitable subset is a small fraction of that. |
| Disclosed | 2024-02-13 (Grafana security release blog). |
| Reporter | Grafana bug-bounty program; credited via GHSA advisory. |
noisgate verdict.
The decisive factor is impact ceiling: the CVSS vector itself declares C:N (zero confidentiality loss) with only Low integrity/availability, and the flaw requires a pre-authenticated user on a basic-auth-enabled instance — a narrow deployment slice in enterprise environments that typically front Grafana with SSO. Blast radius is bounded to identity confusion within a single Grafana tenant; there is no path to RCE, privilege escalation, or data egress.
Why this verdict
- Impact vector is C:N/I:L/A:L — even a successful exploit yields no data theft, no code execution, no persistence. The worst case is identity spoofing inside one Grafana instance.
- Requires PR:L (authenticated user) — attacker must already hold a Grafana account. On locked-down enterprise deployments (
allow_sign_up=false), this collapses to insider misuse. - Basic-auth-only code path — the majority of enterprise Grafana instances integrate with Okta/Azure AD/Google/LDAP, where the vulnerable profile-update flow is either disabled or gated by the IdP.
- Role multiplier — Grafana observability tier: Grafana is a *monitoring* plane, not an identity, hypervisor, or CI/CD component. Even if compromised, Grafana rarely holds credentials that pivot to fleet takeover (datasource creds are the exception — but this bug does not expose them). No high-value-role floor applies.
- No KEV, no PoC weaponization, EPSS ~0.05% — the market has looked at this and shrugged.
Why not higher?
MEDIUM would require a plausible path to data exposure or privilege escalation. This bug produces neither — it lets an attacker misrepresent their email address, and Grafana's authorization model does not trust email for anything except display and notification routing. HIGH is not defensible when the CVSS vector itself says C:N.
Why not lower?
IGNORE would require the bug to be unreachable in the wild. It is reachable — any Grafana instance with basic-auth is affected — so it deserves a place in the 365-day patching queue as backlog hygiene, not zero attention.
What to do — in priority order.
- Disable open signup — Set
[users] allow_sign_up = falseingrafana.ini. This removes the low-friction path to obtaining an initial account. Deploy as part of normal config drift review — no mitigation SLA at LOW severity, so fold into the next config change window. - Front Grafana with your IdP — Configure OAuth/SAML/LDAP via
auth.generic_oauthorauth.ldapand setdisable_login_form = true. The vulnerable email-update path applies to basic-auth flows; SSO identities are governed by the IdP, not Grafana's local profile store. - Alert on user email field changes — Ingest
grafana.loginto your SIEM and alert onlogger=user action=updateevents where theemailfield differs from prior state. Cheap detective control; catches abuse even on unpatched instances. - Patch to the fixed minor — Upgrade to 9.5.16 / 10.0.11 / 10.1.7 / 10.2.4 / 10.3.3 or later during the normal quarterly Grafana upgrade cycle. Per noisgate remediation SLA for LOW: no hard deadline, treat as backlog hygiene within 365 days.
- WAF rules — the exploit is a legitimate authenticated API call to
/api/user. Blocking it breaks profile management for everyone. - MFA on Grafana login — MFA gates authentication, not post-login profile edits. Once the attacker is logged in, MFA is out of the picture.
- Network segmentation — the attacker is already an authenticated user of the app; L3/L4 controls don't apply.
Crowdsourced verification payload.
Run on the Grafana host as any user who can read the binary, or hit the API from an auditor workstation. Invoke as ./check_cve_2023_6152.sh https://grafana.example.com (URL optional; if omitted, script inspects the local grafana-server binary). No privileges required for the API check; local binary check needs read on /usr/sbin/grafana-server.
#!/usr/bin/env bash
# noisgate verification for CVE-2023-6152 (Grafana email-verify bypass)
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -u
TARGET_URL="${1:-}"
version_lt() {
# returns 0 if $1 < $2
[ "$1" = "$2" ] && return 1
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
is_vulnerable() {
local v="$1"
# Extract MAJOR.MINOR.PATCH
local mm=$(echo "$v" | awk -F. '{print $1"."$2}')
case "$mm" in
9.5) version_lt "$v" "9.5.16" && return 0 ;;
10.0) version_lt "$v" "10.0.11" && return 0 ;;
10.1) version_lt "$v" "10.1.7" && return 0 ;;
10.2) version_lt "$v" "10.2.4" && return 0 ;;
10.3) version_lt "$v" "10.3.3" && return 0 ;;
*)
# 10.4+ and 11.x are patched; <9.5 is EOL — flag UNKNOWN
if version_lt "$v" "9.5.0"; then return 2; fi
return 1
;;
esac
return 1
}
GRAFANA_VER=""
if [ -n "$TARGET_URL" ]; then
GRAFANA_VER=$(curl -fsS "${TARGET_URL%/}/api/health" 2>/dev/null | grep -oE '"version"[[:space:]]*:[[:space:]]*"[^"]+"' | sed -E 's/.*"([0-9.]+)".*/\1/')
fi
if [ -z "$GRAFANA_VER" ] && command -v grafana-server >/dev/null 2>&1; then
GRAFANA_VER=$(grafana-server -v 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
fi
if [ -z "$GRAFANA_VER" ]; then
echo "UNKNOWN: could not determine Grafana version"
exit 2
fi
echo "Detected Grafana version: $GRAFANA_VER"
is_vulnerable "$GRAFANA_VER"
rc=$?
if [ $rc -eq 0 ]; then
echo "VULNERABLE: $GRAFANA_VER predates the CVE-2023-6152 fix in its minor series"
exit 1
elif [ $rc -eq 2 ]; then
echo "UNKNOWN: version $GRAFANA_VER is out of scope / EOL — verify manually"
exit 2
fi
# Additional signal: is basic-auth enabled?
if [ -r /etc/grafana/grafana.ini ]; then
if grep -Eq '^[[:space:]]*disable_login_form[[:space:]]*=[[:space:]]*true' /etc/grafana/grafana.ini; then
echo "PATCHED: version $GRAFANA_VER includes fix; basic-auth login form disabled"
else
echo "PATCHED: version $GRAFANA_VER includes fix (basic-auth still enabled — informational only)"
fi
else
echo "PATCHED: version $GRAFANA_VER includes fix"
fi
exit 0
If you remember one thing.
allow_sign_up=false and confirm your Grafana estate is fronted by your IdP with disable_login_form=true; those two knobs remove the exploit surface even on unpatched hosts.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.