skip to content

Which observations about a live session record honestly indicate hijack, and what should the server do with that verdict?

level: seniorimportance: should knowfreq 52%

answer

  1. behaviour over time, not one property
  2. two places at once
  3. a rate no human produces
  4. allow, challenge, or end
  5. measure the rate before enforcing

basics

~20 s

Three families: use from two places that cannot both be true at once, an established client property changing mid-session, and a request rate or ordering no human produces. The verdict routes to record-only, challenge, or end — never straight to end.

solid answer

~50 s

Detection beats binding because it looks at **behaviour over time** instead of one property per request. The signals worth having are: parallel use of a single server-side session record from two networks within a window too short for one caller to have moved (the impossible-travel or velocity check); a change of an established property mid-session, such as the network operator or the client agent family; and a shape anomaly — a request rate, an ordering, or a breadth of records touched that no human at a bedside produces. None of these is a verdict on its own; you combine them into a score. The score routes to one of three outcomes: record and allow, demand fresh proof while keeping the record alive, or end it. Run the detector in observe-only mode first, because until the false-positive rate per population is measured, enforcing it is a guess.

code

pseudocode · 22 lines
pseudocode
signals = []

if elapsed(record.last_seen, now) < min_travel_time(record.last_net, now_net):
    signals.add("impossible-travel", weight = 4)

if in_flight_from_two_networks(record.id, window = 60s):
    signals.add("parallel-use", weight = 4)

if agent_family(request) != record.bind.agent_family:
    signals.add("agent-family-change", weight = 1)

if request_rate(record.id, window = 60s) > human_ceiling:
    signals.add("machine-rate", weight = 3)

score = decayed_total(record, signals)

if score < CHALLENGE_AT:            # low band
    record_only(signals); allow(request)
else if score < END_AT:             # middle band, thresholds are exclusive
    challenge(request)              # ask for fresh proof; the record stays alive
else:                               # high band
    end_session(record.id, reason = signals)

go deeper

for a junior

Know that a server can notice a session being used in ways one person could not manage — two distant places at once, or far faster than a human works — and that noticing is separate from acting.

for a middle

Explain the three signal families and why each one alone has an innocent explanation, so they are combined into a score rather than wired individually to an action.

for a senior

Show the operational discipline: observe-only first, measured false-positive rates per population, decaying scores, re-baselining, and a middle band that challenges instead of ending the record.

for a principal

Own the trade between residual risk and the cost of a false positive, and be able to justify the thresholds as a business decision rather than an engineering preference.

## Why detection and binding are different tools A binding asks one question per request — *does this property still match?* — and can only answer with the properties the caller happens to present. Detection asks a question about the **history of one server-side session record**: given everything this record has done, is a single caller a plausible explanation? That difference matters because the signals that actually distinguish two callers are temporal, and no single request contains them. ## The three families worth implementing 1. **Parallel or impossible use.** The same session record is in flight from two networks within a window too short for one caller to have crossed between them — the velocity or impossible-travel check. This is the strongest family because it needs no assumption about what a normal caller looks like: both halves of the evidence belong to the same record, and simultaneity from two distant positions has no benign explanation a single caller can give. It is not infallible — a client whose traffic egresses through two different gateways, or a user on a corporate tunnel that flaps, can produce it — which is why it scores rather than decides. 2. **A change of an established property mid-session.** The network operator changes, the client agent family changes, the declared locale or time offset changes. Each has an innocent explanation in isolation (a hand-off, an update, a traveller), so each is weak alone. Two of them changing in the same minute is much less innocent than either one. 3. **Shape anomalies.** A request rate above what a human produces, an ordering no interface generates, or a breadth of records touched that no single shift's work explains. This family catches the case the other two miss entirely: the attacker who is on the same network, on the same terminal, presenting every property correctly, and simply working faster and wider than a person does. ## Scoring instead of tripwires Every one of those signals has a benign cause, so any of them wired directly to an action is a false-positive factory. Combine them: - Give each signal a weight reflecting how often it fires on honest traffic **in your deployment**, not in general. - Sum them into a score with two thresholds, and make the thresholds explicit configuration you can move without a deploy. - Decay the score, so yesterday's accepted hand-off is not still counting against a clinician today. - Re-baseline accepted changes on the record, or a single legitimate move is scored on every subsequent request. ## Routing the verdict | Score band | Action | What it costs an honest user | What it costs an attacker | |---|---|---|---| | Low | record the signal, allow the request | nothing | nothing yet — you are building evidence | | Middle | demand fresh proof, keep the record alive | seconds | the credential they do not have | | High | end the session record | their work in progress | the session | The middle row is the one candidates skip, and it is the one that makes the system usable. A probabilistic verdict should buy a **challenge**, because a challenge converts a probability into evidence: an attacker who cannot re-prove identity is exposed, while an honest clinician loses a few seconds and keeps their chart open. Reserve ending the record for the band where you are willing to defend the false positive out loud. What happens after you decide to end it — which sibling sessions go with it, and how the user is told — is a separate mechanism from deciding. ## Measure before you enforce Ship the detector emitting signals and verdicts into a log with no action attached, and leave it there long enough to cover a full cycle of the things that move: a fleet update, a network change, a month of shifts. Then you can state, per population, how many honest sessions each threshold would have challenged and how many it would have ended. Enforcing before that number exists is how a control gets disabled permanently after one bad morning. ## What detection still cannot see The blind spot is the same one binding has, for the same reason: when the second caller is physically at the same terminal on the same network, every property is identical and only the **shape** family has anything to work with. On a shared clinical terminal that is precisely the realistic threat, which is why the shape signals earn their keep there and the property signals do not.

  • How do you stop a detector from doing more damage than the attack it catches?
    Run it in observe-only mode until you can state the false-positive rate per population, score signals instead of wiring tripwires, decay the score, and route the middle band to a challenge rather than a logout. A control that ends sessions on a guess gets switched off after its first bad morning.
  • Why is parallel use a stronger signal than a single property changing?
    A property change has ordinary explanations — an update, a network hand-off, travel. Simultaneous use from two positions one caller cannot occupy at once has none that a single caller can give, and both halves of the evidence belong to the same session record rather than relying on a baseline of what is normal.
  • What would you log so the verdict can be reviewed afterwards?
    The session record's identifier, the signals that fired with their weights, the resulting score, the threshold it crossed, the action taken, and the outcome of any challenge. Without the score and the threshold beside the action, nobody can later tell whether a lockout was correct or whether a threshold needs moving.

saying these in an interview costs you the question

  • Wires a single anomaly signal directly to ending the session record
  • Says impossible travel has no false positives at all
  • Ignores request shape because the client properties all matched
  • Enforces thresholds that were never measured against honest traffic
  • Treats challenging the caller and ending the session as the same response