high Threat analysis

SolarWinds Serv-U CVE-2026-28318: KEV Denial of Service Vulnerability in Managed File Transfer

CISA added SolarWinds Serv-U CVE-2026-28318 to KEV on 2026-06-05, indicating active exploitation. The high-severity vulnerability allows remote, unauthenticated attackers to cause a Denial of Service (DoS) by sending specially crafted HTTP POST requests with a Content-Encoding: deflate header. SolarWinds has released version 15.5.4 Hotfix 1 to address the flaw.

#solarwinds#serv-u#cisa-kev#dos#uncontrolled-resource-consumption
On this page 0% read

    Executive Summary

    CISA added CVE-2026-28318 to the Known Exploited Vulnerabilities catalog on 2026-06-05, warning of active exploitation in the wild [Source 1]. The vulnerability affects SolarWinds Serv-U managed file transfer software. It is an uncontrolled resource consumption flaw (CWE-400) that allows a remote, unauthenticated attacker to cause a Denial of Service (DoS) condition by crashing the Serv-U service [Source 1] [Source 2].

    The crash is triggered by sending a specially crafted HTTP POST request that includes the header Content-Encoding: deflate [Source 2] [Source 3]. SolarWinds released Serv-U version 15.5.4 Hotfix 1 to remediate the vulnerability [Source 2]. Administrators are strongly advised to patch their servers immediately or apply temporary mitigations such as blocking POST requests containing the Content-Encoding header or restricting access to trusted IP addresses [Source 2].

    Key Facts

    event_id: "solarwinds-serv-u-cve-2026-28318-kev"
    cve: "CVE-2026-28318"
    vendor: "SolarWinds"
    product: "Serv-U"
    kev_added: "2026-06-05"
    kev_due: "2026-06-19"
    cvss_v3: "7.5"
    cwe: "CWE-400"
    vulnerability: "uncontrolled resource consumption / remote denial of service"
    patched_version: "15.5.4 Hotfix 1"
    high_value_evidence:
      - "Serv-U-StartupLog.txt (version check)"
      - "WAF/HTTP access logs (POST requests with Content-Encoding: deflate)"
      - "/var/log/syslog or Windows Event Log (Serv-U process crash/exit)"

    Source Confidence & Evidence Mapping

    • confirmed: CISA added CVE-2026-28318 to KEV on June 5, 2026, confirming evidence of active exploitation [Source 1].
    • confirmed: SolarWinds published a trust center security advisory for CVE-2026-28318 detailing the Content-Encoding: deflate vector and releasing version 15.5.4 Hotfix 1 as the minimum patched build [Source 2].
    • confirmed: Industry advisories and analysis reports (e.g. BleepingComputer) verified the DoS behavior and provided recommended mitigations [Source 3].
    • unknown: Public sources do not identify specific threat actor groups, campaign names, victim counts, or complete packet-level exploit payloads beyond the header manipulation.

    Impact Determination

    ClassificationCriteriaRequired evidenceHandling decision
    Confirmed compromiseSystem logs show frequent Serv-U crashes correlated with incoming POST requests containing Content-Encoding: deflate, or post-crash forensic review indicates active system tampering.HTTP access/WAF logs, Serv-U process crash event IDs (e.g. Event ID 1000 on Windows or syslog segfaults on Linux), and file access logs.Isolate the system, preserve log and registry evidence, perform memory forensics, and rotate all administrative and MFT user credentials.
    Presumed exposedServ-U server is exposed to the internet and is running a version prior to 15.5.4 Hotfix 1.Serv-U version extracted from Serv-U-StartupLog.txt, binary properties, or Windows Registry.Apply Serv-U 15.5.4 Hotfix 1 immediately or implement temporary blocking mitigations at the WAF level.
    Potentially exposedServ-U is present in the network asset inventory, but its version, patch level, and external exposure status are not yet verified.CMDB assets, internal scanner logs, port scans.Verify version and external exposure paths.
    Not exposedServ-U is not deployed, or it is verified to be running version 15.5.4 Hotfix 1 or later with negative findings in crash and access logs.Version status report, system uptime checks, and log audits.Document version status, archive evidence, and continue routine monitoring.

    Timeline

    • 2026-06-05: SolarWinds publishes security advisory for CVE-2026-28318, releasing Serv-U 15.5.4 Hotfix 1 [Source 2].
    • 2026-06-05: CISA adds CVE-2026-28318 to the KEV Catalog [Source 1] [Source 3].
    • 2026-06-06: Halting Problems releases this analysis and the corresponding local/log audit scripts.
    • 2026-06-19: CISA BOD 22-01 remediation due date for federal civilian executive branch agencies [Source 1].

    Technical Analysis

    The vulnerability is rooted in how Serv-U processes compression headers in incoming HTTP requests. When an unauthenticated remote client sends an HTTP POST request containing Content-Encoding: deflate, the application attempts to decompress the payload. Due to improper resource limitation, this decompression process triggers uncontrolled CPU and memory consumption. As a result, the server runs out of memory or hangs, crashing the Serv-U service and causing a Denial of Service (DoS) for all connected file transfer users.

    While DoS vulnerabilities are often deprioritized, file transfer systems like Serv-U represent a high-value entry point. Threat actors often leverage DoS attacks to disrupt operations, mask other malicious activities, or force services to reboot in vulnerable states to hijack configurations or access files.

    Detection and Hunting

    Script: Local and Log-Based Vulnerability Audit

    The following Python script checks local Serv-U installation paths, registries, and log files for unpatched versions, system crash events, or HTTP access log entries that match the exploitation signature (POST requests utilizing deflate compression).

    #!/usr/bin/env python3
    """Audit SolarWinds Serv-U CVE-2026-28318 exposure, log anomalies, and crash indicators."""
    
    from __future__ import annotations
    
    import argparse
    import json
    import os
    import re
    import sys
    from pathlib import Path
    
    CVE = "CVE-2026-28318"
    MIN_PATCHED_VERSION = "15.5.4 Hotfix 1"
    MIN_PATCHED_VERSION_TUPLE = (15, 5, 4, 1)
    
    DEFAULT_STARTUP_LOGS = [
        r"C:\ProgramData\RhinoSoft\Serv-U\Serv-U-StartupLog.txt",
        r"C:\ProgramData\SolarWinds\Serv-U\Serv-U-StartupLog.txt",
        "/usr/local/Serv-U/Serv-U-StartupLog.txt",
    ]
    
    # SELECTORS to scan for in logs
    SELECTORS = [
        "CVE-2026-28318",
        "deflate",
        "Content-Encoding",
        "Serv-U",
    ]
    
    
    def parse_serv_u_version(version_str: str) -> tuple[int, int, int, int]:
        """Parse Serv-U version string into a comparable 4-tuple: (major, minor, patch, hotfix/build).
    
        Handles formats like:
          - "15.5.4 Hotfix 1" -> (15, 5, 4, 1)
          - "15.5.4 HF 1" -> (15, 5, 4, 1)
          - "15.5.4.123" -> (15, 5, 4, 123)
          - "15.5.4" -> (15, 5, 4, 0)
          - "15.5.3" -> (15, 5, 3, 0)
        """
        v_norm = version_str.lower().strip()
        # Replace "hotfix" or "hf" with a dot for easier regex grouping
        v_norm = re.sub(r"\b(hotfix|hf)\s*([\d]+)", r".\2", v_norm)
        digits = [int(x) for x in re.findall(r"\d+", v_norm)]
    
        if not digits:
            return (0, 0, 0, 0)
        elif len(digits) == 1:
            return (digits[0], 0, 0, 0)
        elif len(digits) == 2:
            return (digits[0], digits[1], 0, 0)
        elif len(digits) == 3:
            return (digits[0], digits[1], digits[2], 0)
        else:
            return (digits[0], digits[1], digits[2], digits[3])
    
    
    def check_windows_registry() -> str | None:
        """Retrieve Serv-U version from Windows Registry if running on Windows."""
        try:
            import winreg
            subkeys = [r"SOFTWARE\RhinoSoft\Serv-U", r"SOFTWARE\Wow6432Node\RhinoSoft\Serv-U"]
            for subkey in subkeys:
                try:
                    with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, subkey) as key:
                        version, _ = winreg.QueryValueEx(key, "Version")
                        return str(version)
                except OSError:
                    continue
        except (ImportError, OSError):
            pass
        return None
    
    
    def find_version_in_startup_log(log_path: Path) -> str | None:
        """Scan Serv-U-StartupLog.txt for Version strings."""
        if not log_path.exists():
            return None
        try:
            content = log_path.read_text(encoding="utf-8", errors="ignore")
            # Match lines like "Version 15.5.4" or "Version 15.5.4 (15.5.4.202)" or "Version 15.5.4 Hotfix 1"
            matches = re.findall(
                r"Version\s+([\d\.]+(?:\s+(?:hotfix|hf)\s+\d+)?)",
                content,
                re.IGNORECASE
            )
            if matches:
                # Return longest match as it is likely the most descriptive/precise version
                return max(matches, key=len).strip()
        except OSError:
            pass
        return None
    
    
    def scan_access_log_for_deflate_post(log_path: Path) -> list[dict[str, object]]:
        """Scan HTTP access/WAF logs for POST requests with Content-Encoding: deflate."""
        findings: list[dict[str, object]] = []
        if not log_path.exists():
            return findings
    
        try:
            with open(log_path, "r", encoding="utf-8", errors="ignore") as f:
                for line_no, line in enumerate(f, start=1):
                    # Search for POST request indicators with 'deflate' and 'Content-Encoding'
                    lower_line = line.lower()
                    if "post" in lower_line and "deflate" in lower_line:
                        findings.append({
                            "file": str(log_path),
                            "line": line_no,
                            "evidence": line.strip()[:1000],
                            "reason": "Found POST request containing deflate compression indicator",
                        })
        except OSError:
            pass
        return findings
    
    
    def check_system_crashes() -> list[str]:
        """Check system logs for Serv-U service crashes (Windows Event Log or Linux systemd)."""
        crashes = []
        if sys.platform != "win32":
            paths = ["/var/log/syslog", "/var/log/messages"]
            for p in paths:
                log_path = Path(p)
                if log_path.exists():
                    try:
                        content = log_path.read_text(encoding="utf-8", errors="ignore")
                        matches = re.findall(r".*(serv-u|Serv-U).*segfault|crash|exited.*", content, re.IGNORECASE)
                        if matches:
                            crashes.append(f"Found Serv-U crash/segfault indicators in {p}")
                    except OSError:
                        pass
        return crashes
    
    
    def main() -> int:
        parser = argparse.ArgumentParser(description=__doc__)
        parser.add_argument(
            "--version",
            help="Manually specify Serv-U version to audit (e.g. '15.5.4', '15.5.4 Hotfix 1')."
        )
        parser.add_argument(
            "--startup-log",
            type=Path,
            help="Path to Serv-U-StartupLog.txt (auto-detects if omitted)."
        )
        parser.add_argument(
            "--access-log",
            type=Path,
            help="Path to HTTP access/WAF log to scan for malicious POST deflate requests."
        )
        parser.add_argument(
            "--output",
            default="hp-serv-u-cve-2026-28318-audit.json",
            help="JSON file path to save audit results."
        )
        parser.add_argument(
            "--fail-on-open",
            action="store_true",
            help="Exit with code 2 if unpatched version or exploitation indicators are found."
        )
        args = parser.parse_args()
    
        results: dict[str, object] = {
            "cve": CVE,
            "min_patched_version": MIN_PATCHED_VERSION,
            "audited_version": None,
            "is_vulnerable": None,
            "version_source": None,
            "log_findings": [],
            "crash_findings": [],
        }
    
        # 1. Determine Version
        version_str = args.version
        version_source = "CLI Argument"
    
        if not version_str and sys.platform == "win32":
            version_str = check_windows_registry()
            if version_str:
                version_source = "Windows Registry"
    
        if not version_str and args.startup_log:
            version_str = find_version_in_startup_log(args.startup_log)
            if version_str:
                version_source = f"Startup Log ({args.startup_log})"
    
        if not version_str:
            for p in DEFAULT_STARTUP_LOGS:
                path = Path(p)
                if path.exists():
                    version_str = find_version_in_startup_log(path)
                    if version_str:
                        version_source = f"Auto-detected Startup Log ({p})"
                        break
    
        # 2. Evaluate vulnerability status
        if version_str:
            results["audited_version"] = version_str
            results["version_source"] = version_source
            parsed_v = parse_serv_u_version(version_str)
            is_vulnerable = parsed_v < MIN_PATCHED_VERSION_TUPLE
            results["is_vulnerable"] = is_vulnerable
            print(f"[+] Found Serv-U version: {version_str} via {version_source}")
            if is_vulnerable:
                print(f"[!] Serv-U version is below patched threshold ({MIN_PATCHED_VERSION}). System is VULNERABLE.")
            else:
                print(f"[+] Serv-U version is patched ({version_str} >= {MIN_PATCHED_VERSION}).")
        else:
            results["is_vulnerable"] = "Unknown (Version not detected)"
            print("[-] Serv-U version could not be detected. Check paths or provide --version.")
    
        # 3. Access/WAF Log Scan
        if args.access_log:
            print(f"[+] Scanning access log: {args.access_log}...")
            hits = scan_access_log_for_deflate_post(args.access_log)
            results["log_findings"] = hits
            print(f"[+] Found {len(hits)} suspicious deflate POST request(s).")
            for h in hits:
                print(f"    - Line {h['line']}: {h['evidence']}")
    
        # 4. Local System Crash Scan
        crash_logs = check_system_crashes()
        results["crash_findings"] = crash_logs
        if crash_logs:
            print(f"[!] System crash indicators found:")
            for crash in crash_logs:
                print(f"    - {crash}")
    
        output_path = Path(args.output)
        try:
            output_path.write_text(json.dumps(results, indent=2, sort_keys=True), encoding="utf-8")
            print(f"[+] Wrote audit results to {output_path.resolve()}")
        except OSError as e:
            print(f"[-] Failed to write JSON results to {args.output}: {e}", file=sys.stderr)
    
        vulnerable_found = results["is_vulnerable"] is True
        indicators_found = len(results["log_findings"]) > 0 or len(results["crash_findings"]) > 0
    
        if args.fail_on_open and (vulnerable_found or indicators_found):
            return 2
    
        return 0
    
    
    if __name__ == "__main__":
        raise SystemExit(main())

    Downstream Abuse Audits

    A compromise or disruption of Serv-U can expose the host and its data to significant downstream risks:

    1. Configuration Disclosure: An attacker targeting a vulnerable Serv-U server might seek to download configuration files such as Serv-U.Archive, the Users directory, or server identities (Serv-UID.txt / registry configurations). Although passwords in Serv-U.Archive are encrypted, exposure of the Server Identity allows offline decryption of user credentials, facilitating permanent unauthorized access.
    2. Sensitive File Exposure: Since Serv-U hosts enterprise file transfer interfaces, a compromised server could allow malicious access to critical corporate files, source code, data backups, or keys stored in user folders.
    3. Cloud Credential Leakage: Serv-U setups integrated with cloud backends (such as AWS S3, Azure Blob, or Google Cloud Storage) might store access credentials or OIDC integration variables on the local system. Security teams must verify file permissions on any cloud storage backend scripts and configuration files.

    Remediation

    To secure your environment, apply the following steps:

    1. Upgrade Immediately: Apply the security update to Serv-U version 15.5.4 Hotfix 1 or newer.
    2. WAF Mitigations: If patching is delayed, configure WAF rules or reverse proxies to inspect HTTP POST requests. Drop any incoming POST requests containing the Content-Encoding: deflate header.
    3. Access Control: Limit exposure by restricting access to the Serv-U HTTP/S portal to known, trusted source IP addresses.
    4. Credential Integrity: After patching, check system logs for prior crash patterns. If exploitation is suspected, rotate all Serv-U administrator passwords, user passwords, and audit the integrity of the configuration files (Serv-U.Archive).

    Machine-Readable Event Profile

    {
      "schema_version": "3.0",
      "event_id": "solarwinds-serv-u-cve-2026-28318-kev",
      "event_name": "SolarWinds Serv-U CVE-2026-28318 KEV Denial of Service Vulnerability",
      "parent_campaign_id": "none",
      "is_campaign_level": false,
      "publication_state": "publish_ready",
      "confidence": "high",
      "confidence_reason": "CISA has added this CVE to the KEV catalog, confirming active exploitation in the wild. SolarWinds has released an advisory and a hotfix.",
      "attack_types": ["Denial of Service", "Uncontrolled Resource Consumption"],
      "sources": {
        "direct": [
          "https://www.solarwinds.com/trust-center/security-advisories/CVE-2026-28318"
        ],
        "primary_research": [
          "https://www.cisa.gov/known-exploited-vulnerabilities-catalog",
          "https://www.bleepingcomputer.com/news/security/cisa-warns-of-actively-exploited-solarwinds-serv-u-dos-flaw/"
        ],
        "correlated": []
      },
      "affected_assets": {
        "ecosystems": ["SolarWinds Serv-U"],
        "registries": [],
        "packages": [],
        "versions": ["prior to 15.5.4 Hotfix 1"],
        "repositories": [],
        "vendors": ["SolarWinds"],
        "ci_cd_systems": [],
        "container_images": [],
        "developer_tools": [],
        "credentials_at_risk": ["files stored in MFT directories"]
      },
      "timeline": {
        "first_seen": "2026-06-05",
        "malicious_publish_time": "unknown",
        "discovery_time": "unknown",
        "removal_time": "unknown",
        "disclosure_time": "2026-06-05",
        "patch_or_fix_time": "2026-06-05"
      },
      "artifact_analysis": {
        "malicious_artifacts": [],
        "execution_trigger": "remote unauthenticated HTTP POST request containing Content-Encoding: deflate header",
        "payload_behavior": ["excessive CPU and memory utilization", "service crash"],
        "provenance": {}
      },
      "iocs": {
        "package_versions": [],
        "files": ["Serv-U-StartupLog.txt"],
        "hashes": [],
        "domains": [],
        "urls": [],
        "ips": [],
        "process_patterns": [],
        "network_patterns": ["POST request with Content-Encoding: deflate"]
      },
      "detection": {
        "lockfile_hunts": [],
        "filesystem_hunts": [],
        "process_hunts": [],
        "network_hunts": ["detect HTTP POST requests with Content-Encoding: deflate"],
        "ci_cd_hunts": [],
        "registry_hunts": [],
        "hunt_recipes": []
      },
      "open_questions": [],
      "defender_takeaways": {
        "detection": "Inspect WAF and HTTP reverse proxy logs for HTTP POST requests using deflate encoding.",
        "hunting": "Audit local system crash logs for Serv-U process exits and check version banner in Serv-U-StartupLog.txt.",
        "remediation": "Apply Serv-U 15.5.4 Hotfix 1 immediately.",
        "prevention": "Configure WAF to block POST requests containing Content-Encoding header if not required by business operations."
      },
      "remediation_gates": {
        "containment_complete": ["Block Content-Encoding: deflate headers", "Restrict network access to trusted IPs"],
        "eradication_complete": ["Apply Serv-U 15.5.4 Hotfix 1"],
        "recovery_complete": ["Restart Serv-U service", "Confirm normal operations"],
        "closure_required": ["Confirm version is patched", "Complete negative log audit for deflate POST requests"]
      }
    }

    Sources

    1. CISA Known Exploited Vulnerabilities Catalog
    2. SolarWinds Trust Center Security Advisory CVE-2026-28318
    3. BleepingComputer: CISA warns of actively exploited SolarWinds Serv-U DoS flaw