id: 046199a4-b983-57ac-8e4d-3c78e139a8bf name: PHP2Shell - Web server starts a shell or tool description: | 'A PHP worker or web server process started a shell, a download tool or a reconnaissance command. After PHP2Shell exploitation the attacker runs commands as the web server account. Tune KnownGood for tools your applications call.' severity: High requiredDataConnectors: - connectorId: MicrosoftThreatProtection dataTypes: - DeviceProcessEvents queryFrequency: 15m queryPeriod: 15m triggerOperator: gt triggerThreshold: 0 tactics: - Execution - Persistence relevantTechniques: - T1059.004 - T1059.001 - T1505.003 query: | // PHP2Shell post-exploitation: commands run by the PHP worker or web server (Linux and PHP on Windows). let WebServer = @"(?i)^(php(-fpm|-cgi)?[0-9.]*(\.exe)?|apache2|httpd(\.exe)?|lsphp|frankenphp)$"; let Tools = dynamic(["sh", "bash", "dash", "zsh", "busybox", "curl", "wget", "python", "python3", "perl", "ruby", "nc", "ncat", "netcat", "socat", "base64", "whoami", "id", "uname", "cmd.exe", "powershell.exe", "pwsh.exe", "certutil.exe", "whoami.exe"]); // Add command lines your applications legitimately run (a mail or image tool, for example) after review. let KnownGood = dynamic(["REPLACE_WITH_EXPECTED_COMMAND_LINE"]); DeviceProcessEvents | where InitiatingProcessFileName matches regex WebServer | where FileName in~ (Tools) | where not(ProcessCommandLine has_any (KnownGood)) | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), Runs = count(), Commands = make_set(ProcessCommandLine, 20) by DeviceName, AccountName, InitiatingProcessFileName, FileName | extend CommandLine = tostring(Commands[0]) entityMappings: - entityType: Host fieldMappings: - identifier: FullName columnName: DeviceName - entityType: Account fieldMappings: - identifier: Name columnName: AccountName - entityType: Process fieldMappings: - identifier: CommandLine columnName: CommandLine eventGroupingSettings: aggregationKind: AlertPerResult version: 1.0.0 kind: Scheduled