id: 451d8a12-b30b-578f-aa74-3255c881ef46 name: PHP2Shell - Web server writes PHP or ini files description: | 'A PHP worker or web server, or a process it started, created or changed a PHP script, .user.ini, .htaccess or php.ini. This is how web shells and auto_prepend_file persistence are planted. CMS updates write many files at once; review those.' severity: Medium requiredDataConnectors: - connectorId: MicrosoftThreatProtection dataTypes: - DeviceFileEvents queryFrequency: 30m queryPeriod: 30m triggerOperator: gt triggerThreshold: 0 tactics: - Persistence relevantTechniques: - T1505.003 query: | // PHP2Shell persistence: web shells and auto_prepend_file settings written by the web server or its children. // A CMS update run from the browser also writes PHP files: a large Files count in one burst is usually an update. let WebServer = @"(?i)^(php(-fpm|-cgi)?[0-9.]*(\.exe)?|apache2|httpd(\.exe)?|lsphp|frankenphp)$"; let ScriptExtensions = dynamic([".php", ".phtml", ".phar", ".php5", ".php7", ".pht", ".inc"]); DeviceFileEvents | where ActionType in ("FileCreated", "FileModified", "FileRenamed") | where InitiatingProcessFileName matches regex WebServer or InitiatingProcessParentFileName matches regex WebServer | extend Extension = tolower(extract(@"(\.[A-Za-z0-9]+)$", 1, FileName)) | where Extension in (ScriptExtensions) or FileName in~ (".user.ini", ".htaccess", "php.ini") | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), Files = dcount(FileName), Names = make_set(FileName, 20), Folders = make_set(FolderPath, 10) by DeviceName, InitiatingProcessAccountName, InitiatingProcessFileName | extend FileName = tostring(Names[0]), FolderPath = tostring(Folders[0]) entityMappings: - entityType: Host fieldMappings: - identifier: FullName columnName: DeviceName - entityType: Account fieldMappings: - identifier: Name columnName: InitiatingProcessAccountName - entityType: File fieldMappings: - identifier: Name columnName: FileName - identifier: Directory columnName: FolderPath eventGroupingSettings: aggregationKind: AlertPerResult version: 1.0.0 kind: Scheduled