{
  "$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/aba0b08c-aace-40c5-a21d-39153023dcaa')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/aba0b08c-aace-40c5-a21d-39153023dcaa')]",
      "properties": {
        "alertRuleTemplateName": "aba0b08c-aace-40c5-a21d-39153023dcaa",
        "customDetails": null,
        "description": "The query searches for event 5143, which is triggered when a share is created or changed and includes de share permissions.\nFirst it checks to see if this is a whitelisted share for the system (e.g. domaincontroller netlogon, printserver print$ etc.).\nThe share permissions are then checked against 'allow' rule (A) for a number of well known overly permissive groups, like all users, guests, authenticated users etc.\nIf these are found, an alert is raised so the share creation may be audited.\nNote: this rule only checks for changed permissions, to prevent repeat alerts if for example a comment is changed, but the permissions are not altered.\n",
        "displayName": "Excessive share permissions",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "Computer",
                "identifier": "FullName"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic%20Rules/ExcessiveSharePermissions.yaml",
        "query": "let timeframe=1h;\nlet system_roles = datatable(role:string, system:string)                  // Link roles to systems.\n  [\"DC\",\"dc1.corp.local\",\n  \"DC\",\"dc2.corp.local\",\n  \"PRINT\",\"printer.corp.local\"\n  ];\nlet share_roles = datatable(role:string, share:string)                    // Link roles to shares.\n  [\"DC\", @\"\\\\*\\sysvol\",\n  \"DC\",@\"\\\\*\\netlogon\",\n  \"PRINT\",@\"\\\\*\\print$\"];\nlet allowed_system_shares = system_roles                                  // Link systems to shares.\n  | join kind=inner share_roles on role\n  | extend system = tolower(system), share = tolower(share)\n  | project-away role\n  | summarize allowed_shares = make_set(share) by system;\nlet monitored_principals=datatable(identifier:string, Group_Name:string)  // Define a data-table with groups to monitor.\n  [\"AN\", \"Anonymous Logon\",            // We accept the 'alias' for these well-known SIDS.\n  \"AU\", \"Authenticated Users\",\n  \"BG\",\"Built-in guests\",\n  \"BU\",\"Built-in users\",\n  \"DG\",\"Domain guests\",\n  \"DU\",\"Domain users\",\n  \"WD\",\"Everyone\",\n  \"IU\",\"Interactively Logged-on users\",\n  \"LG\",\"Local Guest\",\n  \"NU\",\"Network logon users\",\n  \"513\", \"Domain Users\",                                                  // Support matching on the last part of a SID.\n  \"514\", \"Domain Guests\",\n  \"545\", \"Builtin Users\",\n  \"546\", \"Builtin Guests\",\n  \"S-1-5-7\", \"Anonymous Logon\"                                            // For the global SIDS, we accept them as-is.\n  ];\nSecurityEvent\n| where TimeGenerated >= ago(timeframe)\n| where EventID == 5143\n| extend EventXML = parse_xml(EventData)\n| extend OldSD = tostring(EventXML[\"EventData\"][\"Data\"][13][\"#text\"])     // Grab the previous Security Descriptor.\n| extend NewSD = tostring(EventXML[\"EventData\"][\"Data\"][14][\"#text\"])     // Grab the new Security Descriptor.\n| project-away EventXML\n| where tostring(OldSD) !~ tostring(NewSD)                                // Don't bother with unchanged permissions.\n| extend system = tolower(Computer), share=tolower(ShareName)             // Normalize system and share name for matching with whitelist.\n| join kind=leftouter allowed_system_shares on system                     // Retrieve the allowed shares per system.\n| where not(set_has_element(allowed_shares, share))                       // Check if the current share is an allowed share.\n| project-away system, share, allowed_shares                              // Get rid of temporary fields.\n| extend DACLS = extract_all(@\"(D:(?:\\((?:[\\w\\-]*;){5}(?:[\\w\\-]*)\\))*)\", tostring(NewSD)) // Grab all instances of D:(DACL), in case there are multiple sets.\n| project-away OldSD, NewSD                                               // Get rid of data we no longer need.\n| mv-expand DACLS to typeof(string)                                       // In case there are any duplicate/subsequent D: entries (e.g., D:<dacls>S:<sacls>D:<dacls>) split them out to individual D: sets.\n| extend DACLS = substring(DACLS,2)                                       // Strip the leading D:.\n| extend DACLS = split(DACLS, \")\")                                        // Split the sets of DACLS ()() to an array of individual DACLS (). This removes the trailing ) character.\n| mv-expand DACLS to typeof(string)                                       // Duplicate the records in such a way that only 1 DACL per record exist. We will aggregate them back later.\n| extend DACLS = substring(DACLS, 1)                                      // Also remove the leading ( character.\n| where not(isempty(DACLS)) and DACLS startswith \"A;\"                     // Remove any empty or non-allow DACLs.\n| extend allowed_principal = tostring(split(DACLS,\";\",5)[0])              // Grab the SID what is affected by this DACL.\n| extend allowed_principal = iff(not(allowed_principal startswith \"S-\" and string_size(allowed_principal) > 15), allowed_principal, split(allowed_principal,\"-\",countof(allowed_principal,\"-\"))[0]) // This line takes only the last part (e.g., 513) of a long SID, so you can refer to groups/users without needing to supply the full SID above.\n| join kind=inner monitored_principals on $left.allowed_principal == $right.identifier // Join the found groups to the table of groups to be monitored above. Adds the more readable 'group_name).\n| project-away allowed_principal, identifier, DACLS\n| summarize Authorized_Public_Principals = make_set(Group_Name), take_any(*) by TimeGenerated, SourceComputerId, EventData // Summarize the fields back, making a set of the various group_name values for this record.\n| project-away Group_Name\n// Begin client-specific filter.\n// End client-specific filter.\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "PT1H",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Collection",
          "Discovery"
        ],
        "techniques": [
          "T1039",
          "T1135"
        ],
        "templateVersion": "1.0.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}
