Learn Ethical Hacking (#81) - Zero Trust Implementation - Beyond the Buzzword
Learn Ethical Hacking (#81) - Zero Trust Implementation - Beyond the Buzzword
What will I learn
- What zero trust actually means -- not a product you buy, but an architecture you build;
- The five pillars -- identity, device, network, application, and data verification;
- Identity-first security -- strong authentication as the new perimeter;
- Device trust -- how to verify device health before granting access;
- Micro-segmentation in practice -- implementing per-workload security policies;
- Software Defined Perimeter (SDP) -- making resources invisible to unauthorized users;
- Migration strategy -- moving from castle-and-moat to zero trust without breaking everything;
- Defense: implementing zero trust incrementally, measuring progress, and avoiding vendor hype.
Requirements
- A working modern computer running macOS, Windows or Ubuntu;
- Understanding of security architecture from Episode 53;
- Understanding of network security from Episode 73;
- The ambition to learn ethical hacking and security research.
Difficulty
- Intermediate/Advanced
Curriculum (of the Learn Ethical Hacking Series):
- Learn Ethical Hacking (#1) - Why Hackers Win
- Learn Ethical Hacking (#2) - Your Hacking Lab
- Learn Ethical Hacking (#3) - How the Internet Actually Works - For Attackers
- Learn Ethical Hacking (#4) - Reconnaissance - The Art of Not Being Noticed
- Learn Ethical Hacking (#5) - Active Scanning - Mapping the Attack Surface
- Learn Ethical Hacking (#6) - The AI Slop Epidemic - Why AI-Generated Code Is a Security Disaster
- Learn Ethical Hacking (#7) - Passwords - Why Humans Are the Weakest Cipher
- Learn Ethical Hacking (#8) - Social Engineering - Hacking the Human
- Learn Ethical Hacking (#9) - Cryptography for Hackers - What Protects Data (and What Doesn't)
- Learn Ethical Hacking (#10) - The Vulnerability Lifecycle - From Discovery to Patch to Exploit
- Learn Ethical Hacking (#11) - HTTP Deep Dive - Request Smuggling and Header Injection
- Learn Ethical Hacking (#12) - SQL Injection - The Bug That Won't Die
- Learn Ethical Hacking (#13) - SQL Injection Advanced - Extracting Entire Databases
- Learn Ethical Hacking (#14) - Cross-Site Scripting (XSS) - Injecting Code Into Browsers
- Learn Ethical Hacking (#15) - XSS Advanced - Bypassing Filters and CSP
- Learn Ethical Hacking (#16) - Cross-Site Request Forgery - Making Users Attack Themselves
- Learn Ethical Hacking (#17) - Authentication Bypass - Getting In Without a Password
- Learn Ethical Hacking (#18) - Server-Side Request Forgery - Making Servers Betray Themselves
- Learn Ethical Hacking (#19) - Insecure Deserialization - Code Execution via Data
- Learn Ethical Hacking (#20) - File Upload Vulnerabilities - When Users Upload Weapons
- Learn Ethical Hacking (#21) - API Security - The New Attack Surface
- Learn Ethical Hacking (#22) - Business Logic Flaws - When the Code Works But the Logic Doesn't
- Learn Ethical Hacking (#23) - Client-Side Attacks - Beyond XSS
- Learn Ethical Hacking (#24) - Content Management Systems - Hacking WordPress and Friends
- Learn Ethical Hacking (#25) - Web Application Firewalls - Bypassing the Guards
- Learn Ethical Hacking (#26) - The Full Web Pentest - Methodology and Reporting
- Learn Ethical Hacking (#27) - Bug Bounty Hunting - Getting Paid to Hack the Web
- Learn Ethical Hacking (#28) - The AI Web Attack Surface - AI Features as Vulnerabilities
- Learn Ethical Hacking (#29) - Network Sniffing - Seeing Everything on the Wire
- Learn Ethical Hacking (#30) - Wireless Network Attacks - Breaking Wi-Fi
- Learn Ethical Hacking (#31) - Privilege Escalation - Linux
- Learn Ethical Hacking (#32) - Privilege Escalation - Windows
- Learn Ethical Hacking (#33) - Active Directory Attacks - The Crown Jewels
- Learn Ethical Hacking (#34) - Pivoting and Lateral Movement - Spreading Through Networks
- Learn Ethical Hacking (#35) - Cloud Security - AWS Attack and Defense
- Learn Ethical Hacking (#36) - Cloud Security - Azure and GCP
- Learn Ethical Hacking (#37) - Container Security - Docker and Kubernetes Attacks
- Learn Ethical Hacking (#38) - Infrastructure as Code - Securing the Automation
- Learn Ethical Hacking (#39) - Email Security - Phishing Infrastructure and Defense
- Learn Ethical Hacking (#40) - DNS Attacks - Exploiting the Internet's Foundation
- Learn Ethical Hacking (#41) - Exploitation Frameworks - Metasploit and Cobalt Strike
- Learn Ethical Hacking (#42) - Custom Exploit Development - Writing Your Own
- Learn Ethical Hacking (#43) - Exploit Development Advanced - Modern Mitigations and Bypasses
- Learn Ethical Hacking (#44) - Reverse Engineering - Understanding Binaries
- Learn Ethical Hacking (#45) - Supply Chain Attacks - Poisoning the Source
- Learn Ethical Hacking (#46) - The Human Factor - Why Security Training Fails
- Learn Ethical Hacking (#47) - Physical Security and OSINT - The Forgotten Attack Vectors
- Learn Ethical Hacking (#48) - Insider Threats - When the Call Is Coming from Inside the House
- Learn Ethical Hacking (#49) - Deepfakes and AI Deception - The New Social Engineering
- Learn Ethical Hacking (#50) - Red Team Operations - Simulating Real Attacks
- Learn Ethical Hacking (#51) - Incident Response - When Things Go Wrong
- Learn Ethical Hacking (#52) - Threat Intelligence - Knowing Your Enemy
- Learn Ethical Hacking (#53) - Security Architecture - Designing Systems That Resist Attack
- Learn Ethical Hacking (#54) - Compliance and Governance - The Business of Security
- Learn Ethical Hacking (#55) - Privacy and Data Protection - GDPR, CCPA, and Beyond
- Learn Ethical Hacking (#56) - Cryptocurrency Security - Attacking and Defending Digital Assets
- Learn Ethical Hacking (#57) - IoT and Embedded Security - Hacking the Physical World
- Learn Ethical Hacking (#58) - The AI Security Landscape - Attacking and Defending AI Systems
- Learn Ethical Hacking (#59) - Python for Pentesters - Automating Everything
- Learn Ethical Hacking (#60) - Zig for Security Tools - When Speed and Memory Matter
- Learn Ethical Hacking (#61) - Writing Custom Scanners - Beyond Off-the-Shelf
- Learn Ethical Hacking (#62) - C2 Frameworks - Building Command and Control
- Learn Ethical Hacking (#63) - Payload Generation and Evasion - Defeating Antivirus
- Learn Ethical Hacking (#64) - Fuzzing - Finding Bugs at Machine Speed
- Learn Ethical Hacking (#65) - OSINT Automation - Large-Scale Intelligence Gathering
- Learn Ethical Hacking (#66) - Reporting and Documentation - The Professional Difference
- Learn Ethical Hacking (#67) - Continuous Security - DevSecOps and Pipeline Security
- Learn Ethical Hacking (#68) - Wireless and Bluetooth Exploitation Deep Dive
- Learn Ethical Hacking (#69) - Mobile Application Security - Android and iOS
- Learn Ethical Hacking (#70) - Building a Pentesting Practice - Going Professional
- Learn Ethical Hacking (#71) - Hardening Linux - From Default to Fortress
- Learn Ethical Hacking (#72) - Hardening Windows and Active Directory
- Learn Ethical Hacking (#73) - Network Security Architecture - Defending the Wire
- Learn Ethical Hacking (#74) - Security Monitoring and SIEM - Seeing Everything
- Learn Ethical Hacking (#75) - Threat Hunting - Proactive Detection
- Learn Ethical Hacking (#76) - Digital Forensics Deep Dive - Evidence That Holds Up
- Learn Ethical Hacking (#77) - Malware Analysis - Understanding the Threat
- Learn Ethical Hacking (#78) - Secure Development - Writing Code That Doesn't Get Hacked
- Learn Ethical Hacking (#79) - Securing AI Systems in Production
- Learn Ethical Hacking (#80) - Security Automation - Orchestrating Defense
- Learn Ethical Hacking (#81) - Zero Trust Implementation - Beyond the Buzzword (this post)
Learn Ethical Hacking (#81) - Zero Trust Implementation - Beyond the Buzzword
Solutions to Episode 80 Exercises
Exercise 1: Automated IP blocking script (abbreviated).
import re, time, subprocess
from collections import defaultdict
THRESHOLD = 10
WINDOW = 300 # 5 minutes
blocked = set()
failures = defaultdict(list)
def monitor_auth_log():
with open('/var/log/auth.log') as f:
f.seek(0, 2) # seek to end
while True:
line = f.readline()
if not line:
time.sleep(1)
continue
match = re.search(
r'Failed password.*from (\d+\.\d+\.\d+\.\d+)', line
)
if match:
ip = match.group(1)
now = time.time()
failures[ip] = [
t for t in failures[ip] if now - t < WINDOW
]
failures[ip].append(now)
if len(failures[ip]) >= THRESHOLD and ip not in blocked:
subprocess.run([
'nft', 'add', 'rule', 'inet', 'filter',
'input', 'ip', 'saddr', ip, 'drop'
])
blocked.add(ip)
print(f"BLOCKED: {ip} ({len(failures[ip])} failures)")
The script tails /var/log/auth.log using a seek-to-end approach (the same technique that tail -f uses internally) and watches for failed SSH password lines. The sliding window implementation using list comprehension -- filtering timestamps within the last 300 seconds -- is simple but effective. Every time a new failure arrives for an IP, all entries older than 5 minutes are purged, so the counter naturally decays over time without needing a separate cleanup thread.
The comparison against fail2ban is where the educational value lives. Fail2ban provides everything this script does NOT: configurable ban expiry (our script blocks forever until reboot or manual unblock), multi-service support (fail2ban watches SSH, HTTP, FTP, mail, and any service with a log file), email notifications, regex flexibility through jail configuration, and a well-tested codebase maintained since 2004. What our script has that fail2ban does not: transparency. You can read every line and understand exactly what it does in 30 seconds. Fail2ban's codebase is thousands of lines with complex configuration layering that takes significant effort to audit. For production use fail2ban. For understanding the mechanics of automated blocking, write your own first.
Exercise 2: TI ingestion pipeline (abbreviated).
Feed results (hourly run):
EmergingThreats compromised IPs: 1,247
URLhaus recent URLs: 892
Feodo Tracker botnet C2s: 614
Total after dedup: 2,491 unique IOCs
Overlap: 262 IOCs appeared in 2+ feeds (10.5%)
Output: consolidated blocklist written to /opt/security/blocklists/
Cron: 0 * * * * python3 /opt/security/ti_ingest.py
The 10.5% overlap between feeds is an interesting metric to track over time because it tells you something about the threat intelligence ecosystem. A high overlap means the feeds are largely redundant -- they are all drawing from the same underlying sources or sharing data. A low overlap means each feed provides genuinely unique intelligence. In practice, 10% overlap is typical for free public feeds, and it rises to 30-50% when you add commercial feeds that aggregate from the same upstream providers. The deduplication step (using Python sets, as we implemented in episode 80) is not just an optimization -- it prevents your firewall from processing duplicate block rules, which matters at scale when you are pushing thousands of IOCs per hour.
Exercise 3: Phishing SOAR playbook (abbreviated).
TRIGGER: user reports phishing email via "Report Phish" button
1. EXTRACT IOCs from email:
sender_address, reply_to, return_path, embedded_URLs,
attachment_hashes (SHA-256)
2. ENRICH: query VirusTotal, URLhaus, AbuseIPDB for each IOC
IF any IOC is confirmed malicious -> proceed to step 3
IF no IOC is known -> create low-priority ticket for analyst
3. SEARCH email gateway: find all recipients of same message
(match on: sender + subject + attachment hash)
4. QUARANTINE: remove email from all inboxes
IF attachment was opened by any user -> proceed to step 5
IF not opened -> skip to step 6
5. ISOLATE: quarantine endpoint via EDR API
NOTIFY user: "Your computer has been isolated due to a
security incident. IT will contact you within 1 hour."
6. CREATE incident ticket with:
all IOCs, affected users, quarantine status, timeline
7. NOTIFY SOC channel + affected users' managers
The three decision branches in this playbook are what make it more than a simple linear script. The first branch (step 2: IOC confirmed malicious vs unknown) determines the urgency of the response -- a known-malicious IOC triggers immediate quarantine, while an unknown IOC creates a ticket for human review. This prevents the automation from aggressively quarantining emails that contain URLs that VirusTotal simply has not scanned yet (which happens constantly with fresh phishing campaigns). The second branch (step 4: attachment opened vs not opened) determines whether endpoint isolation is needed -- quarantining the email is sufficient if nobody interacted with it, but if someone opened a malicious attachment, their machine is potentially compromised and must be isolated from the network using the same EDR API isolation technique we discussed in episode 80's malware response playbook. The third implicit branch is the match criteria in step 3: searching by sender + subject + attachment hash ensures you find all copies of the phishing email, not just the one that was reported. A phishing campaign typically hits dozens or hundreds of mailboxes simultaneously, and quarantining only the reported copy leaves the rest sitting in other users' inboxes waiting to be clicked.
Episode 80 covered security automation -- the orchestration layer that connects your detection tools (SIEM, EDR, threat intelligence) with your response capabilities (firewall blocking, host isolation, ticket creation) through pre-defined playbooks. We looked at SOAR platforms, automated incident response, and the critical boundary between what should be automated (repetitive, time-sensitive, well-defined actions) and what requires human judgment (ambiguous situations, high-impact decisions, novel attack patterns). That episode answered the question "how do we respond faster than humans can work?"
Today we address a more fundamental question: what if we stopped trusting anything by default? Every defense we have built in this series -- firewalls, network segmentation (episode 73), SIEM monitoring (episode 74), hardening (episodes 71-72) -- operates within a model that assumes some things are trusted. If you are on the corporate network, you can reach internal services. If you authenticated at login, your session is valid until it expires. If the device is a company laptop, it is probably safe. Zero trust challenges every single one of those assumptions, and the organizations that have implemented it properly are dramatically harder to breach than those that have not.
Zero Trust -- The Architecture, Not the Product
Here we go. Every security vendor on the planet sells "zero trust." Palo Alto, Zscaler, Microsoft, CrowdStrike, Cisco -- they all have a "zero trust" product line. They are all selling you a component of zero trust. None of them IS zero trust. Zero trust is not a product you buy. It is an architectural philosophy: never trust, always verify. Every access request -- regardless of where it comes from, what network it is on, what device it is using -- must be authenticated, authorized, and encrypted before access is granted.
The traditional model (which most organizations still run) is the castle-and-moat architecture: a thick perimeter (firewall + VPN) protects a soft interior. Once you are "inside" the network -- VPN connected, office Ethernet, corporate WiFi -- you are trusted. This model died the day remote work became normal, cloud migration moved applications outside the perimeter, and attackers demonstrated (repeatedly) that breaching the perimeter gives them unlimited lateral movement through the soft interior. We covered exactly those lateral movement techniques in episode 34 -- PsExec, WMI, pass-the-hash, Kerberoasting -- and every one of them works because the internal network trusts authenticated sessions implicitly.
Zero trust replaces implicit trust ("you are on the network, therefore you are trusted") with explicit verification ("prove who you are, prove your device is healthy, prove you need access to THIS specific resource, for THIS specific session, RIGHT NOW"). The perimeter does not disappear -- it moves from the network edge to every individual resource. Instead of one big wall around everything, you have a tiny wall around each application, each database, each service. An attacker who compromises one user's laptop and authenticates to one application cannot automatically reach anything else.
The Five Pillars
NIST SP 800-207 defines zero trust architecture around five pillars. Think of these as the five questions that must be answered before ANY access is granted:
1. IDENTITY -- Who is requesting access?
- Strong authentication (MFA, passwordless, FIDO2)
- Continuous verification (not just at login -- throughout session)
- Risk-based decisions (login from new country? extra verification)
2. DEVICE -- Is the device trustworthy?
- Managed and enrolled in MDM/endpoint management?
- OS patched and up to date?
- Disk encryption enabled?
- EDR running and reporting healthy?
3. NETWORK -- How is the connection secured?
- Encrypt ALL traffic (even internal east-west)
- Micro-segmentation (no flat networks)
- No implicit trust for any network location
4. APPLICATION -- Is the access appropriate?
- Per-application access policies (not per-network)
- Just-in-time access (temporary, not permanent)
- API-level authorization checks
5. DATA -- Is the data protected regardless of location?
- Classification and labeling
- Encryption at rest and in transit
- DLP controls (prevent unauthorized data movement)
- Access logged and auditable
The critical insight is that these pillars are NOT independent -- they work together to create a composite trust decision. A request from a known user (identity: strong) on an unmanaged device (device: weak) from an unusual location (network: suspicious) to a sensitive application (application: high value) accessing classified data (data: critical) should be treated very differently from the same user on their enrolled laptop from the office accessing a non-sensitive internal wiki. The access decision is a function of ALL five pillars simultaneously, not any one of them in isolation. This is what the industry calls Conditional Access -- and it is the engine at the heart of any real zero trust implementation.
Identity-First Security
In zero trust, identity IS the perimeter. The firewall used to decide access based on IP address. In zero trust, the identity provider decides access based on WHO you are, WHAT you are trying to access, WHERE you are accessing from, WHEN you are accessing it, and HOW your device is configured. Here is what a Conditional Access policy engine looks like in code:
#!/usr/bin/env python3
"""conditional_access.py -- zero trust access decision engine"""
class AccessDecision:
ALLOW = "allow"
DENY = "deny"
MFA_REQUIRED = "mfa_required"
STEP_UP = "step_up"
def evaluate_access(request):
"""Evaluate access request against zero trust policies.
Returns (decision, reason)."""
user = request['user']
device = request['device']
resource = request['resource']
context = request['context']
# Rule 1: compromised device = immediate deny
if device.get('edr_status') == 'compromised':
return (AccessDecision.DENY,
"Device flagged as compromised by EDR")
# Rule 2: admin access requires managed device + MFA
if user.get('role') == 'admin':
if not device.get('managed'):
return (AccessDecision.DENY,
"Admin access requires managed device")
if not request.get('mfa_verified'):
return (AccessDecision.MFA_REQUIRED,
"Admin access requires MFA")
# Rule 3: new location = step-up authentication
if context.get('location_risk') == 'high':
if not request.get('step_up_verified'):
return (AccessDecision.STEP_UP,
"Unusual location detected -- verify identity")
# Rule 4: unmanaged device = limited access
if not device.get('managed'):
if resource.get('sensitivity') in ('high', 'critical'):
return (AccessDecision.DENY,
"Sensitive resources require managed device")
return (AccessDecision.ALLOW,
"Unmanaged device -- web apps only")
# Rule 5: sensitive resource = require recent MFA
if resource.get('sensitivity') == 'critical':
mfa_age = context.get('mfa_age_seconds', 9999)
if mfa_age > 300: # 5 minutes
return (AccessDecision.MFA_REQUIRED,
"Critical resource -- re-authenticate")
return (AccessDecision.ALLOW, "All checks passed")
The rule ordering matters enormously and is a source of subtle bugs in real Conditional Access deployments. Rule 1 (compromised device) runs first because it is the most critical -- a compromised device should NEVER get access regardless of who the user is or what they are trying to reach. If you put the admin-access rule first and the admin's device is compromised, a poorly ordered policy might grant access to the admin before checking the device state. This is the same principle as firewall rule ordering from episode 73 -- the most restrictive, most critical rules evaluate first.
The mfa_age_seconds check in Rule 5 implements continuous verification, which is one of the key differences between zero trust and traditional authentication. In the castle-and-moat model, you authenticate once when you connect to the VPN, and then your session is valid for 8 hours. In zero trust, accessing a critical resource requires that your MFA was verified within the last 5 minutes -- not 8 hours ago when you logged in. This means an attacker who steals a session token (the techniques from episode 17) gets a token that only works for non-critical resources, and any attempt to access critical resources triggers a fresh MFA challenge that the attacker cannot satisfy without the user's physical authentication device ;-)
Device Trust and Compliance
The identity pillar answers "who are you?" The device pillar answers "is your machine safe to connect?" In a zero trust architecture, BOTH must be verified before access is granted:
def check_device_compliance(device_info):
"""Evaluate device health against compliance policy.
Returns (compliant: bool, issues: list, risk_level: str)."""
issues = []
# OS version check
os_ver = device_info.get('os_version', '')
min_versions = {
'windows': '10.0.22621', # Windows 11 22H2
'macos': '14.0', # Sonoma
'ubuntu': '22.04',
}
os_type = device_info.get('os_type', '').lower()
if os_type in min_versions:
if os_ver < min_versions[os_type]:
issues.append(f"OS version {os_ver} below minimum "
f"{min_versions[os_type]}")
# Disk encryption
if not device_info.get('disk_encrypted'):
issues.append("Disk encryption not enabled")
# EDR status
edr = device_info.get('edr_status', 'unknown')
if edr == 'not_installed':
issues.append("EDR agent not installed")
elif edr == 'outdated':
issues.append("EDR signatures outdated")
# Patch status
days_since_patch = device_info.get('days_since_last_patch', 999)
if days_since_patch > 14:
issues.append(f"Last patched {days_since_patch} days ago "
f"(max 14)")
# Firewall
if not device_info.get('firewall_enabled'):
issues.append("Host firewall disabled")
# Risk scoring
if len(issues) == 0:
return True, [], 'low'
elif len(issues) <= 2:
return False, issues, 'medium'
else:
return False, issues, 'high'
The 14-day patch window is a pragmatic compromise. Security teams want patches applied immediately. Operations teams know that immediate patching breaks things -- patches have bugs, applications have compatibility issues, and forced reboots during business hours cause productivity loss. 14 days gives enough time for "patch Tuesday" updates to be tested and deployed through normal change management (which connects to the compliance frameworks from episode 54), while being short enough that critical vulnerabilities do not sit unpatched for months. Some organizations use a tiered approach: 48 hours for critical CVEs with known active exploitation, 14 days for high-severity patches, 30 days for everything else. The automated compliance checking from this code can enforce these timelines without manual follow-up.
Having said that, the compliance check is only as good as the data it receives. If the MDM agent on the device reports "disk encryption enabled" but the user has actually disabled BitLocker through a local admin workaround, the compliance engine has no way to know. This is why zero trust architectures typically combine MDM compliance data with EDR telemetry (which independently monitors the endpoint's security posture) and occasional posture re-assessment during active sessions. Trust the data, but verify the data source.
Micro-segmentation in Practice
Network segmentation is not new -- we covered VLANs and firewall zones in episode 73. What IS new in zero trust is the granularity. Traditional segmentation puts broad categories in separate zones: servers here, workstations there, DMZ in front. Micro-segmentation puts individual workloads in their own security boundary. Every application, every service, every database has its own access policy:
Traditional segmentation:
[Internet] --> [DMZ: web servers] --> [Internal: everything else]
Attacker breaches one web server -> can reach ALL internal systems
Micro-segmentation:
[Internet] --> [Web App A] --policy--> [API Server A] --policy--> [DB A]
[Web App B] --policy--> [API Server B] --policy--> [DB B]
Attacker breaches Web App A -> can ONLY reach API Server A
Cannot reach Web App B, API Server B, DB B, or anything else
Implementation tools:
- VMware NSX (virtual firewalls between VMs)
- Illumio (application-level segmentation)
- Calico (Kubernetes network policies)
- AWS Security Groups (per-instance firewall rules)
- Azure NSGs (network security groups per subnet/NIC)
Kubernetes example (Calico network policy):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-server-policy
spec:
podSelector:
matchLabels:
app: api-server
ingress:
- from:
- podSelector:
matchLabels:
app: web-frontend
ports:
- port: 8080
# Result: ONLY pods labeled "web-frontend" can reach
# the api-server on port 8080. Everything else is denied.
The Kubernetes NetworkPolicy example demonstrates micro-segmentation at its most granular. Without this policy, every pod in the cluster can communicate with every other pod -- Kubernetes networking is flat by default (just like a traditional LAN). With the policy applied, the api-server pod ONLY accepts connections from pods labeled web-frontend on port 8080. An attacker who compromises a different pod in the same cluster -- say, a logging service or a monitoring agent -- cannot reach the api-server at all. The connection attempt is dropped at the network level before it even reaches the application. This is the container-native equivalent of the network firewall rules from episode 73, but applied at the individual workload level instead of the network segment level.
The practical challenge with micro-segmentation is not the technology -- it is the policy management. A medium-sized organization might have 500 services communicating with each other. Defining per-service access policies for 500 services means understanding and codifying every legitimate communication path. Miss one legitimate path and you break a production workflow. Allow one unnecessary path and you leave an attack vector open. The standard approach is to start in learning mode (observe all traffic flows for 2-4 weeks, build a map of what communicates with what) and then switch to enforcement mode (block everything that was not observed during the learning period). This is the same concept as behavioral baselining from episode 75's threat hunting -- you define "normal" by observation, and then alert on deviations.
Software Defined Perimeter
SDP takes micro-segmentation one step further: instead of just restricting which traffic is allowed between services, it makes unauthorized services completely invisible. In a traditional network, even with segmentation, an attacker can scan and discover what services exist (the reconnaissance techniques from episode 5 work against segmented networks -- the firewall drops the connection, but the scan reveals that SOMETHING is there). With SDP, unauthorized users cannot even see the service. No port response, no banner, no DNS resolution. The service simply does not exist from their perspective.
Traditional access:
1. User connects to corporate VPN
2. ALL internal services are reachable (even if firewalled)
3. Attacker scans: discovers 500+ services, attacks the weakest
SDP access:
1. User authenticates to SDP controller (MFA + device check)
2. Controller verifies: identity, device posture, authorization
3. Controller creates micro-tunnel to ONLY the authorized resource
4. User accesses ONE specific resource through the tunnel
5. ALL other resources remain invisible -- no scan response
Think of it as a bouncer at a nightclub who checks your ID
and then teleports you directly to your reserved table.
You never see the other rooms, you never walk through the
hallway, you cannot wander into the kitchen. The only thing
that exists for you is your table and the path to it.
Tools:
- Zscaler Private Access (ZPA)
- Cloudflare Access (free tier for small deployments)
- Google BeyondCorp Enterprise
- Tailscale / WireGuard (simpler SDP-like functionality)
- Open source: OpenZiti, Fyde
The VPN comparison is particuarly telling. A VPN (Virtual Private Network) was the original "remote access" solution, and it works by placing the remote user's machine on the corporate network. Once connected, the user is "inside" and can reach everything that the internal network can reach -- which is exactly the implicit trust model that zero trust rejects. SDP replaces the VPN with per-application tunnels that grant access to one resource at a time. An attacker who compromises the user's machine after SDP authentication gets access to whatever application the user was connected to -- but ONLY that application. They cannot scan the network, they cannot discover other services, they cannot move laterally. The blast radius of a compromise is dramatically reduced.
Tailscale and WireGuard deserve mention as the pragmatic middle ground. Full enterprise SDP solutions (Zscaler, Cloudflare) are powerful but expensive and complex to deploy. Tailscale builds a mesh VPN where each device gets its own identity and access to specific services is controlled through ACLs (access control lists). It is not full SDP -- the services are technically reachable within the mesh, not hidden -- but it implements the identity-based access control and per-resource policies that matter most. For small and medium organizations that cannot justify the cost of enterprise SDP, Tailscale provides 80% of the security benefit at 10% of the complexity.
Migration Strategy -- How to Get There
You cannot switch to zero trust overnight. Every organization that tries to do a "big bang" migration breaks production, rolls back, and blames zero trust for being impractical. The correct approach is incremental migration, one application at a time, proving the model works before expanding:
Phase 1: Identity foundation (month 1-3)
- Deploy identity provider with MFA for ALL users
- Implement SSO for all applications that support it
- Inventory all applications and who accesses them
- Map data flows between systems
- Identify the 5 most critical applications
Phase 2: Protect the crown jewels (month 3-6)
- Move the 5 critical applications behind identity proxy
- Implement Conditional Access policies
- Deploy device compliance checking (MDM enrollment)
- Keep VPN as fallback for unmigrated applications
Phase 3: Expand and segment (month 6-12)
- Migrate remaining applications to identity-based access
- Implement micro-segmentation between workloads
- Deploy SDP for server-to-server communication
- Begin decommissioning VPN for migrated applications
Phase 4: Continuous improvement (ongoing)
- Measure: percentage of access verified (target: 100%)
- Reduce: implicit trust grants remaining
- Monitor: access patterns for anomalies (UEBA from ep 74)
- Iterate: refine policies, reduce exceptions
- The VPN does not need to die on day one
The Phase 1 identity foundation is where most of the value is, and it is also the least disruptive phase. Deploying MFA and SSO does not change how the network works -- it adds a verification layer on top of existing access. Users still connect to the same applications the same way, but now they prove their identity with a second factor. This single change blocks the vast majority of credential-based attacks we covered in episodes 7 (password attacks), 8 (social engineering), and 17 (authentication bypass). A phishing attack that steals a user's password (episode 39) no longer leads to account compromise if MFA is required. The ROI on Phase 1 alone is enormous -- Google reported that deploying FIDO2 security keys eliminated 100% of phishing-based account takeovers against their employees. ONE HUNDRED PERCENT.
Phase 2 is where the architectural shift begins, and it is crucial to start with the crown jewels -- the 5 most critical applications. These are the applications where a breach causes the most damage: the financial system, the customer database, the source code repository, the HR system, the admin console. Moving these behind an identity proxy (Cloudflare Access, Azure AD Application Proxy, or similar) means access is no longer determined by "are you on the VPN" but by "are you the right person, on the right device, from the right location, accessing the right resource." The VPN stays running as a fallback for the other 95 applications, and you migrate them gradually in Phase 3. No disruption, no big bang, no rollback.
Measuring Zero Trust Maturity
The CISA Zero Trust Maturity Model provides a concrete framework for assessing where your organization is and where it needs to go:
CISA Zero Trust Maturity Model:
Traditional (where most organizations are):
- Perimeter-based security (firewall + VPN)
- Static network controls
- Passwords without MFA
- Manual provisioning and deprovisioning
Initial:
- MFA deployed for some applications
- Some cloud-based identity provider usage
- Basic device management
- Limited visibility into access patterns
Advanced:
- MFA on all applications (phishing-resistant preferred)
- Conditional Access policies based on risk
- Device compliance as access requirement
- Micro-segmentation for critical workloads
- Centralized logging and monitoring
Optimal:
- Continuous verification throughout sessions
- Dynamic policy adjustment based on real-time risk
- Full micro-segmentation including east-west traffic
- Automated response to trust violations
- Data-level protections regardless of location
Most organizations today are somewhere between Traditional and Initial. They have MFA on their email (because Microsoft nags them about it) but not on their internal applications. They have a VPN but no device compliance checking. They have a firewall but no micro-segmentation. Getting from Traditional to Advanced takes 1-2 years of focused effort and deliberate investment. Getting to Optimal is aspirational for all but the most mature organizations (Google's BeyondCorp is the canonical example, and they have been building it since 2011).
I argue that the maturity model is most useful as a communication tool for talking to leadership. "We need to implement zero trust" is vague and sounds expensive. "We are currently at Traditional maturity. Moving to Initial requires deploying MFA on all applications and enrolling devices in MDM. The cost is X, the timeline is 3 months, and the risk reduction is Y% fewer credential-based breaches" is specific, measurable, and fundable. The maturity model turns an architectural philosophy into a roadmap with concrete milestones -- and that is what gets budget approved.
The AI Slop Connection
Every vendor claims their AI-powered product delivers zero trust. The reality: AI cannot implement zero trust. Zero trust is an architecture -- it requires redesigning how access works, not installing a box. No amount of AI-powered analysis compensates for a flat network with implicit trust.
AI CAN help with specific zero trust components: risk-based access decisions (AI assesses login risk in real time based on behavioral patterns), behavioral analytics (AI detects unusual access patterns that static rules would miss), and policy optimization (AI suggests policy refinements based on access data -- for example, identifying that a Conditional Access rule generates 200 false denials per week and recommending a threshold adjustment). But AI is a COMPONENT of zero trust, not a substitute for it.
The danger of AI in zero trust is worth highlighting: an AI that auto-approves access requests based on "learned behavior" can be gamed. An attacker who gradually escalates access over weeks (accessing slightly more sensitive resources each day, slightly different hours, slightly different locations) trains the AI to accept their behavior as normal. Then the big escalation -- accessing the financial database at 3 AM from a new IP -- looks like a natural progression to the AI because each individual step was only a small deviation from the previous baseline. This is the same slow-burn manipulation pattern we discussed in episode 48's insider threat section. Human review of unusual access patterns remains essential because humans can ask "why is this person accessing this at all?" -- a question that behavioral AI does not know how to formulate.
The organizations that will succeed with zero trust are the ones that treat it as an ongoing architectural program (Phases 1 through 4, measured by the maturity model, continuously improved) rather than a product purchase. The vendors will sell you identity proxies, SDP gateways, micro-segmentation platforms, and device compliance engines -- and those are all legitimate components that you will need. But the architecture that connects them, the policies that govern them, and the operational processes that maintain them are YOUR job. Zero trust is something you BUILD, not something you BUY.
And once you have the zero trust architecture in place -- identity-verified, device-compliant, micro-segmented, continuously monitored -- you still need someone watching the controls, responding to policy violations, and coordinating the response when something gets through. All the automation from episode 80, all the monitoring from episode 74, all the detection from episode 75 -- it needs to come together in a single coordinated operations capability. That is the next evolution of the defensive security posture we have been building throughout this entire series.
Exercises
Exercise 1: Assess your lab environment against the CISA Zero Trust Maturity Model. For each of the 5 pillars (identity, device, network, application, data), rate your current state (Traditional/Initial/Advanced/Optimal) and identify the specific gap that prevents you from reaching the next level. Create a prioritized roadmap: what is the single highest-impact change you could make for each pillar? Present your assessment as a table with columns for pillar, current level, gap, and recommended action.
Exercise 2: Implement a basic identity-based access proxy using Cloudflare Access (free tier) or Tailscale (free for personal use). Put a web application in your lab behind the proxy. Verify: (a) the application is NOT directly accessible without authentication, (b) only authenticated users can reach it, (c) access is logged with user identity and timestamp. Compare the experience against VPN-based access -- how does the user flow differ? What attack vectors does the proxy eliminate that the VPN does not?
Exercise 3: Design a Conditional Access policy set for a fictional organization (200 employees, 50 remote workers, 20 admins, 10 third-party contractors). Define policies for: (a) regular employees on managed devices, (b) regular employees on personal devices (BYOD), (c) administrators from any location, (d) third-party contractors with limited access, (e) service accounts for automation. For each policy, specify: required MFA type (FIDO2, TOTP, SMS), device requirements (managed/unmanaged/any), allowed applications (all/web-only/specific list), session timeout, and what happens when the device falls out of compliance mid-session. Present as a policy matrix table.
Thanks for your time!
Leave Learn Ethical Hacking (#81) - Zero Trust Implementation - Beyond the Buzzword to:
Read more #stem posts
Best Posts From scipio
We have not curated any of scipio's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.
More Posts From scipio
- Learn AI Series (#122) - Edge AI: Running Models on Devices
- Learn Zig Series (#103) - Mini Project: Reverse Proxy - Routing
- Learn Ethical Hacking (#81) - Zero Trust Implementation - Beyond the Buzzword
- Learn AI Series (#121) - Model Serving Architecture
- Learn Zig Series (#102) - Mini Project: HTTP Load Tester - Part 2
- Learn Ethical Hacking (#80) - Security Automation - Orchestrating Defense
- Learn AI Series (#120) - Model Optimization: Making Models Fast
- Learn Zig Series (#101) - Mini Project: HTTP Load Tester - Part 1
- Learn Ethical Hacking (#79) - Securing AI Systems in Production
- Learn AI Series (#119) - Experiment Tracking and Reproducibility