Codesecure SolutionsA Codesecure Solutions product
Correlation use cases

The attacks that no single
event ever reveals.

A failed login is noise. Forty failures then a success from the same address is an incident. Correlation is where the pipeline stops looking at events and starts looking at behaviour. These patterns ship enabled, each one broken down here: what the attacker does, why single event detection misses it, and the exact file that catches it.

nullsoc.in / correlations / industry_correlations
The NullSOC correlation editor showing an entire correlation file as one highlighted YAML document.

The shipped correlation file, open in the editor. Every pattern, one document.

5
ATT&CK tactics covered
Reconnaissance, initial access, credential access, escalation and persistence.
4,512
Detections feeding them
Every rule finding is an input to the correlation stage.
Any
Sequence you can express
Four keys cover thresholds, ordering, grouping and variation.
24h
Backtest before enabling
Replay real history through a draft and see every time it would have fired.
At a glance

The patterns, and the
evidence each one needs.

Every card opens onto the full breakdown: the attack, why it hides from single event detection, the file that catches it, and what to do when it fires.

T1110 correlation 900021

Password spray

An attacker takes one common password and tries it against every account they can name. Each account sees one or two...

read the breakdown
T1110 correlation 900010

Brute force, then a success

Repeated SSH authentication failures from one address, and then that same address logs in successfully. The failures...

read the breakdown
T1110 correlation 900020

Credential compromise

Five failed attempts against one account, then that account authenticates successfully. The attacker found the...

read the breakdown
T1110 correlation 900013

Spraying across hosts

One source address failing logins against several different machines. The attacker is looking for the weakest host in...

read the breakdown
T1078 correlation 900011

Impossible travel

One account authenticates successfully from two different countries inside the same hour. Nobody flies that fast....

read the breakdown
T1078 correlation 900012

Login from an unexpected country

A successful authentication whose source geography sits outside the countries you actually operate in. The simplest...

read the breakdown
T1595 correlation 900022

Reconnaissance, then exploitation

A port scan or web probe from an address, and then an actual attack from that same address. The scan was the attacker...

read the breakdown
T1136 correlation 900023

Backdoor account

A new account is created on a host, and then that account is added to a privileged group. Two entirely ordinary...

read the breakdown
T1068 T1136 correlation 900501

Escalation, then a new account

Four attack events against a host, then a user added on that same host. The attacker got in, escalated, and is now...

read the breakdown
Credential attacks

Credential attacks

Somebody is guessing, spraying or reusing credentials. Individually each attempt is a routine failed login, which is exactly why volume based alerting either misses these or drowns in them.

correlation 900021

Password spray

T1110 High
The attack

An attacker takes one common password and tries it against every account they can name. Each account sees one or two failures, comfortably under any lockout threshold, so nothing locks and nothing alerts. From the account side it looks like ordinary user error.

Why a single event misses it

Per account thresholds are the standard control, and a spray is designed to defeat them. Five failures on one account is a lockout. One failure on fifty accounts is invisible, unless you group by the source instead of the target.

What to do with it

Block the source, then check whether any account in the sprayed set subsequently succeeded. A spray that found one working credential is a breach, not an attempt.

groups bysource.ip
requires variationuser.name >= 6 distinct
threshold10 failures
window10 minutes
severitylevel 12

The different count is what makes this a spray rather than a brute force. Six or more distinct accounts from one address, inside ten minutes.

correlation 900021shipped, unedited
- id: 900021 level: 12 timeframe: 600s steps: - match: rule.groups contains authentication_failed and source.ip exists frequency: 10 same: [source.ip] different: - user.name >= 6 mitre: [T1110] description: "Password spray, one source IP failing logins against 6+ different users"
correlation 900010

Brute force, then a success

T1110 High
The attack

Repeated SSH authentication failures from one address, and then that same address logs in successfully. The failures are the attack. The success is the breach.

Why a single event misses it

Most deployments alert on the failures and treat the success as a separate, benign event. The two are only meaningful together, and only when tied to the same source.

What to do with it

Treat the session as compromised. The account that succeeded is the one to rotate, and the source address is the one to block.

groups bysource.ip
sequencerule 5716 then rule 5715
threshold6 failures
window2 minutes
severitylevel 12

This matches on specific rule ids rather than groups, so it is precise to sshd. The group based variant below covers every authentication source.

correlation 900010shipped, unedited
- id: 900010 level: 12 timeframe: 120s steps: - match: rule.id == 5716 frequency: 6 - match: rule.id == 5715 same: [source.ip] mitre: [T1110] description: SSH brute force then successful login
correlation 900020

Credential compromise

T1110 High
The attack

Five failed attempts against one account, then that account authenticates successfully. The attacker found the password, whether by guessing, by a list, or by trying a leaked credential that turned out to still work.

Why a single event misses it

Grouped by account rather than by source, so it still fires when the attacker rotates addresses between attempts, which a source based rule would miss entirely.

What to do with it

Force a password reset on that account and review everything it did after the successful login. This is the correlation that most often turns into a real case.

groups byuser.name
sequencefailures then success
threshold5 failures
window5 minutes
severitylevel 12

Because it groups on the account, a distributed attempt from many addresses still collapses into one finding rather than five unrelated ones.

correlation 900020shipped, unedited
- id: 900020 level: 12 timeframe: 300s steps: - match: rule.groups contains authentication_failed frequency: 5 - match: rule.groups contains authentication_success same: [user.name] mitre: [T1110] description: "Successful login after repeated failures (same account), credential compromise"
correlation 900013

Spraying across hosts

T1110 High
The attack

One source address failing logins against several different machines. The attacker is looking for the weakest host in the estate rather than hammering a single door.

Why a single event misses it

Every per host control sees a trickle and stays quiet. Only a view across the whole estate, grouped by source, shows the shape of it.

What to do with it

Block at the perimeter rather than on the individual hosts, and check whether the source reached anything it should not have been able to see.

groups bysource.ip
requires variationagent.name
window10 minutes
severitylevel 12

The different field is the host, so a noisy attacker against one machine is deliberately excluded. This fires on breadth, not volume.

correlation 900013shipped, unedited
- id: 900013 level: 12 timeframe: 600s steps: - match: rule.groups contains authentication_failed and source.ip exists frequency: 1 same: [source.ip] different: - agent.name mitre: [T1110] description: Same source IP failing logins across multiple agents
Account abuse

Account abuse

The credentials worked. What makes these suspicious is not the login itself but where it came from, or the impossibility of the same account being in two places at once.

correlation 900011

Impossible travel

T1078 High
The attack

One account authenticates successfully from two different countries inside the same hour. Nobody flies that fast. Either the credentials are shared between people, or they are in somebody else hands.

Why a single event misses it

Both events are successful logins. Nothing about either one is anomalous on its own, and no severity threshold will ever surface them.

What to do with it

Confirm with the account owner before acting. Shared credentials and corporate VPN egress are the two common benign explanations, and both are worth fixing anyway.

groups byuser.name
requires variationsource.geo.country_iso_code
window1 hour
severitylevel 12

Geography is resolved at decode from a city level database, so the country is a real field the correlation can group on rather than an enrichment done after the fact.

correlation 900011shipped, unedited
- id: 900011 level: 12 timeframe: 3600s steps: - match: rule.id == 5715 - match: rule.id == 5715 same: [user.name] different: - source.geo.country_iso_code mitre: [T1078] description: "Impossible travel: same user, two countries"
correlation 900012

Login from an unexpected country

T1078 High
The attack

A successful authentication whose source geography sits outside the countries you actually operate in. The simplest possible geographic control, and one of the most effective.

Why a single event misses it

It is a successful login. There is nothing wrong with it except where it came from, which is context no single event rule carries.

What to do with it

Verify against your travel and contractor list. Then decide whether the country belongs on an allow list or the account belongs in a case.

matchauthentication_success
guardcountry exists and is not home
window1 hour
severitylevel 12

The country list is a condition inside the file, so it is yours to set. The exists guard matters: without it, every local login with no geography at all would fire.

correlation 900012shipped, unedited
- id: 900012 level: 12 timeframe: 3600s steps: - match: rule.groups contains authentication_success and source.geo.country_iso_code exists and source.geo.country_iso_code != "IN" mitre: [T1078] description: Login success from outside India
Intrusion and persistence

Intrusion and persistence

Two ordinary administrative events in the wrong order. Nothing here trips a single event rule, because every step is something a legitimate administrator does every week.

correlation 900022

Reconnaissance, then exploitation

T1595 High
The attack

A port scan or web probe from an address, and then an actual attack from that same address. The scan was the attacker choosing a target. The attack is them acting on it.

Why a single event misses it

Internet facing hosts are scanned constantly. Alerting on scans is pure noise, and alerting only on attacks loses the context that this one was researched first.

What to do with it

Prioritise this above an unattributed attack. Somebody who scanned first knows what they found and is far more likely to come back.

groups bysource.ip
sequencerecon or web scan then attack
window30 minutes
severitylevel 12

This is the correlation that turns a scan from noise into evidence. The scan alone stays silent, exactly as it should.

correlation 900022shipped, unedited
- id: 900022 level: 12 timeframe: 1800s steps: - match: rule.groups contains recon or rule.groups contains web_scan - match: rule.groups contains attack same: [source.ip] mitre: [T1595] description: Reconnaissance then attack from the same source (scan then exploit)
correlation 900023

Backdoor account

T1136 High
The attack

A new account is created on a host, and then that account is added to a privileged group. Two entirely ordinary administrative actions that, back to back on one machine, are how an intruder keeps their access after you close the way they came in.

Why a single event misses it

Accounts get created and groups get changed every week in a normal estate. Alerting on either produces noise nobody reads. The sequence on a single host is the signal.

What to do with it

Confirm against your change record. An account creation with no ticket behind it, followed by a privilege grant, is persistence until proven otherwise.

groups byagent.name
sequenceaccount created then group changed
window1 hour
severitylevel 13

Raised to level 13, above the credential correlations, because a successful persistence step means an earlier stage already worked.

correlation 900023shipped, unedited
- id: 900023 level: 13 timeframe: 3600s steps: - match: rule.groups contains adduser or rule.groups contains account_changed - match: rule.groups contains group_changed same: [agent.name] mitre: [T1136] description: New account then group-membership change on the same host (backdoor account)
correlation 900501

Escalation, then a new account

T1068 T1136 Critical
The attack

Four attack events against a host, then a user added on that same host. The attacker got in, escalated, and is now provisioning themselves a way back that survives a patch.

Why a single event misses it

The attack events may each be blocked and logged as handled. The account creation looks like administration. Neither half raises an incident alone.

What to do with it

Treat the host as compromised and work the timeline backwards from the account creation. This is the highest severity correlation in the shipped set.

groups byagent.id
sequence4 attacks then account added
window5 minutes
severitylevel 15, critical

A five minute window is deliberately tight. This is the shape of an active intrusion, not a pattern that unfolds over days.

correlation 900501shipped, unedited
- id: 900501 level: 15 timeframe: 300s steps: - match: rule.groups contains attacks frequency: 4 - match: rule.groups contains adduser same: [agent.id] mitre: [T1068, T1136] description: Attacks followed by the addition of a user on the same host (Wazuh 40501, composite rule expressed as a correlation)
Write your own

Four keys cover
nearly every pattern.

The set above is a starting point, not a ceiling. Correlation uses the same condition grammar as the detection rules, so anything a rule can match, a correlation can sequence.

  • steps is an ordered list. One step with a frequency is a threshold. Two or more is a sequence that must happen in order.
  • same ties the steps together. Group by source address, account or host so two unrelated attacks never merge into one finding.
  • different demands variation. A bare field means at least two distinct values, and field >= N means at least N.
  • timeframe is the window the whole pattern must complete inside, so a slow trickle over a week does not accumulate into a false positive.
Backtest before you enable. Replay the last 24 hours of real findings through a draft correlation and see every time it would have fired, using the same engine the worker runs.
Correlation reference
FileYAML, many per file
Runs overthe finding stream
Grammarthe same 25 rule operators
stepsordered, per step frequency
samegroup the chain
differentfield, or field >= N
timeframe120s, 10m, 1h
level0 to 16
mitretechnique ids
Backtest24 hours of real findings
Get started

Bring the intrusion your tools
only saw one half of.

Describe an incident where the alerts were all individually low severity. We will express it as a correlation on the call and backtest it against your own history.

Powered by Codesecure Solutions. Self hosted, cloud or fully managed.