flawopen.com/Incidents/MOVEit CVE-2023-34362

MOVEit Transfer: one SQL injection, thousands of organisations

Critical — Mass exploitation CWE-89: SQL Injection Disclosed 31 May 2023
ELI5

A courier company runs a secure depot where other businesses leave parcels for each other. Someone finds that the request form at the front desk can be filled in with extra instructions that the clerk follows literally — including "and also give me a permanent staff pass". Because hundreds of businesses all use the same depot, robbing the depot once robs all of them.

Key terms on this page
managed file transfer (MFT)
Software organisations use to exchange large or sensitive files with partners. By design it is internet-facing and full of other people's confidential data — an unusually concentrated target.
web shell
A script planted on a compromised server that gives the attacker an ongoing command interface, surviving after the original exploit is patched.
zero-day
A vulnerability being exploited before the vendor has released a fix.

What happened

On 31 May 2023 Progress Software disclosed a critical vulnerability in MOVEit Transfer, its managed file transfer product, which was already being exploited in the wild. CVE-2023-34362 is an SQL injection in the web application reachable without authentication, allowing an attacker to read and manipulate the backing database and, in practice, to achieve code execution on the server.

The Cl0p ransomware group had been exploiting it ahead of disclosure. Rather than encrypting systems, they used it to plant a web shell — publicly tracked as LEMURLOOT — and steal the files held in each MOVEit instance. Because MFT servers hold data belonging to an organisation's customers, partners and payroll providers, the breach cascaded outward: a single compromised MOVEit deployment at a service provider exposed data for every downstream client it served. The eventual victim count ran into the thousands of organisations and tens of millions of individuals.

Timeline
Late May 2023
Exploitation begins as a zero-day. Reporting indicates roughly 130 victims compromised in the first ten days.
31 May 2023
Progress publishes the advisory and an emergency patch. CVE-2023-34362 is assigned.
June 2023
Two further SQL injection flaws in the same product — CVE-2023-35036 and CVE-2023-35708 — are found and patched.
June 2023 onward
CISA and the FBI publish joint advisories; victim disclosures continue for more than a year.

The technical root cause

The flaw was straightforward: user-controlled values reached SQL statements in the MOVEit web application without being properly separated from the query text. Progress described the issue as an SQL injection permitting unauthenticated access to the database; exploitation varied slightly by backend engine — MySQL, Microsoft SQL Server or Azure SQL — because what an attacker could do after gaining query control depended on the engine's capabilities.

Why SQL injection became remote code execution

Query control in an application's own database is rarely the end state an attacker wants. Here it allowed manipulation of the application's session and account records — enabling the attacker to forge an authenticated context and then use the product's legitimate file-handling functionality to write a web shell to disk. The database was the pivot, not the prize.

The fact that three separate SQL injection vulnerabilities were found in the same product within weeks is itself the significant finding. That pattern points to a systemic practice — string-built queries used broadly across a codebase — rather than a single careless line.

THE UNDERLYING PATTERN
// Query text and data concatenated.
// The database cannot tell which
// part the developer intended.
string sql =
  "SELECT * FROM folders WHERE id = '"
  + Request["folderId"] + "'";

cmd = new SqlCommand(sql, conn);
PARAMETERISED
// Data travels separately from the
// query text. No parsing ambiguity
// is possible.
string sql =
  "SELECT * FROM folders WHERE id = @id";

cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue(
  "@id", Request["folderId"]);

The lessons that actually transfer

FAQ

Do ORMs prevent this?

Largely, when used normally — ORMs bind parameters by default. The risk returns when developers drop to raw SQL fragments or string-build a query builder's conditions, which most ORMs permit.

Would a WAF have blocked it?

Signature-based filtering catches unsophisticated payloads and can slow mass scanning, but it is routinely bypassed and was not a reliable defence here. It is a mitigation layer, not a substitute for parameterised queries.

Related reading

Sources