Detection rules › Kusto
Squid proxy events related to mining pools
'Checks for Squid proxy events in Syslog associated with common mining pools. This query presumes the default Squid log format is being used. http://www.squid-cache.org/Doc/config/access_log/'
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Command & Control | T1102 Web Service |
Rule body kusto
id: 80733eb7-35b2-45b6-b2b8-3c51df258206
name: Squid proxy events related to mining pools
description: |
'Checks for Squid proxy events in Syslog associated with common mining pools. This query presumes the default Squid log format is being used.
http://www.squid-cache.org/Doc/config/access_log/'
severity: Low
requiredDataConnectors:
- connectorId: Syslog
dataTypes:
- Syslog
- connectorId: SyslogAma
dataTypes:
- Syslog
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- CommandAndControl
relevantTechniques:
- T1102
query: |
let DomainList = dynamic(["monerohash.com", "do-dear.com", "xmrminerpro.com", "secumine.net", "xmrpool.com", "minexmr.org", "hashanywhere.com", "xmrget.com",
"mininglottery.eu", "minergate.com", "moriaxmr.com", "multipooler.com", "moneropools.com", "xmrpool.eu", "coolmining.club", "supportxmr.com",
"minexmr.com", "hashvault.pro", "xmrpool.net", "crypto-pool.fr", "xmr.pt", "miner.rocks", "walpool.com", "herominers.com", "gntl.co.uk", "semipool.com",
"coinfoundry.org", "cryptoknight.cc", "fairhash.org", "baikalmine.com", "tubepool.xyz", "fairpool.xyz", "asiapool.io", "coinpoolit.webhop.me", "nanopool.org",
"moneropool.com", "miner.center", "prohash.net", "poolto.be", "cryptoescrow.eu", "monerominers.net", "cryptonotepool.org", "extrmepool.org", "webcoin.me",
"kippo.eu", "hashinvest.ws", "monero.farm", "supportxmr.com", "xmrpool.eu", "linux-repository-updates.com", "1gh.com", "dwarfpool.com", "hash-to-coins.com",
"hashvault.pro", "pool-proxy.com", "hashfor.cash", "fairpool.cloud", "litecoinpool.org", "mineshaft.ml", "abcxyz.stream", "moneropool.ru", "cryptonotepool.org.uk",
"extremepool.org", "extremehash.com", "hashinvest.net", "unipool.pro", "crypto-pools.org", "monero.net", "backup-pool.com", "mooo.com", "freeyy.me", "cryptonight.net",
"shscrypto.net"]);
Syslog
| 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)
| where HTTP_Status_Code == '200'
| where Domain contains "."
| where Domain has_any (DomainList)
| extend AccountName = tostring(split(User, "@")[0]), AccountUPNSuffix = tostring(split(User, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: User
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIP
- entityType: URL
fieldMappings:
- identifier: Url
columnName: URL
version: 1.0.4
kind: Scheduled
Stages and Predicates
Let binding: DomainList
let DomainList = dynamic(["monerohash.com", "do-dear.com", "xmrminerpro.com", "secumine.net", "xmrpool.com", "minexmr.org", "hashanywhere.com", "xmrget.com",
"mininglottery.eu", "minergate.com", "moriaxmr.com", "multipooler.com", "moneropools.com", "xmrpool.eu", "coolmining.club", "supportxmr.com",
"minexmr.com", "hashvault.pro", "xmrpool.net", "crypto-pool.fr", "xmr.pt", "miner.rocks", "walpool.com", "herominers.com", "gntl.co.uk", "semipool.com",
"coinfoundry.org", "cryptoknight.cc", "fairhash.org", "baikalmine.com", "tubepool.xyz", "fairpool.xyz", "asiapool.io", "coinpoolit.webhop.me", "nanopool.org",
"moneropool.com", "miner.center", "prohash.net", "poolto.be", "cryptoescrow.eu", "monerominers.net", "cryptonotepool.org", "extrmepool.org", "webcoin.me",
"kippo.eu", "hashinvest.ws", "monero.farm", "supportxmr.com", "xmrpool.eu", "linux-repository-updates.com", "1gh.com", "dwarfpool.com", "hash-to-coins.com",
"hashvault.pro", "pool-proxy.com", "hashfor.cash", "fairpool.cloud", "litecoinpool.org", "mineshaft.ml", "abcxyz.stream", "moneropool.ru", "cryptonotepool.org.uk",
"extremepool.org", "extremehash.com", "hashinvest.net", "unipool.pro", "crypto-pools.org", "monero.net", "backup-pool.com", "mooo.com", "freeyy.me", "cryptonight.net",
"shscrypto.net"]);
Stage 1: source
Syslog
Stage 2: where
| where ProcessName contains "squid"
Stage 3: extend
| 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)
Stage 4: extend
| extend TLD = extract("\\.[a-z]*$",0,Domain)
Stage 5: where
| where HTTP_Status_Code == '200'
Stage 6: where
| where Domain contains "."
Stage 7: where
| where Domain has_any (DomainList)
References DomainList (defined above).
Stage 8: extend
| extend AccountName = tostring(split(User, "@")[0]), AccountUPNSuffix = tostring(split(User, "@")[1])
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 |
|---|---|---|
Domain | contains |
|
Domain | match |
|
HTTP_Status_Code | eq |
|
ProcessName | contains |
|
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 |
|---|---|
Bytes | extend |
Domain | extend |
HTTP_Status_Code | extend |
RemotePort | extend |
SourceIP | extend |
Status | extend |
URL | extend |
User | extend |
contentType | extend |
TLD | extend |
AccountName | extend |
AccountUPNSuffix | extend |