---
title: 'Fundamentals of Social Engineering'
source: 'https://academia.sh/en/courses/attack-techniques/fundamentals-of-social-engineering'
course: 'Attack Techniques and the Threat Landscape'
language: en
updated: '2026-09-26T03:02:49+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bounds the verification items available at decision time by a time budget and computes how many items can be used'
    - "Maps the chain's six steps to their preconditions and counts the step with no control"
---

# Fundamentals of Social Engineering

Modeling the moment of decision as a time budget: how many of seven verification items can be used under pressure, how many of twelve requests are fake and pass anyway, how many of six chain links carry a control, and the requests a callback procedure stops versus the legitimate work it delays.

The previous topic modeled an attack as a sequence of steps and tried to place a control against
each one. In that model the first link in the chain was always technical: an unrecorded account, an
open port, an unmonitored connection. This topic asks a different question. When the first link in
the chain is a decision made by a person, what can be placed against that decision, and how much of
it?

Verifying a request takes time, and every verification item has its own cost. Time pressure is
therefore not a matter of style but a measurable constraint: as the seconds left to the
decision-maker shrink, the number of verification items available shrinks with them. Trust is
measured the same way — an unverifiable internal detail is a shortcut that stands in for an item.
This lesson reduces both factors to a single number, the **count of usable items**, and counts the
link at which the chain breaks. Attempting the steps modeled here outside written authorization and
a defined scope is both illegal and unprofessional.

- **SE1.** The request set, verification items, and their durations belong to the subscriber
  services desk of the fictional regional measurement network. No real request is processed; what is
  measured is the model built with `node`.
- **SE2.** Every verification item has a fixed duration. In reality duration varies by person and by
  current load; a fixed duration preserves the items' ranking from cheap to expensive, and that
  ranking is what the measure rests on.
- **SE3.** The decision-maker applies items from cheapest to most expensive. This is the **most
  optimistic** assumption; a real order is set by intuition and fits fewer items into the same
  budget.
- **SE4.** The request's true class is known in the model. In reality the class is known only after
  the fact; it is assumed known here so that fake requests that slip through and legitimate work
  that is delayed can be counted separately.
- **SE5.** An item either disqualifies a request or it does not. Partial suspicion, asking a second
  question, and putting a request on hold are not modeled.
- **SE6.** Time pressure is reduced to a single number: the seconds left for the decision. Factors
  such as authority, reciprocity, and embarrassment are not modeled separately; all of them are
  carried as the same number that shortens the budget.

## The Moment of Decision Is a Time Budget

The model has three parts. Verification items are listed with their durations; requests are given
with their class, type, the time budget left to them, and their amount; and each request carries the
items that can **disqualify** it. The list of disqualifying items is not a guess but the model's
definition: if that item is applied, the request stops; if not, it passes.

Request type is carried as a separate column because the scope of a procedure is drawn by type.
There are three types — access, payment, and record — and which type a procedure covers directly
determines which chain it breaks; the cost of the one type left out of scope is counted at the end of
the lesson.

```js
// decisions.mjs — verification items, request set, and decision chain; model
export const ITEM = { // name: cost of applying the item, in seconds
  'compare amount to threshold': 20, 'compare sender address to record': 40,
  'look up work order number in system': 60, 'find requester in authorization list': 90,
  'check past request record': 120, 'call back on recorded number': 180, 'request supervisor approval': 300,
};
const [A, S, W, L, H, C, P] = Object.keys(ITEM);
export const THRESHOLD = 2000; // fictional payment unit
// [request, class, type, pressure budget (s), amount, items that disqualify the request]
export const REQUEST = [
  ['password reset', 'fake', 'access', 60, 0, [C, L]],
  ['payment account change', 'fake', 'payment', 120, 4800, [C, H]],
  ['urgent payment approval', 'fake', 'payment', 30, 9500, [A, P, C]],
  ['field access outside work order', 'fake', 'access', 90, 0, [W, C]],
  ['subscriber record export', 'fake', 'record', 180, 0, [L, P]],
  ['planned maintenance temporary access', 'legitimate', 'access', 300, 0, []],
  ['new field worker account', 'legitimate', 'access', 600, 0, []],
  ['end-of-period invoice approval', 'legitimate', 'payment', 240, 12000, []],
  ['meter replacement payment', 'legitimate', 'payment', 120, 1500, []],
  ['printer setup at branch office', 'legitimate', 'record', 480, 0, []],
  ['subscriber dispute record lookup', 'legitimate', 'record', 90, 0, []],
  ['temporary authorization for outage crew', 'legitimate', 'access', 45, 0, []],
];
// chain steps: [step, precondition, control that sees the step, item dropped once the step completes]
export const CHAIN = [
  ['gathering task information', 'externally visible task list', null, 0],
  ['building the pretext', 'the name of an internal process', null, 0],
  ['making contact', 'a reachable channel', 'is the channel on record', 1],
  ['signaling trust', 'an unverifiable internal detail', 'is the detail checked against the record', 1],
  ['creating urgency', "the decision-maker's time budget", 'is the time budget fixed by procedure', 2],
  ['requesting the action', 'an authorized decision-maker', 'is callback mandatory', 5],
];
export function items(budget) { // verification items that fit the budget, cheapest to most expensive
  let t = 0; const chosen = [];
  for (const [name, s] of Object.entries(ITEM)) { if (t + s > budget) break; t += s; chosen.push(name); }
  return { chosen, time: t };
}
export const procedureScope = (t) => t[2] === 'access' || (t[2] === 'payment' && t[4] > THRESHOLD);
```

## How the Pressure Budget Cuts the Number of Items

```js
// run1.mjs — number of verification items usable under time pressure, and fake requests that pass
import { ITEM, REQUEST, items } from './decisions.mjs';

console.log(`${Object.keys(ITEM).length} verification items, total ${Object.values(ITEM).reduce((a, b) => a + b, 0)} s; ` +
  `${REQUEST.length} requests, ${REQUEST.filter((t) => t[1] === 'fake').length} fake\n`);
console.log(`${'request'.padEnd(39)} ${'class'.padStart(10)} ${'budget'.padStart(6)} ${'items'.padStart(5)} ${'result'.padStart(7)}`);
let passed = 0, stopped = 0;
for (const t of REQUEST) {
  const { chosen } = items(t[3]);
  const stoppedHere = t[5].some((k) => chosen.includes(k));
  if (t[1] === 'fake') { stoppedHere ? stopped++ : passed++; }
  console.log(`${t[0].padEnd(39)} ${t[1].padStart(10)} ${String(t[3]).padStart(6)} ${String(chosen.length).padStart(5)} ` +
    `${(t[1] === 'fake' ? (stoppedHere ? 'stopped' : 'passed') : 'passed').padStart(7)}`);
}
console.log(`\nusable items by pressure budget:`);
for (const b of [30, 60, 120, 180, 300, 600]) {
  const { chosen, time } = items(b);
  console.log(`  ${String(b).padStart(3)} s -> ${chosen.length}/${Object.keys(ITEM).length} items (${time} s), ` +
    `left out: ${Object.keys(ITEM).filter((k) => !chosen.includes(k)).length}`);
}
console.log(`\ndecision without a procedure: fake requests stopped ${stopped}, passed ${passed}`);
console.log(`fake requests that passed: ${REQUEST.filter((t) => t[1] === 'fake' && !t[5].some((k) => items(t[3]).chosen.includes(k))).map((t) => `${t[0]} (${t[3]} s)`).join('; ')}`);
```

```
7 verification items, total 810 s; 12 requests, 5 fake

request                                      class budget items  result
password reset                                fake     60     2  passed
payment account change                        fake    120     3  passed
urgent payment approval                       fake     30     1 stopped
field access outside work order               fake     90     2  passed
subscriber record export                      fake    180     3  passed
planned maintenance temporary access    legitimate    300     4  passed
new field worker account                legitimate    600     6  passed
end-of-period invoice approval          legitimate    240     4  passed
meter replacement payment               legitimate    120     3  passed
printer setup at branch office          legitimate    480     5  passed
subscriber dispute record lookup        legitimate     90     2  passed
temporary authorization for outage crew legitimate     45     1  passed

usable items by pressure budget:
   30 s -> 1/7 items (20 s), left out: 6
   60 s -> 2/7 items (60 s), left out: 5
  120 s -> 3/7 items (120 s), left out: 4
  180 s -> 3/7 items (120 s), left out: 4
  300 s -> 4/7 items (210 s), left out: 3
  600 s -> 6/7 items (510 s), left out: 1

decision without a procedure: fake requests stopped 1, passed 4
fake requests that passed: password reset (60 s); payment account change (120 s); field access outside work order (90 s); subscriber record export (180 s)
```

The lower table gives the lesson's first number. The desk holds seven verification items, and
applying all of them takes 810 seconds. In a thirty-second budget, only **one** of them can be used;
six are left out. Even in a hundred-and-eighty-second budget, only three items are usable; the two
most expensive items — the callback and the supervisor approval — only fit into a budget of six
hundred seconds. The number of items does not scale in proportion with the budget; it steps up: no
new item is added between one hundred twenty and one hundred eighty seconds, because the next item
costs ninety seconds and the running total reaches two hundred ten.

The upper table shows the consequence. Four of five fake requests pass, and what they share is that
their disqualifying items were left out: an item that would disqualify each fake request **exists**
in the model, but it does not fit into the budget the request was given. The one request that is
stopped is the one given the shortest budget — thirty seconds — and it is stopped by the cheapest
item. Comparing the amount to a threshold takes twenty seconds and flags a nine-thousand-five-hundred
unit payment on its own. This is the measure's first counterintuitive finding: raising the pressure
does not always help the chain, because a budget short enough on its own is conspicuous enough to
trigger even the cheapest item.

A decision made without a procedure therefore lets four fake requests through. What is measured is
not the decision-maker's carelessness but the shortness of the budget. The same person can apply six
items given six hundred seconds.

## The Chain, Its Links, and the Early-Break Gain

```js
// run2.mjs — chain steps, the breakable link, and the callback procedure's three columns
import { REQUEST, CHAIN, ITEM, items, procedureScope } from './decisions.mjs';

const CALLBACK = 'call back on recorded number';
let cum = 0; const cumul = CHAIN.map((a) => (cum += a[3]));
console.log(`${'#'.padStart(2)} ${'step'.padEnd(28)} ${'precondition'.padEnd(34)} ${'control'.padStart(7)} ${'cum. items'.padStart(10)}`);
CHAIN.forEach((a, i) => console.log(`${String(i + 1).padStart(2)} ${a[0].padEnd(28)} ${a[1].padEnd(34)} ` +
  `${(a[2] ? 'yes' : 'no').padStart(7)} ${String(cumul[i]).padStart(10)}`));
const breakable = CHAIN.map((a, i) => (a[2] ? i : -1)).filter((i) => i >= 0);
const early = breakable[0], late = breakable[breakable.length - 1];
console.log(`\nchain has ${CHAIN.length} steps; with a control ${breakable.length}, with no control at all ${CHAIN.length - breakable.length}`);
console.log(`earliest breakable link ${early + 1} -> items dropped by then ${early ? cumul[early - 1] : 0}`);
console.log(`latest breakable link  ${late + 1} -> items dropped by then ${cumul[late - 1]}`);
console.log(`items dropped if never broken ${cumul[CHAIN.length - 1]}; early-break gain ${cumul[late - 1] - (early ? cumul[early - 1] : 0)} items`);

console.log(`\ncallback procedure (${ITEM[CALLBACK]} s, type 'access' or above-threshold 'payment'):`);
let stopped = 0, slipped = 0, delayed = [], extraTime = 0;
for (const t of REQUEST) {
  const scope = procedureScope(t);
  const applied = items(t[3]).chosen.concat(scope ? [CALLBACK] : []);
  if (scope) extraTime += ITEM[CALLBACK];
  if (t[1] === 'fake') { t[5].some((k) => applied.includes(k)) ? stopped++ : slipped++; }
  else if (scope && t[3] < ITEM[CALLBACK]) delayed.push(`${t[0]} (${t[3]} s)`);
}
console.log(`  requests in scope ${REQUEST.filter(procedureScope).length}/${REQUEST.length}, added verification time ${extraTime} s`);
console.log(`  fake requests stopped ${stopped}/5, slipped through ${slipped}`);
console.log(`  slipped through: ${REQUEST.filter((t) => t[1] === 'fake' && !procedureScope(t) && !t[5].some((k) => items(t[3]).chosen.includes(k))).map((t) => `${t[0]} (type ${t[2]})`).join('; ')}`);
console.log(`  legitimate work delayed ${delayed.length}: ${delayed.join('; ')}`);
```

```
 # step                         precondition                       control cum. items
 1 gathering task information   externally visible task list            no          0
 2 building the pretext         the name of an internal process         no          0
 3 making contact               a reachable channel                    yes          1
 4 signaling trust              an unverifiable internal detail        yes          2
 5 creating urgency             the decision-maker's time budget       yes          4
 6 requesting the action        an authorized decision-maker           yes          9

chain has 6 steps; with a control 4, with no control at all 2
earliest breakable link 3 -> items dropped by then 0
latest breakable link  6 -> items dropped by then 4
items dropped if never broken 9; early-break gain 4 items

callback procedure (180 s, type 'access' or above-threshold 'payment'):
  requests in scope 8/12, added verification time 1440 s
  fake requests stopped 4/5, slipped through 1
  slipped through: subscriber record export (type record)
  legitimate work delayed 1: temporary authorization for outage crew (45 s)
```

The chain has six steps, and the first two carry no control at all. This is not because those steps
are harmless but because they sit outside the defense's field of view: a task list being visible from
the outside and the name of an internal process being known are preparation steps that never touch
any record. The chain's first two links are therefore **uncountable**, only narrowable.

The four breakable links begin at the third step, and at that point no item has dropped yet. Breaking
at the sixth step comes after four items have already dropped. The difference between the two is the
early-break gain: **four items**. If the chain never breaks, the count reaches nine, meaning that
letting the final step through costs five items on its own. Read together, these three numbers turn
where a defense should invest from an opinion into a ranking.

The callback procedure shows this across three columns. The procedure covers eight of the twelve
requests and stops four of the five fake ones; a decision without a procedure had stopped only one.
The one request that slips through falls outside scope: a record-type export request is neither
access nor an above-threshold payment, so the procedure never touches it. This is where the measure
shifts to detection rather than the chain breaking: for this request there is no link to break — the
request passes, but the export can still be counted afterward.

The cost is written in two items. Adding one hundred eighty seconds to each of eight requests
produces a total of 1,440 seconds of added verification. Exactly one piece of legitimate work is
delayed, and which one matters: the request for temporary authorization for the outage crew arrives
with a forty-five-second budget, the callback takes one hundred eighty seconds, and the work does not
fit inside the procedure. The only legitimate work the procedure delays is the most urgent one. This
is not a flaw but the unavoidable result of the procedure's design: any procedure that turns time
pressure into a control also routes genuinely urgent work through that same control.

## Summary

- All 7 verification items together take 810 seconds. A 30-second budget allows 1 item, a 180-second
  budget allows 3, a 600-second budget allows 6; the item count rises in steps, not in proportion to
  the budget.
- In a decision without a procedure, 4 of 5 fake requests pass. An item that would disqualify each
  one exists in the model, but it does not fit into the budget given; the one request stopped had the
  shortest budget, and the cheapest item stopped it.
- The chain has 6 steps; 4 carry a control, and the first 2 touch no record at all. These two links
  cannot be counted, only made harder by narrowing what is visible from outside.
- The earliest breakable link is step 3, where 0 items have dropped; breaking at step 6 means 4 items
  have already dropped. The early-break gain is 4 items, and the cost of never breaking the chain is
  9 items.
- The callback procedure covers 8 of 12 requests and stops 4 of 5 fake ones; the 1 request outside
  its scope breaks no link, and the measure shifts to detection.
- The procedure's cost is 1,440 seconds of added verification and 1 piece of delayed legitimate work
  — the most urgent request, whose budget is shorter than the procedure's own duration.

## Next Step

In this lesson a request was assumed to have already reached the decision-maker, and what was
measured was the decision itself. The chain's third link — making contact — was passed over in a
single line, yet the message that contact carries is itself a measurable object. What separates a
legitimate message from a fake one in a message set is not tone but countable indicators: a sender
never seen before, a reply address that diverges from the sender, a link target that differs from the
displayed text. The next lesson's question is this: how many distinguishing indicators can be counted
in a message set, how many fake messages does the chosen threshold miss, how many legitimate messages
does it flag by mistake — and why does the indicator count fall as the target narrows.
