Detecting an Azure sign in utilizing stolen tokens - ToddMaxey/Technical-Documentation GitHub Wiki
Detecting token replay attacks in Azure user sign-ins can be a challenging task because the attacker uses a valid token to gain unauthorized access. However, you can look for specific patterns or anomalies in the user's sign-in logs that might indicate a token replay attack. Some of these markers include:
Unusual sign-in locations: If a user is signing in from a location that is not typical for them, it could indicate a token replay attack. You can set up risk-based policies in Azure Active Directory to detect and block sign-ins from unfamiliar locations.
Sign-ins from multiple locations: If a user's sign-in logs show simultaneous or near-simultaneous sign-ins from different geographic locations, it could be a sign of a token replay attack.
Unusual sign-in times: If a user is signing in at an unusual time, such as outside of their regular working hours or during a known vacation period, it could be an indicator of a token replay attack.
Suspicious IP addresses: If a user sign-in originates from an IP address associated with malicious activities or known to be used by attackers, it could be an indication of a token replay attack. Azure Active Directory provides an option to create Named Locations to flag sign-ins from suspicious IPs.
Multiple failed sign-in attempts: If there are multiple failed sign-in attempts before a successful sign-in, it could indicate an attacker attempting to use a stolen token.
Unusual user agent: If a user sign-in log shows an unusual or unfamiliar user agent, it could indicate an attacker using a different device or browser for the token replay attack.
To analyze Azure AD user sign-ins for these markers, you can use Azure Active Directory's built-in features such as sign-in logs, Azure AD Identity Protection, and Conditional Access policies. Additionally, you can integrate Azure AD logs with Azure Sentinel or other Security Information and Event Management (SIEM) solutions for advanced analysis and threat detection.
Remember that detecting token replay attacks is not foolproof, and no single marker can definitively prove an attack. It's essential to monitor and analyze sign-in logs regularly, correlate different markers, and investigate any suspicious activities.
Here are KQL queries for each of the six markers related to token replay attacks. These queries assume you have Azure AD logs integrated with Azure Log Analytics.
Prerequisite:
- Authentication Methods:
//Authentication Details recommend adding user or appdisplay
SigninLogs
| where ResultType == 0
// | where UserPrincipalName == "user"
// | where AppDisplayName == "Azure Portal"
| mv-expand todynamic(AuthenticationDetails)
| extend AuthenticationStepRequirement = AuthenticationDetails.authenticationStepRequirement
| extend authenticationMethod = AuthenticationDetails.authenticationMethod
| extend authenticationStepResultDetail = AuthenticationDetails.authenticationStepResultDetail
| project TimeGenerated,ResourceDisplayName,AppDisplayName,UserPrincipalName,UserType,authenticationMethod,AuthenticationStepRequirement,authenticationStepResultDetail
- Unusual sign-in locations:
SigninLogs
| where TimeGenerated between (datetime() ..datetime() ) //use to narrow results
| where ResultType == 0
|extend Country = tostring(LocationDetails.countryOrRegion)
|extend State = tostring(LocationDetails.state)
| summarize count() by UserPrincipalName, Country,State,IPAddress
| order by UserPrincipalName, count_ desc
- Sign-ins from multiple locations:
No time aggregates
SigninLogs
//| where TimeGenerated between (datetime() ..datetime() ) //use to narrow results
| where ResultType == 0
|extend Country = tostring(LocationDetails.countryOrRegion)
|extend State = tostring(LocationDetails.state)
| summarize Locations = dcount(State) by UserPrincipalName,Country,State
Time aggregates per week
//Query result interpretation:
// time(0.00:00:00), indicating Sunday
// time(1.00:00:00), indicating Monday and so on
//This query is recommended to use within a week timeframe
SigninLogs
//| where TimeGenerated between (datetime(2023-05-01) ..now()) //use to narrow results
| where ResultType == 0
|extend Country = tostring(LocationDetails.countryOrRegion)
|extend State = tostring(LocationDetails.state)
| extend DayOfLogon = dayofweek(TimeGenerated)
| summarize Locations = dcount(State) by UserPrincipalName,Country,State,DayOfLogon
- Unusual sign-in times:
SigninLogs
| where ResultType == 0
| extend HourOfDay = datetime_part("hour", TimeGenerated)
| summarize count() by UserPrincipalName, HourOfDay,UserAgent
| order by UserPrincipalName, HourOfDay
- Suspicious IP addresses:
let SuspiciousIPs = dynamic(["1.2.3.4", "2.3.4.5"]); // Replace with a list of suspicious IPs
SigninLogs
| where ResultType == 0 and IPAddress in (SuspiciousIPs)
| summarize count() by UserPrincipalName, IPAddress
| order by UserPrincipalName, count_ desc
- Multiple failed sign-in attempts:
SigninLogs
| where ResultType != 0
| summarize FailedAttempts = count() by UserPrincipalName, bin(TimeGenerated, 1h)
| where FailedAttempts > 5 // Replace '5' with a threshold that fits your environment
| order by UserPrincipalName, TimeGenerated
- Unusual user agent:
Known suspicious user agent. The string value Detecting token replay attacks in Azure user sign-ins can be a challenging task because the attacker uses a valid token to gain unauthorized access. However, you can look for specific patterns or anomalies in the user's sign-in logs that might indicate a token replay attack. Some of these markers include:
Unusual sign-in locations: If a user is signing in from a location that is not typical for them, it could indicate a token replay attack. You can set up risk-based policies in Azure Active Directory to detect and block sign-ins from unfamiliar locations.
Sign-ins from multiple locations: If a user's sign-in logs show simultaneous or near-simultaneous sign-ins from different geographic locations, it could be a sign of a token replay attack.
Unusual sign-in times: If a user is signing in at an unusual time, such as outside of their regular working hours or during a known vacation period, it could be an indicator of a token replay attack.
Suspicious IP addresses: If a user sign-in originates from an IP address associated with malicious activities or known to be used by attackers, it could be an indication of a token replay attack. Azure Active Directory provides an option to create Named Locations to flag sign-ins from suspicious IPs.
Multiple failed sign-in attempts: If there are multiple failed sign-in attempts before a successful sign-in, it could indicate an attacker attempting to use a stolen token.
Unusual user agent: If a user sign-in log shows an unusual or unfamiliar user agent, it could indicate an attacker using a different device or browser for the token replay attack.
To analyze Azure AD user sign-ins for these markers, you can use Azure Active Directory's built-in features such as sign-in logs, Azure AD Identity Protection, and Conditional Access policies. Additionally, you can integrate Azure AD logs with Azure Sentinel or other Security Information and Event Management (SIEM) solutions for advanced analysis and threat detection.
Remember that detecting token replay attacks is not foolproof, and no single marker can definitively prove an attack. It's essential to monitor and analyze sign-in logs regularly, correlate different markers, and investigate any suspicious activities.
Here are KQL queries for each of the six markers related to token replay attacks. These queries assume you have Azure AD logs integrated with Azure Log Analytics.
Prerequisite:
- Authentication Methods:
//Authentication Details recommend adding user or appdisplay
SigninLogs
| where ResultType == 0
// | where UserPrincipalName == "user"
// | where AppDisplayName == "Azure Portal"
| mv-expand todynamic(AuthenticationDetails)
| extend AuthenticationStepRequirement = AuthenticationDetails.authenticationStepRequirement
| extend authenticationMethod = AuthenticationDetails.authenticationMethod
| extend authenticationStepResultDetail = AuthenticationDetails.authenticationStepResultDetail
| project TimeGenerated,ResourceDisplayName,AppDisplayName,UserPrincipalName,UserType,authenticationMethod,AuthenticationStepRequirement,authenticationStepResultDetail
- Unusual sign-in locations:
SigninLogs
| where TimeGenerated between (datetime() ..datetime() ) //use to narrow results
| where ResultType == 0
|extend Country = tostring(LocationDetails.countryOrRegion)
|extend State = tostring(LocationDetails.state)
| summarize count() by UserPrincipalName, Country,State,IPAddress
| order by UserPrincipalName, count_ desc
- Sign-ins from multiple locations:
No time aggregates
SigninLogs
//| where TimeGenerated between (datetime() ..datetime() ) //use to narrow results
| where ResultType == 0
|extend Country = tostring(LocationDetails.countryOrRegion)
|extend State = tostring(LocationDetails.state)
| summarize Locations = dcount(State) by UserPrincipalName,Country,State
Time aggregates per week
//Query result interpretation:
// time(0.00:00:00), indicating Sunday
// time(1.00:00:00), indicating Monday and so on
//This query is recommended to use within a week timeframe
SigninLogs
//| where TimeGenerated between (datetime(2023-05-01) ..now()) //use to narrow results
| where ResultType == 0
|extend Country = tostring(LocationDetails.countryOrRegion)
|extend State = tostring(LocationDetails.state)
| extend DayOfLogon = dayofweek(TimeGenerated)
| summarize Locations = dcount(State) by UserPrincipalName,Country,State,DayOfLogon
- Unusual sign-in times:
SigninLogs
| where ResultType == 0
| extend HourOfDay = datetime_part("hour", TimeGenerated)
| summarize count() by UserPrincipalName, HourOfDay,UserAgent
| order by UserPrincipalName, HourOfDay
- Suspicious IP addresses:
let SuspiciousIPs = dynamic(["1.2.3.4", "2.3.4.5"]); // Replace with a list of suspicious IPs
SigninLogs
| where ResultType == 0 and IPAddress in (SuspiciousIPs)
| summarize count() by UserPrincipalName, IPAddress
| order by UserPrincipalName, count_ desc
- Multiple failed sign-in attempts:
SigninLogs
| where ResultType != 0
| summarize FailedAttempts = count() by UserPrincipalName, bin(TimeGenerated, 1h)
| where FailedAttempts > 5 // Replace '5' with a threshold that fits your environment
| order by UserPrincipalName, TimeGenerated
- Unusual user agent:
Known suspicious user agent. The string value useragent has the 3 value of operation system, browser and client app. Add as needed
SigninLogs
| where ResultType == 0
| where UserAgent has_any("Ubuntu", "Linux", "python", "bash")
| summarize count() by UserPrincipalName, UserAgent
| order by UserPrincipalName, count_ desc
- Suspicious Resource access:
//Suspicious Resource
let ResourceName = dynamic(["Microsoft Graph","Windows Azure Active Directory"]);
SigninLogs
| where ResultType == 0
| where ResourceDisplayName in (ResourceName)
| summarize count() by ResourceDisplayName,AppDisplayName,UserPrincipalName,UserType
9.Suspicious Application
//Suspicious Application
let AppDisplayname = dynamic(["ADIbizaUX","Microsoft Azure CLI"]);
SigninLogs
| where ResultType == 0
| where AppDisplayName in (AppDisplayname )
| summarize count() by ResourceDisplayName,AppDisplayName
- Suspicious member access
SigninLogs
| where UserType == "Guest"
| mv-expand todynamic(AuthenticationDetails)
| extend AuthenticationStepRequirement = AuthenticationDetails.authenticationStepRequirement
| extend authenticationMethod = AuthenticationDetails.authenticationMethod
| project TimeGenerated,ResourceDisplayName,AppDisplayName,UserPrincipalName,UserType,authenticationMethod,AuthenticationStepRequirement
These queries provide data, filtering, and formatting for each marker to help you analyze potential token replay attacks. However, keep in mind that these queries might require adjustments depending on your organization's specific environment, thresholds, and requirements. To run these queries, go to the Azure Portal, navigate to the Log Analytics workspace connected with your Azure AD logs, and open the "Logs" section. Paste the query into the query editor and click "Run" to execute the query and view the results.
SigninLogs
| where ResultType == 0
| where UserAgent has_any("Ubuntu", "Linux", "python", "bash")
| summarize count() by UserPrincipalName, UserAgent
| order by UserPrincipalName, count_ desc
11. Suspicious Resource access:
```kusto
//Suspicious Resource
let ResourceName = dynamic(["Microsoft Graph","Windows Azure Active Directory"]);
SigninLogs
| where ResultType == 0
| where ResourceDisplayName in (ResourceName)
| summarize count() by ResourceDisplayName,AppDisplayName,UserPrincipalName,UserType
12.Suspicious Application
//Suspicious Application
let AppDisplayname = dynamic(["ADIbizaUX","Microsoft Azure CLI"]);
SigninLogs
| where ResultType == 0
| where AppDisplayName in (AppDisplayname )
| summarize count() by ResourceDisplayName,AppDisplayName
- Suspicious member access
SigninLogs
| where UserType == "Guest"
| mv-expand todynamic(AuthenticationDetails)
| extend AuthenticationStepRequirement = AuthenticationDetails.authenticationStepRequirement
| extend authenticationMethod = AuthenticationDetails.authenticationMethod
| project TimeGenerated,ResourceDisplayName,AppDisplayName,UserPrincipalName,UserType,authenticationMethod,AuthenticationStepRequirement
These queries provide data, filtering, and formatting for each marker to help you analyze potential token replay attacks. However, keep in mind that these queries might require adjustments depending on your organization's specific environment, thresholds, and requirements. To run these queries, go to the Azure Portal, navigate to the Log Analytics workspace connected with your Azure AD logs, and open the "Logs" section. Paste the query into the query editor and click "Run" to execute the query and view the results.