MOVEit supports the encryption of sensitive HTTP query parameters when generating redirection URLs. For example, if a request is made to the “/human.aspx” endpoint over plaintext HTTP, the user is redirected to the HTTPS endpoint. To generate the redirected URL, method MakeEncryptedURLIfNec()
of class MOVEit.DMZ.ClassLib.SILGlobals
will encrypt all HTTP query parameters in the original request and set the encrypted value in the ep
HTTP query parameter of the new redirected URL. When this redirected request is read by the server, method GetEncryptedQueryParameters()
of class MOVEit.DMZ.ClassLib.SILGlobals
decrypts the ep
HTTP query parameter, and the decrypted parameters are set to the server's global variables.
In addition, some redirects call method SaveArgumentsToSessionForRedirect()
of class MOVEit.DMZ.ClassLib.SILGlobals
to save the global variables to the current session. These variables are stored in the sessionvars
SQL table. When another request is made to the server with the HTTP cookie ASP.NET_SessionId
set to the same session ID, the global variables will be loaded in method LoadArgumentsFromSessionIfNeeded()
by reading them from the sessionvars
table.
An SQL injection vulnerability exists within MOVEit Transfer. This vulnerability is due to insufficient validation of encrypted query parameters sent to the server.
As mentioned above, if a request is made to the “/human.aspx” endpoint over plaintext HTTP, the server will redirect to the HTTPS endpoint with all HTTP query strings in the original request encrypted in the ep
HTTP query parameter. This allows generating arbitrary encrypted query strings. When another request is made to the “/human.aspx” endpoint with the ep
HTTP query parameter set to the encrypted query string returned by the server from the initial request, the value will be decrypted and read in method GetEncryptedQueryParameters()
. If the decrypted string contains the query string username, its value will be sanitized using the method SILUtility.XHTMLClean()
, and then URL-decoded using the method HttpUtility.UrlDecode()
. Note that due to the order of these operations, if the value contains a URL-encoded quote character (%27
), it will not be sanitized by SILUtility.XHTMLClean()
and will be successfully decoded to a quote character ('
). This improperly sanitized variable is written to the SILGlobals.LoginName
variable. If this request also contains an InitialPage
HTTP cookie with a value matching the regular expression “[a-z0-9]+\.aspx”, the SILGlobals.LoginName
variable will be saved to the sessionvars
table with a session ID generated by the server and returned in the response.
If a subsequent call is made to the “/machine.aspx” endpoint with the same session ID, the SILGlobals.LoginName
variable will be loaded by method LoadArgumentsFromSessionIfNeeded()
. Later, the method ProcessPreAuthXMLRequest()
of class MOVEit.DMZ.WebApp.SILMachine
will be called. In case the SILGlobals.Transaction
variable is set to “passchangerequest”, the method UserProcessPassChangeRequest()
of class MOVEit.DMZ.ClassLib.UserEngine
will be called with the value of the SILGlobals.LoginName
variable set as the MyLoginName
argument. In this method, the MyLoginName
argument is used when building an SQL Select query using the MOVEit.DMZ.ClassLib.SQLBasicBuilder
class. Specifically, the argument is concatenated to the query using the AddAndToWhere()
method, which does not perform any sanitization on the argument, leading to SQL injection.
A remote, unauthenticated attacker could exploit this vulnerability by sending crafted requests to the target server. Specifically, an initial request can be made to the “/human.aspx” endpoint with a crafted URL-encoded value in the username HTTP query string. Another request can be made to the “/human.aspx” endpoint with the encrypted query strings returned in the first response set in the ep HTTP query parameter, and a “.aspx” page set in the InitialPage
HTTP cookie, leading to the crafted username value being decrypted, URL-decoded, saved to the SILGlobals.LoginName
variable, and saved to the sessionvars
table. Finally, a request can be made to the “/machine.aspx” endpoint with the same session ID returned by the second response. This will lead to the crafted value being loaded from the sessionvars
table and used in the vulnerable SQL query.
A successful attack would result in arbitrary SQL command execution against the database on the target server. This would allow an attacker to inject a session into the activesessions
SQL table, allowing the attacker to authenticate as an arbitrary user. In addition, an arbitrary value may be set in the state field of the fileuploadinfo
SQL table, which is decrypted and deserialized using BinaryFormatter
. Setting this field to a crafted encrypted value would lead to insecure deserialization, which can lead to arbitrary code execution under the security context of the running service.
Detection Guidance
To detect an attack exploiting this vulnerability, the detection device must monitor and parse traffic on the ports used by MOVEit Transfer.
Note that traffic may be SSL/TLS encrypted and must be decrypted before applying the following guidance.
The detection device must monitor for HTTP requests to the MOVEit Transfer endpoint “/human.aspx”. If found, the detection device must parse the HTTP query parameters from the following URIs:
-- Request-URI of the HTTP request
-- An InitialPage
HTTP cookie value (only applicable if the value matches the regular expression “[a-z0-9]+\.aspx”)
After parsing the query parameters from both sources, the detection device must search for the “username” query parameter name. If found, and the value of the query parameter contains a URL-encoded single quote character (%27
), the traffic should be considered suspicious and an attack exploiting this vulnerability is likely underway.
Please also note the string matching of the “username” query parameter name, the “human.aspx” endpoint, and the “InitialPage” cookie name should be done in a case-insensitive manner.