{
	"id": "4e2e90b1-441c-4d3f-86b3-155179c69a2d",
	"created_at": "2026-04-06T00:07:06.469039Z",
	"updated_at": "2026-04-10T03:20:42.146738Z",
	"deleted_at": null,
	"sha1_hash": "2e4867c4900061dc4ebdecd749152a0ea730ced2",
	"title": "How the Kaseya VSA Zero Day Exploit Worked - Trulysuper",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 61042,
	"plain_text": "How the Kaseya VSA Zero Day Exploit Worked - Trulysuper\r\nBy siteadmin\r\nPublished: 2021-07-06 · Archived: 2026-04-05 12:49:43 UTC\r\nDetailed description of the exploit in four steps\r\nThis article explains the pre-auth remote code execution exploit against Kaseya VSA Server that was used in the mass Revil\r\nransomware attack on July 2, 2021.\r\nOn July 5, after an initial investigation of affected organizations, Truesec contacted Kaseya and provided a detailed technical\r\nwrite-up of these vulnerabilities along with forensic evidence of exploitation. Kaseya released the patch 9.5.7a (9.5.7.2994)\r\nthat addresses the security issues on July 11.\r\nWe strongly believe this information will help the security community in their response to the attack and from a larger\r\nperspective it will help the industry understand what happened so we can address the underlying issues, and ultimately\r\nincrease our capabilities to prevent future breaches.\r\nOverview\r\nThe exploit abused four vulnerabilities in the Kaseya application that were chained as visualized in the figure below.\r\nThe exploit abused four vulnerabilities in the Kaseya application that were chained as visualized here\r\nThe High-Level Steps of the Exploit\r\n1. Obtained an authenticated session by abusing a flaw in the authentication logic [CWE-304] in /dl.asp.\r\n2. Uploaded the revil ransomware (agent.crt) through an unrestricted upload vulnerability [CWE-434] while also\r\nbypassing the request forgery protection [CWE-352] in /cgi-bin/KUpload.dll.\r\n3. Uploaded the ASP payload (screenshot.jpg) in the same fashion as described in 2.\r\n4. Invoked the payload in screenshot.jpg through a local code injection vulnerability [CWE-94] in\r\nuserFilterTableRpt.asp.\r\n5. Created Kaseya procedures to copy files and execute the ransomware.\r\n6. Executed the procedures.\r\n7. Removed logs and other forensic evidence.\r\nHere we will focus on the exploit and describe steps 1 through 4 in detail.\r\nThe payloads are not in scope for this article.\r\nStep 1 – Bypassing Authentication [CWE-304]\r\nThe threat actor first sent a POST request to the resource /dl.asp with the POST data userAgentGuid=guid.\r\nkaseya-supply-chain-attack-targeting-msps-to-deliver-revil-ransomware-exploit-1-1\r\nFirst request of the exploit: authentication bypass\r\nIn dl.asp, userAgentGuid is used in a SELECT query to lookup the database row of the agent. The agentGuid must exist due\r\nto the subsequent if statement. The threat actor used the agentGuid of the agent on the VSA server itself (more on this\r\nbelow).\r\nAfter the lookup, dl.asp tries to see if the provided password matches the values stored in the database for that agent. The\r\nprovided password is then compared in several different ways. The login flow is illustrated in the pseudo code below:\r\nif password == hash(row[nextAgentPassword] + row[agentGuidStr])\r\nlogin ok\r\nelseif password == hash(row[curAgentPassword] + row[agentGuidStr])\r\nlogin ok\r\nelseif password == hash(row[nextAgentPassword] + row[displayName])\r\nhttps://blog.truesec.com/2021/07/06/kaseya-vsa-zero-day-exploit\r\nPage 1 of 4\n\nlogin ok\r\nelseif password == hash(row[curAgentPassword] + row[displayName])\r\nlogin ok\r\nelseif password == row[password]\r\nlogin failed\r\nelse\r\nlogin ok\r\nThe last two statements are where the interesting thing happens. In case the password equals row[password] the login will\r\nfail. However, in the case that all checks failed, it would default to an else clause that sets “loginOK” to true.\r\nBecause no password was provided in the request, the “password” variable would be NULL and loginOK would end up\r\nbeing true. When loginOK is set to true, the application sends the login session cookie and will eventually (if no other\r\nparameters are provided like in the attacker’s request) end up in an if clause that returns 302 redirect to the userPortal.\r\nResponse to authentication bypass request\r\nResponse to authentication bypass request\r\nHow Did the Actor Obtain the AgentGuid?\r\nThe outstanding question is how the threat actor obtained around 60 (estimated number of VSA victims) unique valid\r\nagentGuids. It appears they simply knew the agentGuids before launching the attack.\r\nTruesec has discovered several methods the attack could have been performed without prior knowledge of a valid\r\nagentGuid. An example that was also fixed in 9.5.7a is that the userAgentGuid parameter could have been\r\n\u003cvsa_server_hostname\u003e.root.kserver instead of an actual agentGuid. Due to what was described as legacy code, in case\r\nagentGuid is not a number, it will lookup the agentGuid automatically from the table machNameTab.\r\nTruesec has not found and is not aware of any public evidence that shows exactly how these agentGuids were obtained.\r\nPossibly, these random agentGuids might have been what limited the impact of the attack to under 60 out of around 35 000\r\nKaseya VSA customers.\r\nSteps 2 and 3 – Uploading Files [CWE-434] [CWE-352]\r\nAll requests from this point on used the authenticated session obtained in step one.\r\nThe threat actor started the upload by sending a GET request to /done.asp without any parameters. When receiving the\r\nrequest, the application creates a row in the tempData table, stages an upload folder, and finally returns a so-called loadKey\r\nvalue. A valid loadkey is required to perform the file upload.\r\nkaseya-supply-chain-attack-targeting-msps-to-deliver-revil-ransomware-exploit-2\r\nRequest and response to obtain a valid loadKey\r\nTo upload files the threat actor sent a multiform-data POST request to the resource /cgi-bin/KUpload.dll. The request\r\ncontained the following parameters:\r\nFileName (name of the file)\r\nFileData (content of the file to upload)\r\nLoadKey (the value obtained by GETting done.asp)\r\nRedirectPath (path that the application will redirect to after successful upload)\r\nPathData (folder the file will be saved in)\r\n__RequestValidationToken (bypassable CSRF token)\r\nBypassing the CSRF Protection\r\nThe __RequestValidationToken was not properly validated. For example, the value “xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx” was accepted as a valid token.\r\nUploading the Ransomware (Agent.crt)\r\nhttps://blog.truesec.com/2021/07/06/kaseya-vsa-zero-day-exploit\r\nPage 2 of 4\n\nThe first upload performed by the threat actor was a file named agent.crt. This file was an encoded version of the\r\nransomware that was later pushed to all agents from the compromised VSA server.\r\nupload of agent\r\nUpload of agent.crt.\r\nUpon successful upload, the server returns HTTP 200 OK with a body containing a link pointing to /\u003credirectPath\u003e?\r\nFileName=\u003cfilename\u003e\u0026PathData=\u003crelative path\u003e\u0026originalName=\u003cfilename\u003e\u0026FileSize=\u003csize\u003e\u0026TimeElapsed=\u003ctime\u003e.\r\nIn this case, as the file upload was successful, the returned link was /done.asp?\r\nFileName=agent.crt\u0026PathData=WebPagesManagedFilesVSATicketFiles\u0026originalName=agent.crt\u0026FileSize=1221630\u0026TimeElapsed=00:00:0\r\nUploading the ASP Payload (Screenshot.jpg)\r\nThe threat actor uploaded another file named Screenshot.jpg. This was not a jpg file but rather a text file containing ASP\r\ncode. After obtaining another loadKey value from /done.asp the threat actor uploaded the file. Partial contents of the request\r\ncan be seen in the figure below (unfortunately only a partial capture was obtained and the middle part of screenshot.jpg was\r\nmissing).\r\nkaseya-supply-chain-attack-targeting-msps-to-deliver-revil-ransomware-exploit-3\r\nFirst part of uploaded screenshot.jpg.\r\nLast part of uploaded screenshot.jpg.\r\nLast part of uploaded screenshot.jpg.\r\nThe response body link in this case was /done.asp?\r\nFileName=Screenshot.jpg\u0026PathData=WebPagesManagedFilesVSATicketFiles\u0026originalName=Screenshot.jpg\u0026FileSize=6188\u0026TimeElapsed=\r\nwhich indicates that the file was successfully uploaded.\r\nStep 4 – Executing the Payload on the Server [CWE-94]\r\nFinally, the threat actor sent a POST request to /userFilterTableRpt.asp with the pageFilterSQLFile argument.\r\nkaseya-supply-chain-attack-targeting-msps-to-deliver-revil-ransomware-exploit-4 (1)\r\nExploiting the code injection vulnerability.\r\nDue to a flaw in userFilterTableRpt.asp, the contents of the specified file would be interpreted as ASP code as it was passed\r\nto the function eval. In this case, ManagedFiles/VSATicketFiles/Screenshot.jpg, the ASP code text file the threat actor just\r\nuploaded.\r\nFirst, userFilterTableRpt.asp sets a variable from the POST parameter. Then it reads the contents of the specified file and\r\npasses it to eval, which will by definition interpret the value of the argument as code. The flow is illustrated in the pseudo\r\ncode below:\r\nf = open (pageFilterSQLFile)\r\nc = read (f)\r\neval (c)\r\nAnd that is it. The ASP payload was executed and started pushing out the ransomware, and we all know the story from there.\r\nFinal Words\r\nAfter a patch has been made available to customers of Kaseya VSA, and after we have validated the patch to verify that the\r\nattack vector is no longer present, we believe it is time to share these details for the benefit of the community.\r\nWe strongly believe this information will help the security community in their response to the attack and from a larger\r\nperspective it will help the industry understand what happened so we can address the underlying issues, and ultimately\r\nincrease our capabilities to prevent future breaches.\r\nFinally, a big thanks to everyone in the security community who shared their findings throughout this incident. We truly\r\nappreciate the collaborative spirit that ultimately benefits everyone.\r\nhttps://blog.truesec.com/2021/07/06/kaseya-vsa-zero-day-exploit\r\nPage 3 of 4\n\nTimeline\r\n[2021-07-02] Threat actor exploited vulnerabilities in the wild to mass-deploy ransomware.\r\n[2021-07-04] Truesec obtained evidence that was helpful to understand the exploit.\r\n[2021-07-05] Truesec sent a detailed write-up of the vulnerabilities along with supporting forensic evidence to Kaseya.\r\n[2021-07-11] Kaseya released a security patch.\r\n[2021-07-12] Truesec validated the patch.\r\n[2021-07-13] Truesec published this article.\r\nSource: https://blog.truesec.com/2021/07/06/kaseya-vsa-zero-day-exploit\r\nhttps://blog.truesec.com/2021/07/06/kaseya-vsa-zero-day-exploit\r\nPage 4 of 4",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://blog.truesec.com/2021/07/06/kaseya-vsa-zero-day-exploit"
	],
	"report_names": [
		"kaseya-vsa-zero-day-exploit"
	],
	"threat_actors": [],
	"ts_created_at": 1775434026,
	"ts_updated_at": 1775791242,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/2e4867c4900061dc4ebdecd749152a0ea730ced2.pdf",
		"text": "https://archive.orkl.eu/2e4867c4900061dc4ebdecd749152a0ea730ced2.txt",
		"img": "https://archive.orkl.eu/2e4867c4900061dc4ebdecd749152a0ea730ced2.jpg"
	}
}