---
title: 'Physical Techniques'
source: 'https://academia.sh/en/courses/attack-techniques/physical-techniques'
course: 'Attack Techniques and the Threat Landscape'
language: en
updated: '2026-09-26T03:02:49+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Counts doors, cards, and visual verification as access items and derives the paths to the target zone'
    - "Models three physical techniques as step sequences and computes each one's early-break gain"
    - "Measures the escort procedure's effect with two numbers: access items gained and escort time spent"
---

# Physical Techniques

Counting tailgating, shoulder surfing, and dumpster diving in terms of access items: the number of paths to the target zone in a fictional building made up of ten doors, five cards, and two visual verifications, how many doors break the chain on each path, the two paths that never break, and the ten access items the escort procedure gains against its daily cost of 6.8 hours.

Every channel in the previous lesson worked remotely, and all of them shared one precondition: an
address — an email address, a number, or an account. A person entering a building needs none of
these. Going through a door, looking at a screen left unlocked, or collecting a discarded document
draws on a different set of resources, and this set's items are countable: doors, cards, visual
verification.

This lesson measures three techniques on the same building model. Tailgating exploits a door staying
open; shoulder surfing exploits a line of sight; dumpster diving exploits waste that has not been
separated. All three have short chains, and in all three the first step is one no control sees. What
is measured is not how entering the building is done, but **which access item breaks which link**.
Running trials like these outside of written authorization and a defined scope is both illegal and
unprofessional.

- **SE19.** The building, door graph, card authorizations, and waste flow belong to a branch office
  of the fictional regional measurement network. No real building exists; what is measured is the model
  built with `node`.
- **SE20.** A card alone does not stop tailgating: once a card is read, the door opens, and the card
  does not know how many people passed through behind it. The controls that break the chain are a
  control that **sees** the person and a single-person passage.
- **SE21.** The path search counts paths that do not pass through the same door twice. Non-door
  passages such as windows, elevator shafts, and fire exits were not modeled; a real building would
  count these paths too.
- **SE22.** Visual verification depends on a person being present there. Off-shift hours and busy
  passage moments were not modeled; both lower this control's strength.
- **SE23.** The dropped access item is the count of doors, screens, and documents that become
  reachable once that step completes. Item types were not weighted separately.
- **SE24.** The escort procedure rests on the assumption that a person alone in an interior zone is
  seen. An escort losing sight of the person they are escorting was not modeled.

## Access Items and Paths

```js
// building.mjs — door graph, card authorizations, and the chain of three physical techniques; model
// [door, source zone, target zone, control]
export const DOOR = [
  ['main entrance', 'outside', 'entrance hall', 'visual'],
  ['side entrance', 'outside', 'entrance hall', 'card'],
  ['parking garage elevator', 'outside', 'office floor', 'card'],
  ['loading dock door', 'outside', 'warehouse', 'none'],
  ['lobby turnstile', 'entrance hall', 'office floor', 'card+single person'],
  ['warehouse corridor', 'warehouse', 'office floor', 'none'],
  ['equipment room door', 'office floor', 'equipment room', 'card'],
  ['server room door', 'equipment room', 'server room', 'card+visual'],
  ['archive door', 'office floor', 'archive', 'card'],
  ['waste point', 'warehouse', 'waste area', 'none'],
];
export const CARD = { // card type: doors it opens
  visitor: ['side entrance'], office: ['side entrance', 'lobby turnstile', 'archive door'],
  field: ['side entrance', 'lobby turnstile', 'loading dock door'],
  technical: ['side entrance', 'parking garage elevator', 'lobby turnstile', 'equipment room door', 'server room door'],
  cleaning: ['side entrance', 'lobby turnstile', 'equipment room door', 'archive door'],
};
// a card alone does not stop tailgating; a control that sees the person or a single-person passage does
export const breaks = (control) => control.includes('visual') || control.includes('single person');
export function paths(target, zone = 'outside', visited = []) {
  if (zone === target) return [visited];
  return DOOR.filter((k) => k[1] === zone && !visited.includes(k[0]))
    .flatMap((k) => paths(target, k[2], [...visited, k[0]]));
}
export const controlOf = (name) => DOOR.find((k) => k[0] === name)[3];
// [technique, [step, precondition, control that sees the step, access item dropped once the step completes]]
export const TECHNIQUE = {
  tailgating: [
    ['waiting in front of the door', 'the door being visible from outside', null, 0],
    ['waiting for an authorized passage', 'a busy passage hour', null, 0],
    ['entering on the same passage', 'the door staying open', 'single-person passage', 2],
    ['advancing to the target zone', 'interior doors being uncontrolled', 'visual verification', 5],
  ],
  'shoulder surfing': [
    ['positioning in a shared area', 'visitor access', null, 0],
    ['observing the screen or keypad', 'line of sight', 'screen placement', 1],
    ['using the observed information', 'a valid session', 'second factor', 4],
  ],
  'dumpster diving': [
    ['accessing the waste point', 'the waste area being uncontrolled', null, 0],
    ['collecting documents', 'unseparated waste', 'document destruction procedure', 3],
    ['using the collected information', 'the information being current', 'record retention period', 4],
  ],
};
export const ESCORT = { dailyPassages: 34, averageMinutes: 12 }; // fictional
```

```js
// run1.mjs — count of access items and the control density of paths to the target zone
import { DOOR, CARD, breaks, paths, controlOf } from './building.mjs';

const visual = DOOR.filter((k) => k[3].includes('visual'));
console.log(`${DOOR.length} doors, ${Object.keys(CARD).length} card types, ${visual.length} visual verification points`);
console.log(`uncontrolled doors ${DOOR.filter((k) => k[3] === 'none').length}, card-only ${DOOR.filter((k) => k[3] === 'card').length}, ` +
  `doors that break tailgating ${DOOR.filter((k) => breaks(k[3])).length}\n`);
console.log(`${'door'.padEnd(24)} ${'source'.padEnd(14)} ${'target'.padEnd(16)} ${'control'.padEnd(18)} ${'opening cards'.padStart(13)}`);
for (const [name, a, b, d] of DOOR)
  console.log(`${name.padEnd(24)} ${a.padEnd(14)} ${b.padEnd(16)} ${d.padEnd(18)} ` +
    `${String(Object.values(CARD).filter((v) => v.includes(name)).length).padStart(13)}`);
for (const target of ['server room', 'archive']) {
  const y = paths(target);
  console.log(`\n${target}: ${y.length} paths`);
  console.log(`${'path'.padEnd(83)} ${'doors'.padStart(5)} ${'breaking'.padStart(8)} ${'cardless'.padStart(15)}`);
  for (const p of y)
    console.log(`${p.join(' > ').padEnd(83)} ${String(p.length).padStart(5)} ` +
      `${String(p.filter((k) => breaks(controlOf(k))).length).padStart(8)} ` +
      `${String(p.filter((k) => controlOf(k) === 'none').length).padStart(15)}`);
  const fewest = y.reduce((a, b) => (b.filter((k) => breaks(controlOf(k))).length < a.filter((k) => breaks(controlOf(k))).length ? b : a));
  console.log(`path with fewest controls: ${fewest.join(' > ')} (${fewest.filter((k) => breaks(controlOf(k))).length} breaking doors)`);
}
console.log(`\ncard types that open the server room ${Object.entries(CARD).filter(([, v]) => v.includes('server room door')).length}, ` +
  `that open the equipment room door ${Object.entries(CARD).filter(([, v]) => v.includes('equipment room door')).length}`);
```

```
10 doors, 5 card types, 2 visual verification points
uncontrolled doors 3, card-only 4, doors that break tailgating 3

door                     source         target           control            opening cards
main entrance            outside        entrance hall    visual                         0
side entrance            outside        entrance hall    card                           5
parking garage elevator  outside        office floor     card                           1
loading dock door        outside        warehouse        none                           1
lobby turnstile          entrance hall  office floor     card+single person             4
warehouse corridor       warehouse      office floor     none                           0
equipment room door      office floor   equipment room   card                           2
server room door         equipment room server room      card+visual                    1
archive door             office floor   archive          card                           2
waste point              warehouse      waste area       none                           0

server room: 4 paths
path                                                                                doors breaking        cardless
main entrance > lobby turnstile > equipment room door > server room door                4        3               0
side entrance > lobby turnstile > equipment room door > server room door                4        2               0
parking garage elevator > equipment room door > server room door                        3        1               0
loading dock door > warehouse corridor > equipment room door > server room door         4        1               2
path with fewest controls: parking garage elevator > equipment room door > server room door (1 breaking doors)

archive: 4 paths
path                                                                                doors breaking        cardless
main entrance > lobby turnstile > archive door                                          3        2               0
side entrance > lobby turnstile > archive door                                          3        1               0
parking garage elevator > archive door                                                  2        0               0
loading dock door > warehouse corridor > archive door                                   3        0               2
path with fewest controls: parking garage elevator > archive door (0 breaking doors)

card types that open the server room 1, that open the equipment room door 2
```

The door table counts the access items: ten doors, five card types, two visual verification points.
Three doors have no control at all, four doors open with a card only, and the number of doors that
break tailgating is three. The card column shows a second imbalance: only one card type opens the
server room door, but two types open the equipment room door, and one of those is the cleaning card.
Authorization is narrowest at the last door and doubles at the one before it.

The path table gives the real number. There are four paths to the server room, and the breaking-door
count across these paths ranges from three down to one. The path through the main entrance contains
three breaking doors; the path through the parking garage elevator contains only one. This gap between
two paths to the same target shows that defense is stacked at the main entrance, and side entrances are
not treated with the same measure.

The archive is sharper still. In two of the four paths, the breaking-door count is **zero**. The
loading dock door and the warehouse corridor carry no control at all, and both are passed without a
card; the parking garage elevator requires a card but does not see the person. Counting paths here
does not just produce a surface — it produces a ranking: which route to which target leaves a course
that no control sees.

## Three Chains and the Escort Procedure

```js
// run2.mjs — the chain of three techniques, the path-dependent breakable link, and the escort procedure's cost
import { TECHNIQUE, ESCORT, paths, controlOf } from './building.mjs';

const cumulOf = (z) => { let s = 0; return z.map((a) => (s += a[3])); };
console.log(`${'technique'.padEnd(16)} ${'steps'.padStart(5)} ${'controlled'.padStart(10)} ${'early items'.padStart(11)} ` +
  `${'late items'.padStart(10)} ${'gain'.padStart(6)} ${'if never broken'.padStart(15)}`);
for (const [name, z] of Object.entries(TECHNIQUE)) {
  const k = cumulOf(z), d = z.map((a, i) => (a[2] ? i : -1)).filter((i) => i >= 0);
  const e = d[0] ? k[d[0] - 1] : 0, g = k[d[d.length - 1] - 1];
  console.log(`${name.padEnd(16)} ${String(z.length).padStart(5)} ${String(d.length).padStart(10)} ${String(e).padStart(11)} ` +
    `${String(g).padStart(10)} ${String(g - e).padStart(6)} ${String(k[z.length - 1]).padStart(15)}`);
}
const T = TECHNIQUE.tailgating, TK = cumulOf(T);
console.log(`\ntailgating chain:`);
T.forEach((a, i) => console.log(`  ${i + 1} ${a[0].padEnd(34)} precondition ${a[1].padEnd(37)} control ${(a[2] ?? '-')}`));
const link = (path, escort) => {
  const d = [];
  if (path.some((k) => controlOf(k).includes('single person'))) d.push(2);
  if (escort || path.some((k) => controlOf(k).includes('visual'))) d.push(3);
  return d;
};
const dropped = (d) => (d.length ? { e: d[0] ? TK[d[0] - 1] : 0, g: TK[d[d.length - 1] - 1] } : { e: TK[3], g: TK[3] });
let unbroken = 0, gain = 0;
// dropped column: access items dropped at the earliest breakable link; if never breakable, the entire chain
for (const target of ['server room', 'archive']) {
  console.log(`\n${target} (${paths(target).length} paths)`.padEnd(84) +
    `${'links'.padStart(5)} ${'dropped'.padStart(7)} ${'escorted'.padStart(9)} ${'dropped'.padStart(7)}`);
  for (const p of paths(target)) {
    const a = link(p, false), b = link(p, true), da = dropped(a), db = dropped(b);
    if (!a.length) unbroken++;
    gain += da.e - db.e;
    console.log(`${p.join(' > ').padEnd(83)} ${String(a.length).padStart(5)} ${String(da.e).padStart(7)} ` +
      `${String(b.length).padStart(9)} ${String(db.e).padStart(7)}`);
  }
}
console.log(`\npaths never broken without escort ${unbroken}/8; total gain from the escort procedure ${gain} access items`);
console.log(`cost: ${ESCORT.dailyPassages} escorted passages a day x ${ESCORT.averageMinutes} min = ` +
  `${ESCORT.dailyPassages * ESCORT.averageMinutes} min (${(ESCORT.dailyPassages * ESCORT.averageMinutes / 60).toFixed(1)} hours/day)`);
```

```
technique        steps controlled early items late items   gain if never broken
tailgating           4          2           0          2      2               7
shoulder surfing     3          2           0          1      1               5
dumpster diving      3          2           0          3      3               7

tailgating chain:
  1 waiting in front of the door       precondition the door being visible from outside   control -
  2 waiting for an authorized passage  precondition a busy passage hour                   control -
  3 entering on the same passage       precondition the door staying open                 control single-person passage
  4 advancing to the target zone       precondition interior doors being uncontrolled     control visual verification

server room (4 paths)                                                              links dropped  escorted dropped
main entrance > lobby turnstile > equipment room door > server room door                2       0         2       0
side entrance > lobby turnstile > equipment room door > server room door                2       0         2       0
parking garage elevator > equipment room door > server room door                        1       2         1       2
loading dock door > warehouse corridor > equipment room door > server room door         1       2         1       2

archive (4 paths)                                                                  links dropped  escorted dropped
main entrance > lobby turnstile > archive door                                          2       0         2       0
side entrance > lobby turnstile > archive door                                          1       0         2       0
parking garage elevator > archive door                                                  0       7         1       2
loading dock door > warehouse corridor > archive door                                   0       7         1       2

paths never broken without escort 2/8; total gain from the escort procedure 10 access items
cost: 34 escorted passages a day x 12 min = 408 min (6.8 hours/day)
```

The three-technique table shows how short these chains are: four, three, and three steps. In all three
the first step is uncontrolled, and in all three the number of controlled links is two. Early-break
gains differ: two access items for tailgating, one for shoulder surfing, three for dumpster diving.
The highest gain is dumpster diving, because its second step — collecting documents — drops three
items, and the control that breaks that step is not at a door but in the waste separation itself. If
the chain never breaks, dropped items reach seven.

The path table runs tailgating over the building and produces, once again, the same situation the
course has now seen twice: in two of eight paths, no link breaks at all. Both paths lead to the
archive, and dropped items are seven — the entire chain. In the remaining six paths, dropped items at
the earliest breakable link are either zero or two; that is, if a control exists it is early, and if
not it is absent entirely. No middle option appears.

Comparing the escort-procedure columns shows exactly where the procedure works. Nothing changes on six
paths, because those paths already have an early-breaking link. The two paths that change are the ones
that never broke at all: dropped items fall from seven to two, and the total gain is ten access items.
Everything the procedure gains sits on the two routes that previously had no control at all.

The cost is written on a single line: thirty-four escorted passages a day, an average of twelve minutes
per passage, 408 minutes total — 6.8 hours a day. This time is close to a full person's
workload and comes out of the escort's own work. Once it is known that the procedure gains something on
only two routes, a measurable alternative appears: instead of escorting, add a visual or single-person
passage control to the three uncontrolled doors on those two routes. Both gain the same ten items; one
is paid every day, the other once.

## Summary

- The building model has 10 doors, 5 card types, and 2 visual verification points. 3 doors have no
  control, 4 doors open with a card only; the number of doors that break tailgating is 3.
- 4 paths lead to the server room, and the breaking-door count ranges from 3 to 1. Of the 4 paths to
  the archive, 2 have a breaking-door count of 0.
- All three techniques have an uncontrolled first step. Early-break gain is 2 access items for
  tailgating, 1 for shoulder surfing, 3 for dumpster diving; if the chain never breaks, dropped items
  are 7, 5, and 7.
- Tailgating breaks on 6 of 8 paths and never breaks on 2. On the paths that break, dropped items at
  the earliest link are 0 or 2; no middle value appears.
- The escort procedure is effective only on those 2 paths: dropped items fall from 7 to 2, total gain
  10 access items. Gain on the other 6 paths is 0.
- The procedure costs 34 escorted passages a day × 12 minutes = 408 minutes (6.8 hours). The same 10
  items can also be gained by adding a control to the 3 uncontrolled doors on those 2 routes.

## Next Step

Every chain in this lesson required passing through a door, and every door was a countable item. An
impersonation carried out remotely needs no door at all: a domain one character away from a real name
faces no control the moment it is registered. **Producing** such names is not what is measurable;
**detecting** them is. The edit distance between protected names and candidate names can be computed,
and visually similar characters can be normalized. That is the next lesson's question: how many
impersonation candidates turn up in a registry feed, how many of them are false positives, and how many
days of a head start monitoring the registry gains before one goes into use.
