Why This Matters#

The operating system is the foundation of every workload. If the OS is compromised, everything running on it — applications, data, credentials — is compromised. OS hardening reduces the attack surface and limits what an attacker can do even after gaining initial access.


Hardening Principles#

PrincipleActions
Minimize attack surfaceRemove unused packages, disable unnecessary services
Least privilegeNon-root execution, restricted sudo, capability-based access
Patch continuouslyAutomated updates, vulnerability scanning
Secure defaultsDisable root login, enforce strong auth
Defense in depthMultiple layers (firewall + MAC + audit)
ImmutabilityRead-only filesystems, rebuild instead of patch

Linux Security Architecture#

flowchart TD
    User["User Space"]
    User --> DAC["DAC<br/>(file permissions)"]
    User --> MAC["MAC<br/>(SELinux/AppArmor)"]
    User --> Caps["Capabilities<br/>(fine-grained root)"]
    
    Kernel["Kernel Space"]
    DAC --> Kernel
    MAC --> Kernel
    Caps --> Kernel
    
    Kernel --> Seccomp["seccomp<br/>(syscall filter)"]
    Kernel --> Namespaces["Namespaces<br/>(isolation)"]
    Kernel --> Cgroups["cgroups<br/>(resource limits)"]
    Kernel --> Audit["auditd<br/>(logging)"]

Discretionary Access Control (DAC)#

Traditional Unix permissions:

PermissionFileDirectory
Read (r/4)View contentsList files
Write (w/2)Modify contentsCreate/delete files
Execute (x/1)Run as programEnter directory

Special bits:

BitEffectSecurity Implication
SUIDExecute as file ownerPrivilege escalation vector
SGIDExecute as file groupGroup privilege escalation
StickyOnly owner can deleteProtects shared directories (/tmp)

Mandatory Access Control (MAC)#

Enforces policies that even root cannot override:

SystemApproachDistribution
SELinuxLabel-based (type enforcement)RHEL, CentOS, Fedora
AppArmorPath-based profilesUbuntu, SUSE

SELinux example — a web server can only access its own files:

httpd_t (process) → can read → httpd_sys_content_t (files)
httpd_t (process) → cannot read → user_home_t (home dirs)

Linux Capabilities#

Break root’s power into granular capabilities:

CapabilityAllows
CAP_NET_BIND_SERVICEBind to ports < 1024
CAP_NET_RAWUse raw sockets
CAP_SYS_ADMINBroad admin operations (avoid!)
CAP_DAC_OVERRIDEBypass file permission checks
CAP_SETUIDChange process UID

Best practice: Drop all capabilities, add back only what’s needed.


System Hardening Checklist#

User and Authentication#

ControlImplementation
Disable root SSHPermitRootLogin no in sshd_config
Key-based SSH onlyPasswordAuthentication no
Strong password policyPAM modules (pam_pwquality)
Account lockoutpam_faillock after N failed attempts
Sudo restrictionsSpecific commands, no NOPASSWD in production
Remove unused accountsAudit /etc/passwd regularly

Network#

ControlImplementation
Host firewalliptables/nftables — default deny
Disable IPv6 (if unused)Reduces attack surface
Restrict outboundOnly allow necessary egress
Disable unused protocolsICMP redirect, IP forwarding

Filesystem#

ControlImplementation
Separate partitions/tmp, /var, /home with noexec,nosuid
File integrity monitoringAIDE, Tripwire, osquery
Restrict world-writableFind and fix: find / -perm -002
Encrypt at restLUKS, dm-crypt

Services#

ControlImplementation
Disable unnecessary servicessystemctl disable <service>
Remove unused packagesMinimal base image
Restrict service accountsnologin shell, no home directory
Sandbox servicessystemd units with ProtectSystem, PrivateTmp

Patch Management#

Lifecycle#

flowchart LR
    Discover["Discover<br/>(CVE published)"] --> Assess["Assess<br/>(CVSS + context)"]
    Assess --> Test["Test<br/>(staging)"]
    Test --> Deploy["Deploy<br/>(rolling)"]
    Deploy --> Verify["Verify<br/>(rescan)"]

Patching Strategies#

StrategyApproachRiskSpeed
ManualAdmin applies patchesHigh (delays)Slow
ScheduledWeekly/monthly windowsMediumMedium
Automated (unattended-upgrades)Auto-apply security patchesLow (for security)Fast
Immutable infrastructureReplace instances, don’t patchLowestFastest

Immutable is best: Build new AMI/image with patches → deploy → destroy old instances. No configuration drift.


Endpoint Detection and Response (EDR)#

Beyond traditional antivirus — behavioral detection and response:

CapabilityTraditional AVEDR
Detection methodSignature matchingBehavioral analysis + ML
VisibilityFile scanningProcess trees, network, registry
ResponseQuarantine fileIsolate host, kill process, collect forensics
Threat huntingNoYes (query historical data)
CoverageKnown malwareKnown + unknown (zero-day)

EDR Data Sources#

SourceDetects
Process creation/terminationSuspicious process chains
File system changesMalware drops, config modifications
Network connectionsC2 beaconing, lateral movement
Registry modifications (Windows)Persistence mechanisms
Memory analysisFileless malware, injection
DNS queriesC2 domains, tunneling

Container Security (OS Perspective)#

Containers share the host kernel — isolation is weaker than VMs:

Container Hardening#

ControlImplementation
Non-root userUSER 1000 in Dockerfile
Read-only filesystem--read-only flag
Drop capabilities--cap-drop=ALL --cap-add=<needed>
No privilege escalation--security-opt=no-new-privileges
Seccomp profileRestrict available syscalls
Resource limitsCPU/memory limits prevent DoS
Minimal base imageDistroless, Alpine, scratch

Container Escape Vectors#

VectorMitigation
Privileged containerNever use --privileged in production
Mounted Docker socketNever mount /var/run/docker.sock
Kernel exploitsKeep host kernel patched
Writable hostPathAvoid host filesystem mounts

Logging and Auditing#

What to Log#

CategoryEvents
AuthenticationLogin success/failure, MFA events, password changes
AuthorizationAccess denied, privilege escalation attempts
System changesPackage installs, config modifications, user creation
NetworkFirewall denies, new connections, unusual traffic
ProcessUnexpected processes, privilege changes

auditd Rules (Linux)#

# Monitor password file changes
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity

# Monitor sudo usage
-w /etc/sudoers -p wa -k sudo_changes
-a always,exit -F arch=b64 -S execve -F euid=0 -k root_commands

# Monitor network connections
-a always,exit -F arch=b64 -S connect -k network_connect

Log Protection#

ThreatMitigation
Attacker deletes logsShip logs off-host immediately (SIEM)
Log tamperingAppend-only storage, integrity hashing
Log overflow (DoS)Rate limiting, separate partition for /var/log
Sensitive data in logsRedact PII, mask credentials

Key Takeaways#

  1. Minimize attack surface — remove everything unnecessary (packages, services, users)
  2. MAC (SELinux/AppArmor) limits damage — even if an app is compromised, it can’t escape its policy
  3. Immutable infrastructure > patching — rebuild, don’t repair
  4. EDR replaces antivirus — behavioral detection catches what signatures miss
  5. Containers are not VMs — they share a kernel, so host security is critical
  6. Log everything, ship immediately — if logs stay on the host, attackers delete them
  7. Least privilege at every layer — users, processes, capabilities, network