id: 041b9e86-07b8-584e-9e39-731fe3660f9e name: PHP2Shell - Startup memory fatal then shell description: | 'On the same server, a PHP startup memory fatal (rule 01) was followed within 30 minutes by the web server starting a shell or tool (rule 03): an exploit attempt that worked. Matches hosts on their short name.' severity: High requiredDataConnectors: - connectorId: SyslogAma dataTypes: - Syslog - connectorId: MicrosoftThreatProtection dataTypes: - DeviceProcessEvents queryFrequency: 30m queryPeriod: 1h triggerOperator: gt triggerThreshold: 0 tactics: - InitialAccess - Execution relevantTechniques: - T1190 - T1059.004 query: | // PHP2Shell, attempt then execution: the error-log signal and a web server shell on the same host within 30 minutes. // Syslog and Defender name hosts differently, so both sides are matched on the short host name. let Window = 30m; 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"]); let Signals = Syslog | where SyslogMessage has "Allowed memory size" and SyslogMessage contains "in Unknown on line 0" | extend Host = tolower(tostring(split(Computer, ".")[0])) | summarize SignalTime = min(TimeGenerated), Signals = count() by Host; DeviceProcessEvents | where InitiatingProcessFileName matches regex WebServer | where FileName in~ (Tools) | extend Host = tolower(tostring(split(DeviceName, ".")[0])) | join kind=inner Signals on Host | where TimeGenerated between (SignalTime .. (SignalTime + Window)) | summarize StartTime = min(SignalTime), EndTime = max(TimeGenerated), Signals = max(Signals), Commands = make_set(ProcessCommandLine, 10) by DeviceName, AccountName | 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