← Back to SOC feed Coverage →

Disabled accounts using Squid proxy

kql MEDIUM Azure-Sentinel
T1110
SigninLogsSyslog
huntingmicrosoftofficial
This rule was pulled from an open-source repository and enriched with AI. Validate in a test environment before deploying to production.
View original rule at Azure-Sentinel →
Retrieved: 2026-06-04T23:00:00Z · Confidence: medium

Hunt Hypothesis

Disabled accounts that were previously disabled in Active Directory but are still being used with Squid proxy in the current environment may indicate persistent adversary access, as attackers could be leveraging dormant accounts to maintain long-term persistence and exfiltrate data undetected. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential covert channels and unauthorized access that evade traditional detection mechanisms.

KQL Query


let starttime = todatetime('{{StartTimeISO}}');
let endtime = todatetime('{{EndTimeISO}}');
let lookback = starttime - 14d;
let disabledAccounts = (){
SigninLogs
| where TimeGenerated between(lookback..starttime)
| where ResultType == 50057
| where ResultDescription =~ "User account is disabled. The account has been disabled by an administrator."
};
let proxyEvents = (){
Syslog
| where TimeGenerated between(starttime..endtime)
| where ProcessName contains "squid"
| extend URL = extract("(([A-Z]+ [a-z]{4,5}:\\/\\/)|[A-Z]+ )([^ :]*)",3,SyslogMessage),
         SourceIP = extract("([0-9]+ )(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3}))",2,SyslogMessage),
         Status = extract("(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))",1,SyslogMessage),
         HTTP_Status_Code = extract("(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))/([0-9]{3})",8,SyslogMessage),
         User = extract("(CONNECT |GET )([^ ]* )([^ ]+)",3,SyslogMessage),
         RemotePort = extract("(CONNECT |GET )([^ ]*)(:)([0-9]*)",4,SyslogMessage),
         Domain = extract("(([A-Z]+ [a-z]{4,5}:\\/\\/)|[A-Z]+ )([^ :\\/]*)",3,SyslogMessage),
         Bytes = toint(extract("([A-Z]+\\/[0-9]{3} )([0-9]+)",2,SyslogMessage)),
         contentType = extract("([a-z/]+$)",1,SyslogMessage)
| extend TLD = extract("\\.[a-z]*$",0,Domain)
};
proxyEvents
| where Status !contains 'DENIED'
| join kind=inner disabledAccounts on $left.User == $right.UserPrincipalName
| extend timestamp = TimeGenerated, AccountCustomEntity = UserPrincipalName, URLCustomEntity = URL

Analytic Rule Definition

id: 959fe0f0-7ac0-467c-944f-5b8c6fdc9e72
name: Disabled accounts using Squid proxy
description: |
  'Query finds accounts recorded as disabled by AD in previous time period but still using proxy in current time period. Presumes default squid log format is used. http://www.squid-cache.org/Doc/config/access_log/'
description_detailed: |
  'Look for accounts that have a been recorded as disabled by AD in the previous time period but are still using the proxy during
  the current time period. This query presumes the default squid log format is being used. http://www.squid-cache.org/Doc/config/access_log/'
requiredDataConnectors:
  - connectorId: Syslog
    dataTypes:
      - Syslog
tactics:
  - CredentialAccess
relevantTechniques:
  - T1110
query: |

  let starttime = todatetime('{{StartTimeISO}}');
  let endtime = todatetime('{{EndTimeISO}}');
  let lookback = starttime - 14d;
  let disabledAccounts = (){
  SigninLogs
  | where TimeGenerated between(lookback..starttime)
  | where ResultType == 50057
  | where ResultDescription =~ "User account is disabled. The account has been disabled by an administrator."
  };
  let proxyEvents = (){
  Syslog
  | where TimeGenerated between(starttime..endtime)
  | where ProcessName contains "squid"
  | extend URL = extract("(([A-Z]+ [a-z]{4,5}:\\/\\/)|[A-Z]+ )([^ :]*)",3,SyslogMessage),
           SourceIP = extract("([0-9]+ )(([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3}))",2,SyslogMessage),
           Status = extract("(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))",1,SyslogMessage),
           HTTP_Status_Code = extract("(TCP_(([A-Z]+)(_[A-Z]+)*)|UDP_(([A-Z]+)(_[A-Z]+)*))/([0-9]{3})",8,SyslogMessage),
           User = extract("(CONNECT |GET )([^ ]* )([^ ]+)",3,SyslogMessage),
           RemotePort = extract("(CONNECT |GET )([^ ]*)(:)([0-9]*)",4,SyslogMessage),
           Domain = extract("(([A-Z]+ [a-z]{4,5}:\\/\\/)|[A-Z]+ )([^ :\\/]*)",3,SyslogMessage),
           Bytes = toint(extract("([A-Z]+\\/[0-9]{3} )([0-9]+)",2,SyslogMessage)),
           contentType = extract("([a-z/]+$)",1,SyslogMessage)
  | extend TLD = extract("\\.[a-z]*$",0,Domain)
  };
  proxyEvents
  | where Status !contains 'DENIED'
  | join kind=inner disabledAccounts on $left.User == $right.UserPrincipalName
  | extend timestamp = TimeGenerated, AccountCustomEntity = UserPrincipalName, URLCustomEntity = URL
version: 1.0.1
metadata:
    source:
        kind: Community
    author:
        name: Shain
    support:
        tier: Community
    categories:
        domains: [ "Security - Network" ]

Required Data Sources

Sentinel TableNotes
SigninLogsEnsure this data connector is enabled
SyslogEnsure this data connector is enabled

MITRE ATT&CK Context

References

False Positive Guidance

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Hunting Queries/Syslog/disabled_account_squid_usage.yaml