Detection rules › Kusto
SlackAudit - Public link created for file which can contain sensitive information.
'Detects public links created for files that may contain sensitive data such as passwords, authentication tokens, secret keys, or private configuration files. Tune exclusions using the SlackAuditSensitiveFile_Allowlist_File and SlackAuditSensitiveFile_Allowlist_Account watchlists when known benign files or accounts generate expected public-link activity.'
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Exfiltration | T1048 Exfiltration Over Alternative Protocol, T1567.002 Exfiltration Over Web Service: Exfiltration to Cloud Storage |
Rule body kusto
id: 279316e8-8965-47d2-9788-b94dc352c853
name: SlackAudit - Public link created for file which can contain sensitive information.
description: |
'Detects public links created for files that may contain sensitive data such as passwords, authentication tokens,
secret keys, or private configuration files. Tune exclusions using the SlackAuditSensitiveFile_Allowlist_File and SlackAuditSensitiveFile_Allowlist_Account
watchlists when known benign files or accounts generate expected public-link activity.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SlackAuditAPI
dataTypes:
- SlackAudit_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Exfiltration
relevantTechniques:
- T1048
- T1567.002
query: |
let AllowedFiles = toscalar(_GetWatchlist('SlackAuditSensitiveFile_Allowlist_File') | summarize make_set(tostring(SearchKey)));
let AllowedUsers = toscalar(_GetWatchlist('SlackAuditSensitiveFile_Allowlist_Account') | summarize make_set(tostring(SearchKey)));
SlackAudit
| where Action =~ 'file_public_link_created'
| extend FileNameLower = tolower(EntityFileName), UserLower = tolower(SrcUserName)
| where EntityFileName in~ ('id_rsa')
or FileNameLower has_any ('password', 'secret', 'token', 'credential', 'private key', 'api key')
or FileNameLower has_any ('.ssh', '.npmrc', '.muttrc', '.gitconfig', '.netrc', 'package.json', 'Gemfile', 'bower.json', 'config.gypi', 'travis.yml', 'config.json')
| where isempty(AllowedFiles) or EntityFileName !in~ (AllowedFiles)
| where isempty(AllowedUsers) or UserLower !in~ (AllowedUsers)
| extend AccountCustomEntity = SrcUserName
| extend IPCustomEntity = SrcIpAddr
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: AccountCustomEntity
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
alertDetailsOverride:
alertDisplayNameFormat: Slack public link created for sensitive file {{EntityFileName}} by {{SrcUserName}}
alertDescriptionFormat: Public link created for {{EntityFileName}} by {{SrcUserName}} from {{SrcIpAddr}}
customDetails:
FileName: EntityFileName
Action: Action
SourceUser: SrcUserName
SourceIP: SrcIpAddr
ActorEntity: AccountCustomEntity
IpEntity: IPCustomEntity
version: 1.0.1
kind: Scheduled
Stages and Predicates
Let binding: AllowedFiles
let AllowedFiles = toscalar(_GetWatchlist('SlackAuditSensitiveFile_Allowlist_File') | summarize make_set(tostring(SearchKey)));
Let binding: AllowedUsers
let AllowedUsers = toscalar(_GetWatchlist('SlackAuditSensitiveFile_Allowlist_Account') | summarize make_set(tostring(SearchKey)));
Stage 1: source
SlackAudit
Stage 2: where
| where Action =~ 'file_public_link_created'
Stage 3: extend
| extend FileNameLower = tolower(EntityFileName), UserLower = tolower(SrcUserName)
Stage 4: where
| where EntityFileName in~ ('id_rsa')
or FileNameLower has_any ('password', 'secret', 'token', 'credential', 'private key', 'api key')
or FileNameLower has_any ('.ssh', '.npmrc', '.muttrc', '.gitconfig', '.netrc', 'package.json', 'Gemfile', 'bower.json', 'config.gypi', 'travis.yml', 'config.json')
Stage 5: where
| where isempty(AllowedFiles) or EntityFileName !in~ (AllowedFiles)
References AllowedFiles (defined above).
Stage 6: where
| where isempty(AllowedUsers) or UserLower !in~ (AllowedUsers)
References AllowedUsers (defined above).
Stage 7: extend
| extend AccountCustomEntity = SrcUserName
Stage 8: extend
| extend IPCustomEntity = SrcIpAddr
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
Action | eq |
|
AllowedFiles | is_null | |
AllowedUsers | is_null | |
EntityFileName | in |
|
FileNameLower | match |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
FileNameLower | extend |
UserLower | extend |
AccountCustomEntity | extend |
IPCustomEntity | extend |