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])
name: Exchange SSRF Autodiscover ProxyShell - Detection
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'
version: 1.0.3
requiredDataConnectors:
- dataTypes:
- W3CIISLog
connectorId: AzureMonitor(IIS)
relevantTechniques:
- T1190
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: csUserName
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- entityType: IP
fieldMappings:
- identifier: Address
columnName: cIP
- entityType: AzureResource
fieldMappings:
- identifier: ResourceId
columnName: _ResourceId
triggerThreshold: 0
tactics:
- InitialAccess
queryPeriod: 12h
metadata:
categories:
domains:
- Security - Others
support:
tier: Community
author:
name: Thomas McElroy
source:
kind: Community
kind: Scheduled
triggerOperator: gt
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])
queryFrequency: 12h
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/W3CIISLog/ProxyShellPwn2Own.yaml
id: 968358d6-6af8-49bb-aaa4-187b3067fb95