Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Detect requests for an uncommon resources on the web ASIM Web Session

Back
Idc99cf650-c53b-4c4c-9671-7d7500191a10
RulenameDetect requests for an uncommon resources on the web (ASIM Web Session)
DescriptionThis detection mechanism examines connections made to a domain where only a single file is requested,

which is considered unusual since most contemporary web applications require additional resources.

Such activity is often associated with malware beaconing or tracking URLs delivered via emails.

The query includes a sample set of popular web script extensions (scriptExtensions),

which should be customized to align with the specific requirements of your environment
SeverityLow
TacticsCommandAndControl
TechniquesT1102
T1071
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RarelyRequestedResources.yaml
Version1.0.1
Arm templatec99cf650-c53b-4c4c-9671-7d7500191a10.json
Deploy To Azure
let lookback = 1d;
let scriptExtensions = dynamic([".php", ".aspx", ".asp", ".cfml", ".py", ".sh", ".bash", ".pl"]);
//The number of URI's seen to be suspicious, higher = less likely to be suspicious
let uriThreshold = 1;
let ReqestCountThreshold = 10; // set minimum requests count to confirm repetitive connections
// Only look at connections that were allowed through the web proxy
_Im_WebSession (starttime=ago(lookback), eventresult='Success')
| project
    SrcBytes,
    DstBytes,
    Url,
    TimeGenerated,
    DstIpAddr,
    SrcIpAddr,
    HttpRequestMethod,
    HttpReferrer
| where not(ipv4_is_private(DstIpAddr)) // Only take traffic going to internet
| extend DestHostName = tostring(parse_url(Url)["Host"])
// Only look at connections where some data was exchanged.
| where SrcBytes > 0 and DstBytes > 0
// Extract Domain
| extend Domain = iif(countof(DestHostName, '.') >= 2, strcat(split(DestHostName, '.')[-2], '.', split(DestHostName, '.')[-1]), DestHostName)
| extend GetData = iff(Url contains "?", 1, 0)
| summarize
    EventStartTime = min(TimeGenerated),
    EventEndTime = max(TimeGenerated),
    make_set(Url, 100),
    make_set(DstIpAddr, 100),
    make_set(SrcIpAddr, 100),
    EventCount = count(),
    make_set(HttpRequestMethod, 10),
    max(GetData),
    max(HttpReferrer)
    by Domain
// Determine the number of URIs that have been visited for the domain
| extend destinationURICount = array_length(set_Url)
| where destinationURICount <= uriThreshold and EventCount > ReqestCountThreshold // check for repetitive requests for single resource only.
| where tostring(set_Url) has_any(scriptExtensions)
//Remove matches with referer
| where max_HttpReferrer == ""
//Keep requests where data was transferred either in a GET with parameters or a POST
| where set_HttpRequestMethod in~ ("POST") or max_GetData == 1
//Defeat email click tracking, may increase FN's while decreasing FP's
| where set_Url !has "click" and set_HttpRequestMethod !has "GET"
| mv-expand set_Url, set_DstIpAddr, set_SrcIpAddr
| extend
    RequestURL = tostring(set_Url),
    DestinationIP = tostring(set_DstIpAddr),
    SourceIP = tostring(set_SrcIpAddr)
| project
    EventStartTime,
    EventEndTime,
    SourceIP,
    DestinationIP,
    EventCount,
    RequestURL,
    set_HttpRequestMethod
id: c99cf650-c53b-4c4c-9671-7d7500191a10
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
severity: Low
customDetails:
  EventStartTime: EventStartTime
  EventCount: EventCount
  EventEndTime: EventEndTime
alertDetailsOverride:
  alertDescriptionFormat: User requested (TotalEvents='{{EventCount}}') for URL '{{RequestURL}}' which contains a known script extension. The domain associated with this URL has not been accessed by any other user. This activity could be a potential beaconing activity to maintain control over compromised systems, receive instructions, or exfiltrate data
  alertDisplayNameFormat: User with IP '{{SourceIP}}' has been observed making request for a rare resource
relevantTechniques:
- T1102
- T1071
requiredDataConnectors: []
tags:
- SchemaVersion: 0.2.6
  Schema: WebSession
- RuleReference: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Zscaler%20Internet%20Access/Analytic%20Rules/Zscaler-LowVolumeDomainRequests.yaml
entityMappings:
- fieldMappings:
  - identifier: Address
    columnName: SourceIP
  entityType: IP
- fieldMappings:
  - identifier: Address
    columnName: DestinationIP
  entityType: IP
- fieldMappings:
  - identifier: Url
    columnName: RequestURL
  entityType: URL
version: 1.0.1
query: |
  let lookback = 1d;
  let scriptExtensions = dynamic([".php", ".aspx", ".asp", ".cfml", ".py", ".sh", ".bash", ".pl"]);
  //The number of URI's seen to be suspicious, higher = less likely to be suspicious
  let uriThreshold = 1;
  let ReqestCountThreshold = 10; // set minimum requests count to confirm repetitive connections
  // Only look at connections that were allowed through the web proxy
  _Im_WebSession (starttime=ago(lookback), eventresult='Success')
  | project
      SrcBytes,
      DstBytes,
      Url,
      TimeGenerated,
      DstIpAddr,
      SrcIpAddr,
      HttpRequestMethod,
      HttpReferrer
  | where not(ipv4_is_private(DstIpAddr)) // Only take traffic going to internet
  | extend DestHostName = tostring(parse_url(Url)["Host"])
  // Only look at connections where some data was exchanged.
  | where SrcBytes > 0 and DstBytes > 0
  // Extract Domain
  | extend Domain = iif(countof(DestHostName, '.') >= 2, strcat(split(DestHostName, '.')[-2], '.', split(DestHostName, '.')[-1]), DestHostName)
  | extend GetData = iff(Url contains "?", 1, 0)
  | summarize
      EventStartTime = min(TimeGenerated),
      EventEndTime = max(TimeGenerated),
      make_set(Url, 100),
      make_set(DstIpAddr, 100),
      make_set(SrcIpAddr, 100),
      EventCount = count(),
      make_set(HttpRequestMethod, 10),
      max(GetData),
      max(HttpReferrer)
      by Domain
  // Determine the number of URIs that have been visited for the domain
  | extend destinationURICount = array_length(set_Url)
  | where destinationURICount <= uriThreshold and EventCount > ReqestCountThreshold // check for repetitive requests for single resource only.
  | where tostring(set_Url) has_any(scriptExtensions)
  //Remove matches with referer
  | where max_HttpReferrer == ""
  //Keep requests where data was transferred either in a GET with parameters or a POST
  | where set_HttpRequestMethod in~ ("POST") or max_GetData == 1
  //Defeat email click tracking, may increase FN's while decreasing FP's
  | where set_Url !has "click" and set_HttpRequestMethod !has "GET"
  | mv-expand set_Url, set_DstIpAddr, set_SrcIpAddr
  | extend
      RequestURL = tostring(set_Url),
      DestinationIP = tostring(set_DstIpAddr),
      SourceIP = tostring(set_SrcIpAddr)
  | project
      EventStartTime,
      EventEndTime,
      SourceIP,
      DestinationIP,
      EventCount,
      RequestURL,
      set_HttpRequestMethod  
queryPeriod: 1d
triggerOperator: gt
tactics:
- CommandAndControl
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RarelyRequestedResources.yaml
status: Available
description: |
  'This detection mechanism examines connections made to a domain where only a single file is requested, 
  which is considered unusual since most contemporary web applications require additional resources. 
  Such activity is often associated with malware beaconing or tracking URLs delivered via emails. 
  The query includes a sample set of popular web script extensions (scriptExtensions), 
  which should be customized to align with the specific requirements of your environment'  
name: Detect requests for an uncommon resources on the web (ASIM Web Session)
kind: Scheduled
queryFrequency: 1d
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/c99cf650-c53b-4c4c-9671-7d7500191a10')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/c99cf650-c53b-4c4c-9671-7d7500191a10')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "User requested (TotalEvents='{{EventCount}}') for URL '{{RequestURL}}' which contains a known script extension. The domain associated with this URL has not been accessed by any other user. This activity could be a potential beaconing activity to maintain control over compromised systems, receive instructions, or exfiltrate data",
          "alertDisplayNameFormat": "User with IP '{{SourceIP}}' has been observed making request for a rare resource"
        },
        "alertRuleTemplateName": "c99cf650-c53b-4c4c-9671-7d7500191a10",
        "customDetails": {
          "EventCount": "EventCount",
          "EventEndTime": "EventEndTime",
          "EventStartTime": "EventStartTime"
        },
        "description": "'This detection mechanism examines connections made to a domain where only a single file is requested, \nwhich is considered unusual since most contemporary web applications require additional resources. \nSuch activity is often associated with malware beaconing or tracking URLs delivered via emails. \nThe query includes a sample set of popular web script extensions (scriptExtensions), \nwhich should be customized to align with the specific requirements of your environment'\n",
        "displayName": "Detect requests for an uncommon resources on the web (ASIM Web Session)",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIP",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "DestinationIP",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "RequestURL",
                "identifier": "Url"
              }
            ]
          }
        ],
        "eventGroupingSettings": {
          "aggregationKind": "AlertPerResult"
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RarelyRequestedResources.yaml",
        "query": "let lookback = 1d;\nlet scriptExtensions = dynamic([\".php\", \".aspx\", \".asp\", \".cfml\", \".py\", \".sh\", \".bash\", \".pl\"]);\n//The number of URI's seen to be suspicious, higher = less likely to be suspicious\nlet uriThreshold = 1;\nlet ReqestCountThreshold = 10; // set minimum requests count to confirm repetitive connections\n// Only look at connections that were allowed through the web proxy\n_Im_WebSession (starttime=ago(lookback), eventresult='Success')\n| project\n    SrcBytes,\n    DstBytes,\n    Url,\n    TimeGenerated,\n    DstIpAddr,\n    SrcIpAddr,\n    HttpRequestMethod,\n    HttpReferrer\n| where not(ipv4_is_private(DstIpAddr)) // Only take traffic going to internet\n| extend DestHostName = tostring(parse_url(Url)[\"Host\"])\n// Only look at connections where some data was exchanged.\n| where SrcBytes > 0 and DstBytes > 0\n// Extract Domain\n| extend Domain = iif(countof(DestHostName, '.') >= 2, strcat(split(DestHostName, '.')[-2], '.', split(DestHostName, '.')[-1]), DestHostName)\n| extend GetData = iff(Url contains \"?\", 1, 0)\n| summarize\n    EventStartTime = min(TimeGenerated),\n    EventEndTime = max(TimeGenerated),\n    make_set(Url, 100),\n    make_set(DstIpAddr, 100),\n    make_set(SrcIpAddr, 100),\n    EventCount = count(),\n    make_set(HttpRequestMethod, 10),\n    max(GetData),\n    max(HttpReferrer)\n    by Domain\n// Determine the number of URIs that have been visited for the domain\n| extend destinationURICount = array_length(set_Url)\n| where destinationURICount <= uriThreshold and EventCount > ReqestCountThreshold // check for repetitive requests for single resource only.\n| where tostring(set_Url) has_any(scriptExtensions)\n//Remove matches with referer\n| where max_HttpReferrer == \"\"\n//Keep requests where data was transferred either in a GET with parameters or a POST\n| where set_HttpRequestMethod in~ (\"POST\") or max_GetData == 1\n//Defeat email click tracking, may increase FN's while decreasing FP's\n| where set_Url !has \"click\" and set_HttpRequestMethod !has \"GET\"\n| mv-expand set_Url, set_DstIpAddr, set_SrcIpAddr\n| extend\n    RequestURL = tostring(set_Url),\n    DestinationIP = tostring(set_DstIpAddr),\n    SourceIP = tostring(set_SrcIpAddr)\n| project\n    EventStartTime,\n    EventEndTime,\n    SourceIP,\n    DestinationIP,\n    EventCount,\n    RequestURL,\n    set_HttpRequestMethod\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Low",
        "status": "Available",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "tags": [
          {
            "Schema": "WebSession",
            "SchemaVersion": "0.2.6"
          },
          {
            "RuleReference": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Zscaler%20Internet%20Access/Analytic%20Rules/Zscaler-LowVolumeDomainRequests.yaml"
          }
        ],
        "techniques": [
          "T1071",
          "T1102"
        ],
        "templateVersion": "1.0.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}