critical Threat analysis

Ghost CMS CVE-2026-26980: Critical SQL Injection Leads to Admin Takeover and ClickFix Campaigns

Attackers are actively exploiting CVE-2026-26980, a critical SQL injection in the Ghost CMS Content API, to extract Admin API Keys. Stolen keys are used to inject malicious JavaScript into published articles, serving ClickFix social engineering payloads to website visitors.

#ghost-cms#cisa-kev#sql-injection#clickfix#credential-theft#content-supply-chain
On this page 0% read

    Executive Summary

    A critical SQL injection vulnerability, CVE-2026-26980, in the Content API of Ghost CMS allows unauthenticated remote attackers to read arbitrary data from the database, most notably the site’s Admin API Keys [github.com] [sentinelone.com]. Possession of these keys allows full administrative control over the Ghost instance [sentinelone.com] [nvd.nist.gov].

    Starting around May 2026, threat actors launched a widespread campaign exploiting this vulnerability, compromising over 700 websites (including academic institutions and enterprise portals) [sentinelone.com] [mallory.ai]. Attackers used stolen Admin API keys to inject malicious JavaScript into published articles, executing ClickFix social engineering attacks [nvd.nist.gov] [mallory.ai]. Users visiting compromised pages are redirected to a fake Cloudflare “Verify you are human” prompt that tricks them into running malicious PowerShell commands on their local systems, leading to info-stealer infections [sentinelone.com] [mallory.ai].

    The vulnerability affects Ghost CMS versions 3.24.0 through 6.19.0 and was patched in version 6.19.1 [github.com] [mallory.ai]. Operators of Ghost instances should immediately upgrade to version 6.19.1 or newer, audit published content for injected scripts, and rotate all Admin API keys [sentinelone.com].

    Key Facts

    Cve: CVE-2026-26980

    Vendor: Ghost Foundation

    Product: Ghost CMS

    Cvss V3 1: 9.4 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)

    Cwe: CWE-89

    Disclosed Date: 2026-02-19

    Earliest Observed Exploitation: 2026-05-15

    Ecosystem: npm

    Registry: npm

    Affected Packages:

    • ghost

    Affected Versions: 3.24.0 to 6.19.0

    Package Versions:

    • 3.24.0
    • 6.19.0

    Fixed Version: 6.19.1

    Affected Configuration:

    • Ghost CMS instance running vulnerable version
    • Content API is exposed to untrusted requests

    High Value Evidence:

    • package.json
    • Admin API log showing unauthorized POST requests
    • Injected script tags in published posts database

    Credentials At Risk:

    • Ghost Admin API keys

    Evidence Assessment

    • confirmed: SentinelOne and other security vendors confirm active exploitation of CVE-2026-26980 to extract Admin API keys and modify blog contents [sentinelone.com] [nvd.nist.gov].
    • confirmed: Attackers use stolen keys to execute ClickFix attacks, prompting visitors to execute PowerShell code to deploy infostealer payloads [sentinelone.com] [mallory.ai].
    • confirmed: Ghost Foundation released version 6.19.1 to patch the SQL injection in the Content API slug filter [github.com] [mallory.ai].
    • unclear: Public reports do not identify all affected domains or the total quantity of compromised Admin API keys currently in circulation.

    Impact Determination

    ClassificationCriteriaRequired evidenceHandling decision
    Confirmed compromiseGhost instance is below 6.19.1, and web server logs, database audits, or system logs show unauthorized Content API SQL injection attempts or injected JavaScript blocks in post content.Log events showing SQL injection syntax in request paths, database records containing injected <script> tags, or unauthorized Admin API key activity.Isolate the application instance, rotate all Admin API keys, inspect and restore all published content to a clean state, and perform host-level forensics.
    Presumed exposedGhost CMS instance is verified to be within versions 3.24.0 to 6.19.0 and exposed to the public internet during the May 2026 onward campaign window.Installed package metadata (package.json, lockfiles) or web server configuration showing public access to the Content API.Upgrade immediately to 6.19.1 or newer, check all post contents for external scripts, and proactively rotate all Admin API keys.
    Potentially exposedGhost CMS is used in the infrastructure but version, patching state, or key rotation status is unverified.Software asset list, dependency logs, or incomplete patch reports.Run immediate vulnerability scans and verify the installed Ghost CMS build version.
    Not exposedGhost CMS is verified to be running version >= 6.19.1, or the platform is not present in the environment.Verified build files, deployment manifests, or negative asset inventory results.No immediate remediation action required.

    Timeline

    • 2026-02-19: Ghost Foundation patches CVE-2026-26980 in version 6.19.1 [github.com].
    • 2026-05-15: Earliest observed active exploitation chaining the SQL injection with ClickFix malicious scripts [sentinelone.com].
    • 2026-06-01: Security vendors report over 700 sites compromised in the campaign, targeting university and corporate blogs [sentinelone.com] [mallory.ai].
    • 2026-06-11: This threat post analysis is published.

    Technical Analysis

    The vulnerability, CVE-2026-26980, is an unauthenticated SQL injection vulnerability within the Content API of Ghost CMS [github.com] [sentinelone.com]. The issue occurs due to improper input sanitization in the API’s slug filtering logic. An attacker can supply a crafted database query inside a slug parameter request (e.g. via the /ghost/api/v3/content/posts/ endpoint), allowing them to bypass normal query logic and extract arbitrary database records [sentinelone.com] [nvd.nist.gov].

    Because Ghost stores its administrative credentials and Admin API keys in the database, unauthenticated attackers can extract these keys [sentinelone.com]. With a valid Admin API key, the attacker can make authenticated requests to the Admin API, bypass normal dashboard authentication, and add custom scripts to the site’s head/foot templates or post bodies [sentinelone.com] [nvd.nist.gov].

    In the observed campaign, attackers injected malicious script tags that dynamically load fake verification pages (ClickFix) designed to trick users into running local PowerShell scripts, causing the execution of infostealers [mallory.ai] [nvd.nist.gov].

    Affected Assets and Blast Radius

    Affected Assets:

    • Internet-exposed Ghost CMS instances below version 6.19.1

    Highest Priority:

    • Production blog instances with public-facing Content APIs
    • Workstations of administrators who accessed compromised Ghost dashboards

    Credentials And Data At Risk:

    • Ghost Admin API keys
    • Ghost database contents (user lists, hashed passwords, drafts)
    • Downstream reader systems (subject to ClickFix drive-by injection)

    Indicators of Compromise

    The following indicators of compromise (IOCs) can be used to scope exposure across local repositories, systems, and telemetry exports:

    Package Versions

    • 3.24.0
    • 6.19.0

    Files

    • UtilifySetup.exe
    • update.zip
    • NotepadPlusPlus.zip

    Domains

    • clo4shara[.]xyz
    • com-apps[.]cc
    • cloud-verification[.]com

    Detection and Hunting

    Hunt Manifest: ghost-cms-cve-2026-26980-takeover-hunt-1

    • Title: local repository and exported telemetry scope
    • Question: Does the telemetry scope contain patterns associated with Ghost CMS CVE-2026-26980: Critical SQL Injection Leads to Admin Takeover and ClickFix Campaigns?
    • Telemetry Family: process
    • Telemetry Context: host filesystem or log export
    • Positive Signal: Indicators of compromise matched in telemetry: local repository and exported telemetry scope
    #!/usr/bin/env python3
    import os
    import sys
    import subprocess
    from pathlib import Path
    
    ROOT = sys.argv[1] if len(sys.argv) > 1 else "."
    LOG_ROOT = os.environ.get("LOG_ROOT", "")
    OUT = Path(os.environ.get("OUT", "hp-ghost-cms-cve-2026-26980-takeover-scope"))
    
    PACKAGES = ["ghost"]
    VERSIONS = ["3.24.0","6.19.0"]
    FILES = ["UtilifySetup.exe","update.zip","NotepadPlusPlus.zip"]
    DOMAINS = ["clo4shara.xyz","com-apps.cc","cloud-verification.com"]
    
    # Collect unique indicators
    indicators = set()
    for group in [PACKAGES, VERSIONS, FILES, DOMAINS]:
        for val in group:
            if val:
                indicators.add(val)
    
    with open(indicators_file, "w") as f:
        for ind in sorted(indicators):
            f.write(ind + "\n")
    
    print(f"[+] Written unique selectors to {indicators_file}")
    
    # Walk local directory
    print(f"[+] Scanning directory: {ROOT} for selectors...")
    matches = []
    exclude_dirs = {"node_modules", "vendor", "dist", ".git"}
    for root, dirs, filenames in os.walk(ROOT):
        dirs[:] = [d for d in dirs if d not in exclude_dirs]
        for filename in filenames:
            filepath = Path(root) / filename
            try:
                content = filepath.read_text(errors="ignore")
                for ind in indicators:
                    if ind in content:
                        matches.append(f"{filepath}: found '{ind}'")
            except Exception:
                pass  # pass # return or raise not needed here
    
    if matches:
        (OUT / "repository-indicator-matches.txt").write_text("\n".join(matches) + "\n")
        print(f"[!] Found {len(matches)} matches in codebase!")
    
    # Optional Log Scanning
    if LOG_ROOT and os.path.exists(LOG_ROOT):
        print(f"[+] Scanning telemetry log directory: {LOG_ROOT}...")
        log_matches = []
        for root, _, filenames in os.walk(LOG_ROOT):
            for filename in filenames:
                filepath = Path(root) / filename
                try:
                    content = filepath.read_text(errors="ignore")
                    for ind in indicators:
                        if ind in content:
                            log_matches.append(f"{filepath}: found '{ind}'")
                except Exception:
                    pass  # pass # return or raise not needed here
        if log_matches:
            (OUT / "exported-telemetry-indicator-matches.txt").write_text("\n".join(log_matches) + "\n")
            print(f"[!] Found {len(log_matches)} matches in logs!")
    
        if PACKAGES:
            registry_dir = OUT / "registry"
            registry_dir.mkdir(exist_ok=True)
            for package in PACKAGES:
                if not package: continue
                safe_name = package.replace("/", "__")
                print(f"[+] Querying npm view for {package}...")
                res = subprocess.run(["npm", "view", package, "name", "version", "time", "versions", "dist-tags", "maintainers", "dist.tarball", "dist.integrity", "scripts", "--json"], capture_output=True, text=True)
                if res.returncode == 0:
                    (registry_dir / f"npm-{safe_name}.json").write_text(res.stdout)
    
    print(f"[+] Wrote scope artifacts under {OUT}")

    Downstream Abuse Audits

    Compromised workstations expose active API credentials, requiring immediate rotated revocation. The following platforms are at risk:

    • GitHub OIDC and PATs: Attackers harvested SSH private keys and Git Personal Access Tokens. Auditors must inspect recent action runs and release logs during the exposure window.
    • Cloud IAM Credentials: AWS, Azure, and GCP session tokens. CloudTrail and Activity Logs should be queried for AssumeRole or write operations originating from unexpected IP addresses.
    • NPM and Package Registries: Publishing tokens and credentials. Registry profiles must be audited for unauthorized version publishes or token additions.

    Remediation and Closure

    1. Upgrade: Upgrade all Ghost CMS instances immediately to version 6.19.1 or newer.
    2. Rotate Keys: Generate new Admin API keys and revoke any existing keys that were active prior to the upgrade.
    3. Audit Database: Query the database for any injected script tags or raw HTML tags containing untrusted domains (e.g., clo4shara[.]xyz or com-apps[.]cc).
    4. Endpoint Triage: If an administrator or user is confirmed to have clicked on a fake Cloudflare captcha page, isolate the workstation immediately and inspect for infostealer execution.

    Sources

    1. GitHub: Ghost CMS CVE-2026-26980 Patch release - Role: DIRECT_SOURCE - Impact: Vulnerability patches and fix version information.
    2. SentinelOne: Widespread Exploitation of Ghost CMS Vulnerability Leads to ClickFix Attacks - Role: PRIMARY_RESEARCH - Impact: Campaign scope, Admin API key extraction details, and threat behavior.
    3. NVD: CVE-2026-26980 - Role: ENRICHMENT_DATA - Impact: CWE mapping, CVSS score, and vulnerability descriptions.
    4. Mallory Security: Massive ClickFix Campaign Targeting Ghost CMS Users - Role: PRIMARY_RESEARCH - Impact: Indicators, ClickFix domain list, and payload file names.

    IOC Clipboard

    3 IOCs
    Defang IOCs
    domain clo4shara.xyz clo4shara[.]xyz
    domain com-apps.cc com-apps[.]cc
    domain cloud-verification.com cloud-verification[.]com