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/'

Query · kql

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
Raw source Disabled accounts using Squid proxy · KQL
Esc
Published by Azure/Azure-Sentinel ↗, licensed under MIT ↗. Reproduced here unmodified.
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" ]

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.