- Tell a security event from an incident
- Apply the six steps of incident response in order
- Analyse logs with Python to find suspicious activity
- Protect evidence with hashes and a chain of custody
Monday, 08:30. Leyla, an accountant, sees that her files have been renamed with a strange extension and a ransom note is sitting on the desktop. What happens in the first hour decides everything: panic — switching computers off, deleting files, paying in a hurry — destroys evidence and can make things worse. That is why incident response is a procedure prepared in advance.
An event is any observable occurrence in a system (one failed login). An incident is an event that violates security policy or threatens confidentiality, integrity or availability (an account takeover).
In the morning the on-duty analyst sees four alerts. Which are incidents, and which must be handled first?
1. One failed login to the director's account from Baku.
2. The antivirus quarantined a malicious attachment.
3. At 3 a.m. the accounting server sent 4 GB of data to an unknown external address.
4. The website's certificate expires in 20 days.
Show solutionHide solution
2. Event: the defence worked, logging it is enough.
3. Incident, priority 1: a large data transfer at night looks like theft (confidentiality) — isolate the server at once and investigate.
4. Not an incident but planned work: renew the certificate in time, or availability will suffer later.
The six steps of incident response
The classic NIST SP 800-61 model has four phases; SANS splits the same process into six steps. The steps below follow the SANS breakdown.
- 11. Preparation
A response plan, phone numbers of the people in charge, working backups, log collection and drills. What was not done before an attack cannot be done during it.
- 22. Identification
Check the alert: is it really an incident? Which systems are affected, and how serious is it? Record every step with its time.
- 33. Containment
Stop the spread: disconnect infected computers from the network, lock compromised accounts, block the attacker's addresses.
- 44. Eradication
Remove the malware, close the vulnerability that was used, and change all related passwords and keys.
- 55. Recovery
Restore systems from clean backups and watch them closely for a while: the attacker may try to come back.
- 66. Lessons learned
Hold a blameless review: what worked, what did not, what must change. Update the plan.
Logs: searching for traces
The main source of information is logs: authentication logs, firewall, DNS, antivirus and EDR records. In large organisations they are collected in a central SIEM system. All servers must share the same clock (NTP), otherwise the order of events cannot be reconstructed.
from collections import Counter
log = '''2026-03-14 02:10:01 LOGIN_FAIL user=admin ip=203.0.113.50
2026-03-14 02:10:03 LOGIN_FAIL user=admin ip=203.0.113.50
2026-03-14 02:10:04 LOGIN_FAIL user=root ip=203.0.113.50
2026-03-14 02:10:06 LOGIN_FAIL user=test ip=203.0.113.50
2026-03-14 02:10:09 LOGIN_FAIL user=admin ip=203.0.113.50
2026-03-14 02:11:40 LOGIN_OK user=admin ip=203.0.113.50
2026-03-14 08:55:12 LOGIN_FAIL user=leyla ip=10.0.0.23
2026-03-14 08:55:30 LOGIN_OK user=leyla ip=10.0.0.23'''
fails = Counter()
for line in log.splitlines():
if 'LOGIN_FAIL' in line:
fails[line.split('ip=')[1]] += 1
for ip, count in fails.most_common():
alert = '<- investigate' if count >= 5 else ''
print(ip.ljust(13), count, alert)▸ Expected output
203.0.113.50 5 <- investigate 10.0.0.23 1
admin login at 02:11:40 — the password was guessed. Leyla mistyping once in the morning is just an ordinary event.Digital forensics basics
Digital forensics establishes what happened in a way that also holds up in court. The core rules: do not touch the original, make a full copy (image) of the disk through a write blocker and work on the copy; compute hashes of the original and the copy; record who handed the evidence to whom, when and where in the chain of custody.
import hashlib
original = b'disk image of the office laptop ... 500 GB of bytes ...'
working_copy = bytes(original)
changed_copy = original.replace(b'500', b'501')
h = lambda data: hashlib.sha256(data).hexdigest()[:16]
print('original:', h(original))
print('copy: ', h(working_copy), h(working_copy) == h(original))
print('changed: ', h(changed_copy), h(changed_copy) == h(original))▸ Expected output
original: c402ab9b8b43db4f copy: c402ab9b8b43db4f True changed: 86ba2750b9c53f21 False
| Source (in order of volatility) | How long it lasts |
|---|---|
| CPU registers and cache | nanoseconds |
| RAM, processes, network connections | until power-off |
| Temporary files | minutes to hours |
| Disk | months to years |
| Logs on remote servers | per the retention policy |
| Backups and archives | years |
Events from different sources arrive in mixed order. Sort them by time and print each as time source text, padding the source to 8 characters with ljust(8). Read the story of the attack from the timeline.
events = [
('2026-03-14 02:11:40', 'auth', 'admin logged in from 203.0.113.50'),
('2026-03-14 02:10:01', 'auth', 'first failed login for admin'),
('2026-03-14 02:14:05', 'firewall', 'outbound connection to 198.51.100.77:443'),
('2026-03-14 02:12:30', 'server', 'new user backup_svc created'),
]
# print the events in time order: time, source (8 chars), text▸ Expected output
2026-03-14 02:10:01 auth first failed login for admin 2026-03-14 02:11:40 auth admin logged in from 203.0.113.50 2026-03-14 02:12:30 server new user backup_svc created 2026-03-14 02:14:05 firewall outbound connection to 198.51.100.77:443
Key points
- Every incident is an event, but not every event is an incident.
- Six steps: preparation, identification, containment, eradication, recovery, lessons learned.
- A suspicious computer is usually isolated from the network, not switched off.
- Forensics works on copies, compares hashes of the original and the copy and keeps a chain of custody.
- Evidence is collected in order of volatility: memory first, then disk.
Check yourself
10 questions. Every correct answer earns XP.