Powershell Empire Cmdlets Executed in Command Line
Id | ef88eb96-861c-43a0-ab16-f3835a97c928 |
Rulename | Powershell Empire Cmdlets Executed in Command Line |
Description | This query identifies use of PowerShell Empire’s cmdlets within the command line data of the PowerShell process, indicating potential use of the post-exploitation tool. |
Severity | Medium |
Tactics | Collection CommandAndControl CredentialAccess DefenseEvasion Discovery Execution Exfiltration LateralMovement Persistence PrivilegeEscalation |
Techniques | T1548.002 T1134 T1134.002 T1134.005 T1087.001 T1087.002 T1557.001 T1071.001 T1560 T1547.001 T1547.005 T1547.009 T1217 T1115 T1059 T1059.001 T1059.003 T1136.001 T1136.002 T1543.003 T1555.003 T1484.001 T1482 T1114.001 T1573.002 T1546.008 T1041 T1567.001 T1567.002 T1068 T1210 T1083 T1615 T1574.001 T1574.004 T1574.007 T1574.008 T1574.009 T1070.006 T1105 T1056.001 T1056.004 T1106 T1046 T1135 T1040 T1027 T1003.001 T1057 T1055 T1021.003 T1021.004 T1053.005 T1113 T1518.001 T1558.002 T1558.003 T1082 T1016 T1049 T1569.002 T1127.001 T1552.001 T1552.004 T1550.002 T1125 T1102.002 T1047 |
Required data connectors | SecurityEvents WindowsForwardedEvents WindowsSecurityEvents |
Kind | Scheduled |
Query frequency | 12h |
Query period | 12h |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Attacker Tools Threat Protection Essentials/Analytic Rules/powershell_empire.yaml |
Version | 1.3.1 |
Arm template | ef88eb96-861c-43a0-ab16-f3835a97c928.json |
let regexEmpire = tostring(toscalar(externaldata(cmdlets:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/EmpireCommandString.txt"] with (format="txt")));
(union isfuzzy=true
(SecurityEvent
| where EventID == 4688
//consider filtering on filename if perf issues occur
//where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
| where CommandLine has "-encodedCommand"
| parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
| extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
// Note: currently the base64_decode_tostring function is limited to supporting UTF8
| extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) - (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
| where EfectiveCommand matches regex regexEmpire
| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
),
(WindowsEvent
| where EventID == 4688
| where EventData has_any ("-encodedCommand", "powershell.exe","powershell_ise.exe","pwsh.exe")
| where not(EventData has_any ('gc_worker.exe', 'gc_service.exe'))
//consider filtering on filename if perf issues occur
//extend NewProcessName = tostring(EventData.NewProcessName)
//extend Process=tostring(split(NewProcessName, '\\')[-1])
//FileName = Process
//where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
| extend ParentProcessName = tostring(EventData.ParentProcessName)
| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
| extend CommandLine = tostring(EventData.CommandLine)
| where CommandLine has "-encodedCommand"
| parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
| extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
// Note: currently the base64_decode_tostring function is limited to supporting UTF8
| extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) - (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
| where EfectiveCommand matches regex regexEmpire
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
| extend NewProcessName = tostring(EventData.NewProcessName)
| extend Process=tostring(split(NewProcessName, '\\')[-1])
| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
))
version: 1.3.1
severity: Medium
queryFrequency: 12h
triggerOperator: gt
relevantTechniques:
- T1548.002
- T1134
- T1134.002
- T1134.005
- T1087.001
- T1087.002
- T1557.001
- T1071.001
- T1560
- T1547.001
- T1547.005
- T1547.009
- T1217
- T1115
- T1059
- T1059.001
- T1059.003
- T1136.001
- T1136.002
- T1543.003
- T1555.003
- T1484.001
- T1482
- T1114.001
- T1573.002
- T1546.008
- T1041
- T1567.001
- T1567.002
- T1068
- T1210
- T1083
- T1615
- T1574.001
- T1574.004
- T1574.007
- T1574.008
- T1574.009
- T1070.006
- T1105
- T1056.001
- T1056.004
- T1106
- T1046
- T1135
- T1040
- T1027
- T1003.001
- T1057
- T1055
- T1021.003
- T1021.004
- T1053.005
- T1113
- T1518.001
- T1558.002
- T1558.003
- T1082
- T1016
- T1049
- T1569.002
- T1127.001
- T1552.001
- T1552.004
- T1550.002
- T1125
- T1102.002
- T1047
status: Available
kind: Scheduled
triggerThreshold: 0
query: |
let regexEmpire = tostring(toscalar(externaldata(cmdlets:string)[@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/EmpireCommandString.txt"] with (format="txt")));
(union isfuzzy=true
(SecurityEvent
| where EventID == 4688
//consider filtering on filename if perf issues occur
//where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
| where CommandLine has "-encodedCommand"
| parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
| extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
// Note: currently the base64_decode_tostring function is limited to supporting UTF8
| extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) - (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
| where EfectiveCommand matches regex regexEmpire
| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
),
(WindowsEvent
| where EventID == 4688
| where EventData has_any ("-encodedCommand", "powershell.exe","powershell_ise.exe","pwsh.exe")
| where not(EventData has_any ('gc_worker.exe', 'gc_service.exe'))
//consider filtering on filename if perf issues occur
//extend NewProcessName = tostring(EventData.NewProcessName)
//extend Process=tostring(split(NewProcessName, '\\')[-1])
//FileName = Process
//where FileName in~ ("powershell.exe","powershell_ise.exe","pwsh.exe")
| extend ParentProcessName = tostring(EventData.ParentProcessName)
| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))
| extend CommandLine = tostring(EventData.CommandLine)
| where CommandLine has "-encodedCommand"
| parse kind=regex flags=i CommandLine with * "-EncodedCommand " encodedCommand
| extend encodedCommand = iff(encodedCommand has " ", tostring(split(encodedCommand, " ")[0]), encodedCommand)
// Note: currently the base64_decode_tostring function is limited to supporting UTF8
| extend decodedCommand = translate('\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) - (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)
| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)
| where EfectiveCommand matches regex regexEmpire
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
| extend NewProcessName = tostring(EventData.NewProcessName)
| extend Process=tostring(split(NewProcessName, '\\')[-1])
| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName
| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')
))
entityMappings:
- fieldMappings:
- columnName: SubjectUserName
identifier: Name
- columnName: SubjectDomainName
identifier: NTDomain
entityType: Account
- fieldMappings:
- columnName: HostName
identifier: HostName
- columnName: DnsDomain
identifier: DnsDomain
entityType: Host
name: Powershell Empire Cmdlets Executed in Command Line
queryPeriod: 12h
description: |
'This query identifies use of PowerShell Empire's cmdlets within the command line data of the PowerShell process, indicating potential use of the post-exploitation tool.'
requiredDataConnectors:
- dataTypes:
- SecurityEvent
connectorId: SecurityEvents
- dataTypes:
- SecurityEvent
connectorId: WindowsSecurityEvents
- dataTypes:
- SecurityEvents
connectorId: WindowsSecurityEvents
- dataTypes:
- WindowsEvent
connectorId: WindowsForwardedEvents
id: ef88eb96-861c-43a0-ab16-f3835a97c928
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Attacker Tools Threat Protection Essentials/Analytic Rules/powershell_empire.yaml
tactics:
- Collection
- CommandAndControl
- CredentialAccess
- DefenseEvasion
- Discovery
- Execution
- Exfiltration
- LateralMovement
- Persistence
- PrivilegeEscalation
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/ef88eb96-861c-43a0-ab16-f3835a97c928')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/ef88eb96-861c-43a0-ab16-f3835a97c928')]",
"properties": {
"alertRuleTemplateName": "ef88eb96-861c-43a0-ab16-f3835a97c928",
"customDetails": null,
"description": "'This query identifies use of PowerShell Empire's cmdlets within the command line data of the PowerShell process, indicating potential use of the post-exploitation tool.'\n",
"displayName": "Powershell Empire Cmdlets Executed in Command Line",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "SubjectUserName",
"identifier": "Name"
},
{
"columnName": "SubjectDomainName",
"identifier": "NTDomain"
}
]
},
{
"entityType": "Host",
"fieldMappings": [
{
"columnName": "HostName",
"identifier": "HostName"
},
{
"columnName": "DnsDomain",
"identifier": "DnsDomain"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Attacker Tools Threat Protection Essentials/Analytic Rules/powershell_empire.yaml",
"query": "let regexEmpire = tostring(toscalar(externaldata(cmdlets:string)[@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/EmpireCommandString.txt\"] with (format=\"txt\")));\n(union isfuzzy=true\n (SecurityEvent\n| where EventID == 4688\n//consider filtering on filename if perf issues occur\n//where FileName in~ (\"powershell.exe\",\"powershell_ise.exe\",\"pwsh.exe\")\n| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))\n| where CommandLine has \"-encodedCommand\"\n| parse kind=regex flags=i CommandLine with * \"-EncodedCommand \" encodedCommand\n| extend encodedCommand = iff(encodedCommand has \" \", tostring(split(encodedCommand, \" \")[0]), encodedCommand)\n// Note: currently the base64_decode_tostring function is limited to supporting UTF8\n| extend decodedCommand = translate('\\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) - (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)\n| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)\n| where EfectiveCommand matches regex regexEmpire\n| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName\n| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')\n),\n(WindowsEvent\n| where EventID == 4688\n| where EventData has_any (\"-encodedCommand\", \"powershell.exe\",\"powershell_ise.exe\",\"pwsh.exe\")\n| where not(EventData has_any ('gc_worker.exe', 'gc_service.exe'))\n//consider filtering on filename if perf issues occur\n//extend NewProcessName = tostring(EventData.NewProcessName)\n//extend Process=tostring(split(NewProcessName, '\\\\')[-1])\n//FileName = Process\n//where FileName in~ (\"powershell.exe\",\"powershell_ise.exe\",\"pwsh.exe\")\n| extend ParentProcessName = tostring(EventData.ParentProcessName)\n| where not(ParentProcessName has_any ('gc_worker.exe', 'gc_service.exe'))\n| extend CommandLine = tostring(EventData.CommandLine)\n| where CommandLine has \"-encodedCommand\"\n| parse kind=regex flags=i CommandLine with * \"-EncodedCommand \" encodedCommand\n| extend encodedCommand = iff(encodedCommand has \" \", tostring(split(encodedCommand, \" \")[0]), encodedCommand)\n// Note: currently the base64_decode_tostring function is limited to supporting UTF8\n| extend decodedCommand = translate('\\0','', base64_decode_tostring(substring(encodedCommand, 0, strlen(encodedCommand) - (strlen(encodedCommand) %8)))), encodedCommand, CommandLine , strlen(encodedCommand)\n| extend EfectiveCommand = iff(isnotempty(encodedCommand), decodedCommand, CommandLine)\n| where EfectiveCommand matches regex regexEmpire\n| extend SubjectUserName = tostring(EventData.SubjectUserName)\n| extend SubjectDomainName = tostring(EventData.SubjectDomainName)\n| extend NewProcessName = tostring(EventData.NewProcessName)\n| extend Process=tostring(split(NewProcessName, '\\\\')[-1])\n| project timestamp = TimeGenerated, Computer, SubjectUserName, SubjectDomainName, FileName = Process, EfectiveCommand, decodedCommand, encodedCommand, CommandLine, ParentProcessName\n| extend HostName = split(Computer, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')\n))\n",
"queryFrequency": "PT12H",
"queryPeriod": "PT12H",
"severity": "Medium",
"status": "Available",
"subTechniques": [
"T1548.002",
"T1134.002",
"T1134.005",
"T1087.001",
"T1087.002",
"T1557.001",
"T1071.001",
"T1547.001",
"T1547.005",
"T1547.009",
"T1059.001",
"T1059.003",
"T1136.001",
"T1136.002",
"T1543.003",
"T1555.003",
"T1484.001",
"T1114.001",
"T1573.002",
"T1546.008",
"T1567.001",
"T1567.002",
"T1574.001",
"T1574.004",
"T1574.007",
"T1574.008",
"T1574.009",
"T1070.006",
"T1056.001",
"T1056.004",
"T1003.001",
"T1021.003",
"T1021.004",
"T1053.005",
"T1518.001",
"T1558.002",
"T1558.003",
"T1569.002",
"T1127.001",
"T1552.001",
"T1552.004",
"T1550.002",
"T1102.002"
],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Collection",
"CommandAndControl",
"CredentialAccess",
"DefenseEvasion",
"Discovery",
"Execution",
"Exfiltration",
"LateralMovement",
"Persistence",
"PrivilegeEscalation"
],
"techniques": [
"T1003",
"T1016",
"T1021",
"T1027",
"T1040",
"T1041",
"T1046",
"T1047",
"T1049",
"T1053",
"T1055",
"T1056",
"T1057",
"T1059",
"T1068",
"T1070",
"T1071",
"T1082",
"T1083",
"T1087",
"T1102",
"T1105",
"T1106",
"T1113",
"T1114",
"T1115",
"T1125",
"T1127",
"T1134",
"T1135",
"T1136",
"T1210",
"T1217",
"T1482",
"T1484",
"T1518",
"T1543",
"T1546",
"T1547",
"T1548",
"T1550",
"T1552",
"T1555",
"T1557",
"T1558",
"T1560",
"T1567",
"T1569",
"T1573",
"T1574",
"T1615"
],
"templateVersion": "1.3.1",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}