In Blog

It has been about a year since a wave of attacks hit organizations using the managed file transfer application MOVEit Transfer by Progress Software. Back then, the critical vulnerability CVE-2023-34362 allowed an unauthenticated attacker to gain control of the database and could even lead to remote code execution.

Fast forward to now, organizations have been urged to apply patches as a security advisory has been released by Progress Software. The newly disclosed CVE-2024-5806 is a critical vulnerability inside the SFTP module of MOVEit Transfer which allows an unauthenticated attacker to bypass SSH authentication and gain access to any user and their files. Detailed technical analyses of the vulnerability have been published independently by Watchtowr and Rapid7.

 

The Root Issue – Logic Bug

Based on both analyses, it appears that the root cause of the vulnerability is a logic bug due to a mishandled application state during authentication. The following Authenticate function was vulnerable and the fixed version sets an error code and description in two specific cases.

public AuthenticationResult Authenticate(SILUser user)
    {
      if (string.IsNullOrEmpty(this._publicKeyFingerprint) && !this._keyAlreadyAuthenticated)
      {
        this._logger.Error("Attempted to authenticate empty public key fingerprint");
+        this.StatusCode = 2414;
+        this.StatusDescription = "No public key provided";
        return AuthenticationResult.Denied;
      }
      if (string.IsNullOrEmpty(user.ID))
      {
        this._logger.Debug("No user ID provided for public key authentication");
+        this.StatusCode = 2050;
+        this.StatusDescription = this._i18N.GetMsg(60001);
        return AuthenticationResult.Denied;
      }

The teams found that the two conditional branches where the application denies (AuthenticationResult.Denied) the authentication but does not change the StatusCode from 0 (the default value), lead to a vulnerable state that allows an attacker to bypass authentication.

Further in the authentication logic, if the StatusCode is 0 even though the initial result is AuthenticationResult.Denied, it would change the result to Authentication.Indeterminate which indicates that the public key was valid but additional authentication is required. As the Authentication.Indeterminate status implies a valid key, the application remembers that the key was already validated and further checks of _keyAlreadyAuthenticated will evaluate to true and further logic will end up authenticating as the user.

Watchtowr’s team first showed how to exploit the issue via a 0-day vulnerability inside a third-party library as it would allow to provide an empty key fingerprint, thus entering the first “If”. About a week later, Rapid7’s analysis showed an exploit through the second “If” by being able to supply an empty user ID.

 

Third Party Library – IPWorks SSH

The researchers at Watchtowr were able to identify an unusual behavior inside the third-party library IPWorks SSH used by MOVEit’s SFTP module to handle SSH connections. When authenticating via SSH public key authentication to the server, the library would attempt to treat the provided key as a path and even try to load the file at the path expecting a valid key. The usual expected behavior is that the provided key data inside the authentication request contains the key itself.

By monkey patching an SSH client, the researchers were able to trigger the vulnerable behavior, provided they had a valid username. Showcasing their first attack scenarios, they demonstrated that it was possible to coerce an SMB authentication when providing an UNC path to the server. This would yield the NetNTLM hash of the account running the SFTP server and even allow relay attacks if no firewall was present. This scenario could potentially lead to a full compromise of the server if the compromised account could connect remotely and had dangerous privileges.

While the need of a valid username could be seen as a limiting factor, they also showed that since the file was fetched only if the username was valid, an attacker could potentially spray usernames while pointing the path to a remote server which would be listening to DNS interactions. If any interaction occurred, this would reveal a valid username.

The second, more devastating attack scenario, was due to what happened after the key at the file path was loaded. If the path pointed to a valid key, even though the request would be validated, the value of _publicKeyFingerprint returned by the library would be empty. This would trigger the first conditional branch and subsequently allow authentication bypass.

Watchtowr further discussed various techniques they used to provide an attacker-controlled key locally so that the exploit does not depend on the presence of a firewall. In short, the combination of a lax parsing PuTTY Private Keys as well as a log injection from an unauthenticated user, allows them to plant a valid key inside a log file on the server and execute the attack.

 

Username Differential – Invalid Then Valid

Rapid7’s exploit has similar conditions for exploitation as it also requires knowing a valid username which will be the victim. The main difference with Watchtowr’s exploit is that it does not use the vulnerable behavior of IPWorks SSH and does not require planting a key inside the server.

Instead, it relies on how usernames are provided during the SSH authentication process. The initial message sent by the client during authentication contains the username as well as the public key. When receiving this message with an invalid username, the vulnerable SFTP server will end up running the Authenticate function with an empty user.ID, thus triggering the second vulnerable conditional branch.

This initial message is usually used to test if the user can indeed login with the provided public key. This test helps avoiding unnecessary expensive signature verification. Although, as Rapid7’s first message triggers the vulnerable state (inside the second “If”), whichever provided public key will be authenticated and _keyAlreadyAuthenticated will be set to True.

The subsequent call to Authenticate would authenticate the user with the arbitrary key, but as mentioned earlier, the specified user is currently invalid. The technique used by Rapid7 was to abuse the fact that the second message during authentication also contains a username field and no checks were performed to ensure the username in the second message matches the one from the first message. Despite the different usernames, the second message would carry on the saved value of _keyAlreadyAuthenticated. This would lead to authenticating as that username with any arbitrary key that was “validated” during the first message due to the vulnerable state.

 

Conclusion

While both teams’ proofs of concept are relatively simple, the discovery itself of the vulnerability was described as complex. This specific bug required knowledge of the SSH authentication protocol as well as great reverse engineering ability. The discovery of the 0-day on IPWorks SSH will also need to be addressed as it likely impacts many other applications that use the library.

Logic bugs can be very hard to identify via code review as often state can be hard to track without dynamic analysis. It is even harder, and could even be impossible, for SAST tools to identify such bugs as usually they have no concept of what constitutes an “invalid” or “dangerous” state.

It is unknown who first discovered the vulnerability, but kudos to Watchtowr and Rapid7, their reverse engineering of the patch is invaluable to the community as they share IoCs for blue teams.

MOVEit definitely seems to be in the crosshairs of bad actors, and this has grave consequences. If you are looking for an alternative, OKIOK’s S-Filer Portal is a full-fledged MFT solution with the same feature set as MOVEit.

Leave a Comment

Start typing and press Enter to search