Exchange SSRF Autodiscover ProxyShell - Detection
Id | 968358d6-6af8-49bb-aaa4-187b3067fb95 |
Rulename | Exchange SSRF Autodiscover ProxyShell - Detection |
Description | This query looks for suspicious request patterns to Exchange servers that fit patterns recently blogged about by PeterJson. This exploitation chain utilises an SSRF vulnerability in Exchange which eventually allows the attacker to execute arbitrary Powershell on the server. In the example powershell can be used to write an email to disk with an encoded attachment containing a shell. Reference: https://peterjson.medium.com/reproducing-the-proxyshell-pwn2own-exploit-49743a4ea9a1 |
Severity | High |
Tactics | InitialAccess |
Techniques | T1190 |
Required data connectors | AzureMonitor(IIS) |
Kind | Scheduled |
Query frequency | 12h |
Query period | 12h |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Detections/W3CIISLog/ProxyShellPwn2Own.yaml |
Version | 1.0.3 |
Arm template | 968358d6-6af8-49bb-aaa4-187b3067fb95.json |
let successCodes = dynamic([200, 302, 401]);
W3CIISLog
| where scStatus has_any (successCodes)
| where ipv4_is_private(cIP) == False
| where csUriStem hasprefix "/autodiscover/autodiscover.json"
| project TimeGenerated, cIP, sIP, sSiteName, csUriStem, csUriQuery, Computer, csUserName, _ResourceId, FileUri
| where (csUriQuery !has "Protocol" and isnotempty(csUriQuery))
or (csUriQuery has_any("/mapi/", "powershell"))
or (csUriQuery contains "@" and csUriQuery matches regex @"\.[a-zA-Z]{2,4}?(?:[a-zA-Z]{2,4}\/)")
or (csUriQuery contains ":" and csUriQuery matches regex @"\:[0-9]{2,4}\/")
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(csUserName, "@")[0]), AccountUPNSuffix = tostring(split(csUserName, "@")[1])
relevantTechniques:
- T1190
name: Exchange SSRF Autodiscover ProxyShell - Detection
requiredDataConnectors:
- dataTypes:
- W3CIISLog
connectorId: AzureMonitor(IIS)
entityMappings:
- fieldMappings:
- identifier: FullName
columnName: csUserName
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
entityType: Account
- fieldMappings:
- identifier: FullName
columnName: Computer
entityType: Host
- fieldMappings:
- identifier: Address
columnName: cIP
entityType: IP
- fieldMappings:
- identifier: ResourceId
columnName: _ResourceId
entityType: AzureResource
triggerThreshold: 0
id: 968358d6-6af8-49bb-aaa4-187b3067fb95
tactics:
- InitialAccess
version: 1.0.3
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/W3CIISLog/ProxyShellPwn2Own.yaml
queryPeriod: 12h
kind: Scheduled
metadata:
categories:
domains:
- Security - Others
author:
name: Thomas McElroy
support:
tier: Community
source:
kind: Community
queryFrequency: 12h
severity: High
description: |
'This query looks for suspicious request patterns to Exchange servers that fit patterns recently blogged about by PeterJson. This exploitation chain utilises an SSRF vulnerability in Exchange which eventually allows the attacker to execute arbitrary Powershell on the server.
In the example powershell can be used to write an email to disk with an encoded attachment containing a shell.
Reference: https://peterjson.medium.com/reproducing-the-proxyshell-pwn2own-exploit-49743a4ea9a1'
query: |
let successCodes = dynamic([200, 302, 401]);
W3CIISLog
| where scStatus has_any (successCodes)
| where ipv4_is_private(cIP) == False
| where csUriStem hasprefix "/autodiscover/autodiscover.json"
| project TimeGenerated, cIP, sIP, sSiteName, csUriStem, csUriQuery, Computer, csUserName, _ResourceId, FileUri
| where (csUriQuery !has "Protocol" and isnotempty(csUriQuery))
or (csUriQuery has_any("/mapi/", "powershell"))
or (csUriQuery contains "@" and csUriQuery matches regex @"\.[a-zA-Z]{2,4}?(?:[a-zA-Z]{2,4}\/)")
or (csUriQuery contains ":" and csUriQuery matches regex @"\:[0-9]{2,4}\/")
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(csUserName, "@")[0]), AccountUPNSuffix = tostring(split(csUserName, "@")[1])
triggerOperator: gt
{
"$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/968358d6-6af8-49bb-aaa4-187b3067fb95')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/968358d6-6af8-49bb-aaa4-187b3067fb95')]",
"properties": {
"alertRuleTemplateName": "968358d6-6af8-49bb-aaa4-187b3067fb95",
"customDetails": null,
"description": "'This query looks for suspicious request patterns to Exchange servers that fit patterns recently blogged about by PeterJson. This exploitation chain utilises an SSRF vulnerability in Exchange which eventually allows the attacker to execute arbitrary Powershell on the server.\nIn the example powershell can be used to write an email to disk with an encoded attachment containing a shell.\nReference: https://peterjson.medium.com/reproducing-the-proxyshell-pwn2own-exploit-49743a4ea9a1'\n",
"displayName": "Exchange SSRF Autodiscover ProxyShell - Detection",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "csUserName",
"identifier": "FullName"
},
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "AccountUPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "Host",
"fieldMappings": [
{
"columnName": "Computer",
"identifier": "FullName"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "cIP",
"identifier": "Address"
}
]
},
{
"entityType": "AzureResource",
"fieldMappings": [
{
"columnName": "_ResourceId",
"identifier": "ResourceId"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/W3CIISLog/ProxyShellPwn2Own.yaml",
"query": "let successCodes = dynamic([200, 302, 401]);\nW3CIISLog\n| where scStatus has_any (successCodes)\n| where ipv4_is_private(cIP) == False\n| where csUriStem hasprefix \"/autodiscover/autodiscover.json\"\n| project TimeGenerated, cIP, sIP, sSiteName, csUriStem, csUriQuery, Computer, csUserName, _ResourceId, FileUri\n| where (csUriQuery !has \"Protocol\" and isnotempty(csUriQuery))\nor (csUriQuery has_any(\"/mapi/\", \"powershell\"))\nor (csUriQuery contains \"@\" and csUriQuery matches regex @\"\\.[a-zA-Z]{2,4}?(?:[a-zA-Z]{2,4}\\/)\")\nor (csUriQuery contains \":\" and csUriQuery matches regex @\"\\:[0-9]{2,4}\\/\")\n| extend HostName = tostring(split(Computer, \".\")[0]), DomainIndex = toint(indexof(Computer, '.'))\n| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)\n| extend AccountName = tostring(split(csUserName, \"@\")[0]), AccountUPNSuffix = tostring(split(csUserName, \"@\")[1])\n",
"queryFrequency": "PT12H",
"queryPeriod": "PT12H",
"severity": "High",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"InitialAccess"
],
"techniques": [
"T1190"
],
"templateVersion": "1.0.3",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}