CVE-2025-41115: Khi Grafana Ghi Điểm CVSS 10.0 Hoàn Hảo

CVE-2025-41115: Khi Grafana Ghi Điểm CVSS 10.0 Hoàn Hảo

CVE-2025-41115: Khi Grafana Ghi Điểm CVSS 10.0 Hoàn Hảo

TL;DR
CVE-2025-41115 là lỗ hổng điểm CVSS 10.0 trên Grafana Enterprise phiên bản 12.0.0-12.2.1, cho phép kẻ tấn công mạo danh tài khoản quản trị viên thông qua cơ chế cung cấp SCIM.
Nguyên nhân gốc rễ: Grafana ánh xạ trực tiếp giá trị externalId từ SCIM sang trường user.uid nội bộ, tạo ra xung đột không gian tên cho phép kẻ tấn công tạo người dùng với uid="1" (ID quản trị viên).
Nhưng thực tế lỗ hổng này không dễ khai thác như CVSS 10.0 của nó, cùng xem chi tiết nào

Ngày 19 tháng 11 năm 2025, Grafana Labs công bố một lỗ hổng bảo mật với mức độ nghiêm trọng chưa từng có trong lịch sử sản phẩm của họ: CVE-2025-41115 với điểm CVSS đạt mức 10.0/10.0 - điểm số hoàn hảo cho một vulnerability.

Đây không phải là một con số được trao một cách tùy tiện. CVSS 10.0 có nghĩa là lỗ hổng này có thể bị khai thác từ xa (network-accessible), không yêu cầu xác thực (unauthenticated), không cần tương tác người dùng, và gây ra tác động nghiêm trọng đến tất cả ba trụ cột bảo mật: Confidentiality, Integrity, và Availability. Nói cách khác, đây là worst-case scenario trong threat modeling.

Lỗ hổng cho phép kẻ tấn công mạo danh (impersonate) tài khoản administrator, leo thang đặc quyền lên mức cao nhất, và chiếm toàn quyền kiểm soát Grafana instance - tất cả mà không cần credentials ban đầu. Đối với một platform quản lý observability có quyền truy cập vào toàn bộ monitoring data của tổ chức, đây là một disaster scenario.

Scope của lỗ hổng:

  • Chỉ ảnh hưởng Grafana Enterprise phiên bản 12.0.0 đến 12.2.1
  • Cần điều kiện: SCIM provisioning phải được kích hoạt
  • Grafana OSS (phiên bản miễn phí) không bị ảnh hưởng
  • Grafana Cloud và managed services đã được vá tự động

May mắn là lỗ hổng được phát hiện qua internal security audit trước khi bị khai thác in-the-wild. Nhưng câu chuyện đằng sau CVE-2025-41115 là một bài học quan trọng về design flaws trong identity management và lý do tại sao observability infrastructure cần được bảo vệ như production systems.

SCIM 101: The Double-Edged Sword

Trước khi đi sâu vào lỗ hổng, cần hiểu SCIM là gì và tại sao nó lại trở thành attack surface.

SCIM là gì?

SCIM (System for Cross-domain Identity Management) là một open standard protocol cho việc tự động hóa quản lý user lifecycle giữa các hệ thống khác nhau. SCIM bao gồm hai thành phần chính:

  1. Schema definitions - Cấu trúc chuẩn hóa cho user và group objects
  2. REST API - Interface cho identity operations

Thay vì phải tạo/xóa/cập nhật tài khoản thủ công trên từng application, SCIM cho phép tổ chức quản lý identities tập trung từ một Identity Provider (IdP) như Okta, Azure AD, hoặc OneLogin. IdP hoạt động như một "universal directory" - single source of truth cho identity data.

SCIM Workflow

SCIM Lifecycle

SCIM protocol cung cấp 4 operations cơ bản (CRUD):

CREATE - Provision user accounts:

  • IT admin tạo một user mới trên Azure AD
  • Azure AD (SCIM client) gửi provisioning request đến Grafana (SCIM server)
  • Grafana tự động tạo user account tương ứng

READ - Query và sync user data:

  • IdP định kỳ query để verify user existence
  • Sync attributes giữa systems

UPDATE - Modify user attributes:

  • Bidirectional: App-to-IdP hoặc ngược lại
  • Update roles, permissions, profile info

DELETE (hoặc Deactivate):

  • Khi user rời công ty, Azure AD deprovision
  • Grafana tự động set active=false cho account
  • Instant access revocation across all applications

Automation Benefits

SCIM giải quyết pain points của enterprise identity management:

  • Onboard hàng trăm nhân viên mới trong một ngày
  • Consistent security policy enforcement
  • Instant deprovisioning khi nhân viên rời đi
  • Giảm manual workload và human errors

Trust Boundary và Security Model

Nghe có vẻ tiện lợi và an toàn? Đúng vậy - khi được implement đúng. Nhưng SCIM tạo ra một trust relationship critical giữa IdP và Application:

Trust Model:

IdP (SCIM Client) ←--[TRUST]--→ Application (SCIM Server)
      ↓                                  ↓
"Universal Directory"              "Phải trust data"
Single source of truth             từ SCIM requests

SCIM server phải authenticate SCIM client qua API tokens. Nhưng một khi authenticated, server phải tin tưởng data từ client. Đây là điểm yếu.

Rủi ro của SCIM implementation:

  1. Compromised SCIM client: Nếu IdP hoặc SCIM token bị xâm nhập, attacker có toàn quyền provisioning.
  2. Malicious SCIM client: Một ứng dụng lừa đảo hoặc third-party integration có thể lợi dụng SCIM endpoint.
  3. Input validation failures: Nếu SCIM server không validate input đúng cách, attacker có thể inject malicious data.

Grafana mắc phải lỗi thứ 3 - và đó chính là root cause của CVE-2025-41115.


Root Cause: Phân tích lỗi thiết kế

Lỗ hổng CVE-2025-41115 bắt nguồn từ một design decision nguy hiểm: ánh xạ trực tiếp giá trị externalId từ SCIM sang trường user.uid nội bộ của Grafana.

Cách Grafana xử lý SCIM provisioning (vulnerable version):

Khi nhận SCIM request để tạo user mới, Grafana thực hiện mapping như sau:

SCIM Request:
{
  "externalId": "12345",
  "userName": "[email protected]",
  ...
}

Grafana Internal Mapping:
user.uid = externalId  // "12345"
user.email = userName  // "[email protected]"

Nhìn qua thì logic này có vẻ hợp lý - dùng externalId từ IdP làm unique identifier. Nhưng có một vấn đề chết người: Grafana cũng sử dụng numeric IDs cho internal users.

Vấn đề nằm ở đâu?

Trong Grafana, mỗi user được gán một internal ID là số nguyên tăng dần: 1, 2, 3, 4… User đầu tiên (thường là admin account) có user.id = 1.

Bây giờ tưởng tượng scenario này:

  • Admin account hiện tại có user.id = 1user.uid = "1"
  • Attacker kiểm soát SCIM provisioning request
  • Attacker gửi request với externalId = "1"
  • Grafana ánh xạ: new_user.uid = "1"

Kết quả: Grafana nhầm lẫn giữa user mới (với uid="1" từ SCIM) và admin account hiện có (với uid="1" nội bộ). Attacker giờ có thể impersonate admin account.

Tại sao đây là lỗi thiết kế nghiêm trọng?

1. Violation của trust boundary:

SCIM externalId là external input từ bên ngoài Grafana. Việc sử dụng trực tiếp external input làm internal identifier vi phạm nguyên tắc cơ bản: never trust external input.

2. Namespace collision:

Grafana không tách biệt namespace giữa:

  • Internal users (uid = 1, 2, 3…)
  • SCIM-provisioned users (uid = externalId)

Không có prefix, suffix, hoặc cơ chế nào để phân biệt hai loại user này.

3. Type confusion:

externalId có thể là string bất kỳ từ IdP, bao gồm cả numeric strings như "1", "2". Grafana không validate hoặc sanitize giá trị này trước khi dùng làm user.uid.

4. Privilege assumption:

Grafana assume rằng SCIM client sẽ gửi "good" data. Không có check nào để verify rằng externalId không clash với existing internal IDs.

Đây là một case study điển hình về Incorrect Privilege Assignment (CWE-266) - chính xác là classification mà CVE database gán cho lỗ hổng này.


Attack Vector Deep-Dive

Bây giờ đi sâu vào cách thức khai thác từng bước.

Prerequisites

Để khai thác CVE-2025-41115 thành công, attacker cần đáp ứng tất cả các điều kiện sau:

1. Target là Grafana Enterprise với SCIM enabled:

SCIM là feature của Grafana Enterprise, không có trong OSS version. Hơn nữa, SCIM phải được explicitly enabled trong config:

[feature_toggles]
enableSCIM = true

[auth.scim]
enabled = true
user_sync_enabled = true

2. Phiên bản vulnerable:

Grafana Enterprise 12.0.0 đến 12.2.1 (releases từ tháng 4/2025 đến tháng 11/2025).

3. Khả năng gửi SCIM provisioning requests:

Attacker cần một trong hai:

  • Compromised SCIM client (IdP credentials)
  • Malicious SCIM client được configure trong Grafana
  • Man-in-the-middle position để modify SCIM traffic

4. Biết internal user IDs:

Để impersonate một user cụ thể, attacker cần biết user.id của target. Admin user thường có id = 1, nhưng không phải lúc nào cũng vậy.

Exploitation Flow

Step 1: Reconnaissance

# Enumerate Grafana version
curl -s https://target-grafana.com/api/health | jq .version

# Check if SCIM is enabled (requires some level of access)
curl -s https://target-grafana.com/api/org/users | grep -i scim

Attacker cần xác định:

  • Grafana version (12.0.0 - 12.2.1)
  • SCIM có enabled không
  • Internal user IDs (đặc biệt là admin accounts)

Step 2: Compromise or control SCIM client

Giả sử attacker đã compromise Azure AD hoặc Okta tenant của target organization. Hoặc attacker có thể tạo một malicious SCIM integration.

Step 3: Craft malicious SCIM request

SCIM provisioning request chuẩn trông như thế này:

POST /api/scim/v2/Users HTTP/1.1
Host: target-grafana.com
Authorization: Bearer <SCIM_API_TOKEN>
Content-Type: application/scim+json

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "externalId": "user123-from-azure",
  "userName": "[email protected]",
  "name": {
    "givenName": "John",
    "familyName": "Doe"
  },
  "emails": [{
    "value": "[email protected]",
    "primary": true
  }],
  "active": true
}

Malicious request để impersonate admin (uid=1):

POST /api/scim/v2/Users HTTP/1.1
Host: target-grafana.com
Authorization: Bearer <SCIM_API_TOKEN>
Content-Type: application/scim+json

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "externalId": "1",  // ← Malicious: numeric string matching admin ID
  "userName": "[email protected]",
  "name": {
    "givenName": "Evil",
    "familyName": "Admin"
  },
  "emails": [{
    "value": "[email protected]",
    "primary": true
  }],
  "active": true
}

Key difference: externalId = "1" thay vì một UUID hoặc identifier dài.

Step 4: Grafana processes request (vulnerable behavior)

Grafana nhận request và thực hiện:

1. Parse SCIM JSON
2. Extract externalId = "1"
3. Map: new_user.uid = "1"  // ← BUG HERE
4. Create user với uid="1"
5. Lookup permissions: uid="1" → admin account
6. Grant admin privileges to new user

Step 5: Login and verify access

Attacker giờ có thể login bằng [email protected] (với password được provision qua SCIM hoặc password reset) và có full admin privileges.

Step 6: Maintain persistence

Một khi có admin access:

  • Tạo thêm admin accounts
  • Modify authentication settings
  • Extract API keys
  • Access toàn bộ monitoring data
  • Exfiltrate credentials stored trong data sources

Impact Analysis

Confidentiality (HIGH):

  • Truy cập toàn bộ dashboards, metrics, logs
  • Grafana thường có credentials cho databases, cloud APIs
  • Có thể thấy toàn bộ infrastructure topology

Integrity (HIGH):

  • Modify dashboards để hide malicious activity
  • Alter alerting rules
  • Inject false data hoặc hide real incidents

Availability (HIGH):

  • Delete dashboards, data sources
  • Disable alerting
  • Lock out legitimate admins
  • Cause monitoring blind spots

Với observability platform, việc compromise Grafana không chỉ là mất một application - đó là mất visibility vào toàn bộ infrastructure.

CVSS 10.0: thỏa đáng hay thổi phồng?

Sau khi đi qua attack vector chi tiết, một câu hỏi tự nhiên xuất hiện: Liệu CVSS 10.0 có thực sự thỏa đáng không?

CVSS 10.0 là điểm số hiếm gặp, dành riêng cho những lỗ hổng catastrophic như Log4Shell hay EternalBlue - những lỗ hổng mà "bất kỳ ai trên internet" đều có thể exploit dễ dàng. Nhưng thực tế, khai thác CVE-2025-41115 KHÔNG đơn giản như điểm 10.0 gợi ý.

Prerequisites Thực Tế

Để exploit lỗ hổng này, attacker cần tất cả các điều kiện sau:

  1. SCIM API token - phải leak, steal, hoặc compromise để lấy được
  2. SCIM enabled - không phải default configuration
  3. Grafana Enterprise license - không phải mọi instance
  4. Biết internal user IDs - cần enumeration hoặc inside knowledge
  5. Hiểu SCIM protocol - không phải HTTP request đơn giản

Đây là một multi-step attack chain, không phải "gửi một request là xong" như Log4Shell.

Threat Landscape Thực Tế

External Attacker (không có cửa access):

  • Phải compromise IdP hoặc steal SCIM token trước
  • Phải enumerate internal user structure
  • Phải hiểu Grafana SCIM implementation
  • Độ khó: Rất cao - Realistic CVSS: 8.0-8.5

Insider Threat (đây mới là risk thực sự):

  • Admin nội bộ với SCIM access hợp pháp
  • Nhân viên IT bất mãn biết internal structure
  • Một thư viện nhiễm mã độc đã được cài đặt.
  • Độ khó: Thấp - Realistic CVSS: 9.5

Vậy thì CVSS 10.0 của CVE-2025-41115 là technically defensible (nếu tính worst-case: SCIM endpoint misconfigured, public exposure) nhưng thực tế thì đây là sự thổi phồng.

Lỗ hổng này chủ yếu là insider threat risk, không phải "anyone on the internet can hack" như điểm 10.0 gợi ý. So với Log4Shell (cũng 10.0) - được exploit massively trong vài giờ, affect hàng triệu servers - CVE này có threat level thực tế thấp hơn nhiều.

Realistic assessment: 8.5-9.0 (vẫn Critical và cần patch urgent, nhưng không phải "perfect storm")

Security teams nên đọc kỹ advisory và assess risk trong context của mình, không chỉ nhìn CVSS score.


Patch Analysis: Git Commit Breakdown

Grafana Labs đã fix lỗ hổng này trong commit ca5...331e.

Phân tích commit

File thay đổi chính:

  • pkg/services/sqlstore/migrations/user_mig.go

Thay đổi 1: Mở rộng trường user.uid

Before:

// uid field có size hạn chế, không đủ cho prefix

After:

-- PostgreSQL
ALTER TABLE "user" ALTER COLUMN uid TYPE VARCHAR(190);

-- MySQL
ALTER TABLE `user` MODIFY COLUMN `uid` VARCHAR(190);

-- SQLite
-- Recreate table với uid VARCHAR(190)

Grafana mở rộng trường uid trong database để có thể chứa giá trị dài hơn, vì bây giờ họ sẽ thêm prefix.

Thay đổi 2: Thêm prefix cho SCIM users

Core fix logic:

// Before (VULNERABLE):
func CreateUserFromSCIM(scimUser SCIMUser) {
    user := User{
        UID: scimUser.ExternalID,  // Directly map: "1" → uid="1"
        Email: scimUser.UserName,
        // ...
    }
    db.Insert(user)
}

// After (PATCHED):
func CreateUserFromSCIM(scimUser SCIMUser) {
    user := User{
        UID: "scim-" + scimUser.ExternalID,  // Prefix: "1" → uid="scim-1"
        Email: scimUser.UserName,
        // ...
    }
    db.Insert(user)
}

Ví dụ cụ thể:

Scenario ExternalID từ SCIM UID trước patch UID sau patch
Legitimate user "abc-123-xyz" "abc-123-xyz" "scim-abc-123-xyz"
Malicious request "1" "1" (CLASH!) "scim-1" (SAFE)
Admin collision "2" "2" (CLASH!) "scim-2" (SAFE)

Tại sao fix này hiệu quả?

1. Namespace separation:

Bằng cách thêm prefix "scim-", Grafana tạo ra một namespace riêng biệt cho SCIM-provisioned users:

  • Internal users: uid = 1, 2, 3, ...
  • SCIM users: uid = scim-1, scim-2, scim-3, ...

Không còn collision có thể xảy ra.

2. Type distinction:

Bây giờ có thể dễ dàng phân biệt user origin dựa vào prefix:

SELECT * FROM user WHERE uid LIKE 'scim-%';  -- SCIM users
SELECT * FROM user WHERE uid NOT LIKE 'scim-%';  -- Internal users

3. Defense in depth:

Ngay cả khi attacker gửi externalId = "1", kết quả là uid = "scim-1", không bao giờ match với admin account có uid = "1".

Migration handling

Grafana cũng thêm migration logic để update existing SCIM users:

// Migration: Add prefix to existing SCIM users
func MigrateSCIMUsers(db *sql.DB) {
    // Find all users created via SCIM (before patch)
    scimUsers := db.Query(`
        SELECT id, uid FROM user
        WHERE auth_module = 'scim'
        AND uid NOT LIKE 'scim-%'
    `)

    // Add prefix to each
    for _, user := range scimUsers {
        newUID := "scim-" + user.UID
        db.Exec(`
            UPDATE user
            SET uid = ?
            WHERE id = ?
        `, newUID, user.ID)
    }
}

Điều này đảm bảo rằng:

  • Existing SCIM users vẫn hoạt động sau khi upgrade
  • Không có data loss
  • Backward compatibility được duy trì

Lessons từ patch

1. Simple fixes are often the best:

Grafana không cần refactor toàn bộ SCIM implementation. Chỉ cần thêm một prefix đơn giản đã resolve vấn đề.

2. Namespace matters:

Khi xử lý external input, luôn tạo namespace riêng biệt. Prefix/suffix là cách đơn giản nhưng hiệu quả.

3. Migration is critical:

Fix không chỉ là code changes, mà còn phải handle existing data. Migration script đảm bảo smooth upgrade path.

Key Takeaway: Observability Infrastructure = Critical Attack Surface

CVE-2025-41115 là một wake-up call quan trọng cho security teams: Observability infrastructure là critical attack surface và cần được bảo vệ như production systems.

Tại sao Grafana (và các monitoring tools) là high-value targets?

1. Visibility vào toàn bộ infrastructure:

Grafana dashboards thường chứa:

  • Topology maps của entire infrastructure
  • Service dependencies
  • Database connection strings
  • API endpoints và internal URLs
  • Performance bottlenecks và vulnerabilities

Một attacker với access vào Grafana có blueprint hoàn chỉnh của target organization.

2. Credentials storage:

Grafana data sources chứa credentials cho:

  • Databases (PostgreSQL, MySQL, MongoDB, etc.)
  • Cloud platforms (AWS, GCP, Azure)
  • Metrics systems (Prometheus, InfluxDB, Elasticsearch)
  • APM tools (Datadog, New Relic)

Compromise Grafana → compromise multiple systems.

3. Blind spot creation:

Nếu attacker kiểm soát monitoring system, họ có thể:

  • Disable alerts về malicious activity
  • Modify metrics để hide evidence
  • Create false positives để distract SOC team
  • Delete logs của intrusion

4. Privilege escalation path:

Monitoring tools thường có elevated privileges:

  • Read access to all systems
  • API keys với broad permissions
  • SSH keys cho infrastructure access

Grafana admin = potential infrastructure admin.

Bài học cho security teams

1. Treat observability như Tier-1 systems:

Áp dụng same security controls cho Grafana/Prometheus/ELK như cho production databases:

  • Multi-factor authentication (MFA)
  • Network segmentation
  • Regular security audits
  • Least privilege access

2. Don't trust external input - even from "trusted" systems:

CVE-2025-41115 cho thấy ngay cả SCIM (từ corporate IdP) cũng có thể bị abuse. Always validate và sanitize external input, bất kể nguồn.

3. Namespace separation is critical:

Khi xử lý external identifiers, tạo namespace riêng biệt:

  • Prefix/suffix cho external IDs
  • Separate tables/schemas
  • Type distinctions

Không bao giờ assume rằng external và internal IDs sẽ không clash.

4. Monitor the monitors:

Ai monitor Grafana? Implement:

  • Separate SIEM cho monitoring infrastructure
  • Alert trên Grafana admin actions
  • Audit logs cho SCIM provisioning
  • Out-of-band monitoring

5. Rapid response matters:

Grafana Labs phản ứng trong 24 giờ:

  • Phát hiện lỗ hổng → Vá lỗi → Private release → Public disclosure

Không có evidence của in-the-wild exploitation. Speed saved them.

Kết luận

CVE-2025-41115 có CVSS 10.0, nhưng impact thực tế được giảm thiểu nhờ:

  • Scope hạn chế (chỉ Enterprise + SCIM enabled)
  • Phát hiện sớm (internal audit, chưa bị exploit)
  • Response nhanh (24h patch)
  • Auto-patching cho managed services

Tuy nhiên, bài học quan trọng vẫn còn: Hạ tầng quan sát không chỉ đơn thuần là giám sát. Đây là những hệ thống quan trọng có quyền truy cập vào mọi thứ, và cần được bảo mật tương xứng.

Trong mô hình hóa mối đe dọa, đừng quên:

  • Grafana là bề mặt tấn công, không chỉ là công cụ giám sát
  • SCIM và cung cấp danh tính là ranh giới tin cậy
  • Đầu vào từ bên ngoài cần được xác thực, dù từ nguồn "đáng tin cậy"
  • Tách biệt không gian tên ngăn chặn leo thang đặc quyền

Và cuối cùng: Monitor the monitors. Vì khi hệ thống giám sát bị xâm nhập, toàn bộ tổ chức có thể bị phơi bày trong cuộc tấn công.


References: