CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-HR7J-63V7-VJ7G
7.50.04%

The Phantom Session: Surviving the Ban Hammer in Pterodactyl

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 17, 2026·6 min read·1 visit

PoC Available

Executive Summary (TL;DR)

A critical logic flaw in Pterodactyl Panel < 1.12.1 allowed SFTP sessions to persist after user account deletion or password resets. Because the Panel failed to signal the Wings daemon to terminate active connections, a banned user with an open SFTP client could continue to read, write, or delete files indefinitely. The fix involves a new asynchronous revocation job that forcibly kills these sessions.

In the world of game server hosting, Pterodactyl is the undisputed king. But a synchronization gap between the management Panel and the remote Wings daemon created a zombie apocalypse scenario: SFTP sessions that refused to die. This vulnerability allowed malicious users to maintain full filesystem access to servers even after their accounts were deleted or passwords changed, turning a standard termination procedure into a race against a lingering, unauthorized open socket.

The Architecture: Brains vs. Brawn

To understand why this bug exists, you have to understand Pterodactyl's split-personality architecture. You have the Panel, a PHP application that acts as the brain. It handles user management, billing logic, and the pretty UI. Then you have Wings, the Go-based daemon sitting on the remote servers. Wings is the brawn; it runs the Docker containers, manages the file systems, and handles the heavy lifting.

Communication between these two is vital. When a user logs in to SFTP, they aren't authenticating against a local Linux user file; they are authenticating against Wings, which checks with the Panel to see if the credentials are valid. It's a classic distributed system pattern.

The problem with distributed systems is state. Who owns the truth? In this case, the Panel knew the user was banned. The database knew the user was banned. But Wings? Wings was still happily piping data through an open TCP socket, completely unaware that the entity on the other end had been digitally executed minutes ago.

The Flaw: The polite breakdown of communication

The vulnerability wasn't a buffer overflow or a complex cryptographic failure. It was a failure of courtesy. When an administrator deletes a user or a user resets their password, the Panel updates its database immediately. Any new login attempts would fail instantly because Wings would ask the Panel, "Hey, is this guy cool?" and the Panel would say, "New phone, who dis?"

However, for existing connections, silence reigned supreme. SFTP (SSH File Transfer Protocol) runs over a persistent connection. Once the handshake is done and the session is established, the authentication phase is over. Unless the software explicitly implements a "kill switch" or periodic re-validation, that pipe stays open until the client disconnects or the network drops.

Pterodactyl simply didn't have code in place to tap Wings on the shoulder and say, "Cut the cord." This meant a user could open an SFTP client, initiate a transfer or just idle, have their account deleted by an admin, and then proceed to rm -rf / the server contents hours later. It is the digital equivalent of firing an employee but forgetting to deactivate their keycard while they are still inside the building.

The Code: Adding the Kill Switch

The fix, landed in version 1.12.1 via commit 0e74f3aadec89405751ec602c77fc1d030a417c0, introduces the missing communication loop. The developers realized that database state changes needed to trigger active enforcement on the edge nodes.

The patch introduces a new event listener infrastructure. Specifically, they added a RevokeSftpAccessJob. This isn't just a simple API call; it's a queued job with retries. This is crucial because if the remote node is temporarily offline when the user is banned, a synchronous call would fail, and the zombie session would survive. By using a job queue with exponential backoff, the Panel ensures that the "kill" command is eventually delivered.

Here is the logic added to the RevocationListener.php. Notice how it grabs every node the user had access to and dispatches a job to hunt them down:

// app/Listeners/RevocationListener.php
 
public function revoke(Deleting|PasswordChanged $event): void
{
    $user = $event->user;
    
    // Find all nodes where this user has a server
    Node::query()
        ->whereIn('nodes.id', $user->accessibleServers()->select('servers.node_id')->distinct())
        ->chunk(50, function (Collection $nodes) use ($user) {
            // Dispatch the hit squad (RevokeSftpAccessJob)
            $nodes->each(fn (Node $node) => RevokeSftpAccessJob::dispatch($user->uuid, $node));
        });
}

This code effectively says: "I don't care where you are hiding. I will find every server you have access to, and I will terminate your connections."

The Exploit: The scorched earth exit

Let's roleplay a disgruntled community manager, "Dave". Dave knows he's about to be fired from the gaming community he helps run. Dave is petty. Dave wants to watch the world burn.

Step 1: The Setup Dave logs into his FileZilla client and connects to the Minecraft server's SFTP interface. He navigates to the backup folder. He doesn't do anything yet; he just keeps the connection alive (most clients send keep-alive packets automatically).

Step 2: The Ban The Head Admin bans Dave. They delete his Pterodactyl account to be safe. They pat themselves on the back for a job well done. In the Panel logs, Dave is gone. In the database, Dave is gone.

Step 3: The Ghost Dave's FileZilla client doesn't disconnect. The TCP stream is still valid. The Wings daemon hasn't received a RST packet or a termination signal. Dave, now technically a non-existent user, highlights the entire world_the_end folder and hits delete.

Step 4: The Damage Because the session holds the file descriptors and permissions of the user at the time of connection, the deletion proceeds. Dave then uploads a small script named start.sh that loops forever and eats RAM, crashing the node. Dave closes FileZilla and goes to lunch. The admins are left wondering how a "deleted" user just nuked their infrastructure.

The Mitigation: Update or Restart

If you are running Pterodactyl Panel versions prior to 1.12.1, you are vulnerable. The update path is straightforward and standard for Laravel applications. Pull the new code, run the migrations, and restart the queue workers so they pick up the new job definitions.

php artisan down
git pull origin stable
composer install --no-dev --optimize-autoloader
php artisan migrate
php artisan queue:restart
php artisan up

If you cannot update immediately (perhaps you have custom modifications that make merging painful), your mitigation strategy is brute force. Whenever you demote a high-privilege user or delete a suspicious account, you must manually restart the wings service on the nodes they accessed.

systemctl restart wings

This will sever all active connections to that node. It's a sledgehammer, not a scalpel, but it guarantees that the ghost sessions are exorcised. Monitoring tools can also help; keeping an eye on netstat for long-lived connections from known bad IPs is good practice, though difficult to attribute to specific users without deep packet inspection or log correlation.

Official Patches

PterodactylGitHub Commit Diff

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

Pterodactyl Panel < 1.12.1Wings Daemon (indirectly involved in session handling)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Pterodactyl Panel
Pterodactyl
< 1.12.11.12.1
AttributeDetail
Vulnerability TypeImproper Session Handling / Auth Bypass
Attack VectorNetwork
ConfidentialityHigh (File Access)
IntegrityHigh (File Modification)
AvailabilityHigh (Service Disruption via file deletion)
CVSS Score7.5 (High)

MITRE ATT&CK Mapping

T1078Valid Accounts
Persistence
T1098Account Manipulation
Persistence
CWE-613
Insufficient Session Expiration

The software does not properly terminate a session when the user's account is deleted or privileges are revoked, allowing continued access.

Known Exploits & Detection

TheoryStandard persistence via established TCP connection after auth revocation.

Vulnerability Timeline

Patch Committed to GitHub
2026-02-14
Advisory Published
2026-02-14

References & Sources

  • [1]GitHub Advisory GHSA-hr7j-63v7-vj7g

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.