Cryptography and access control
1. Why Walmart asks this
Walmart Global Tech runs identity at extreme scale: SSO for 2M+ associates, customer login for hundreds of millions of shoppers, PCI-scoped payments, multi-tenant internal platforms. Incidents at that scale start as authN/authZ failures — forged tokens, stolen sessions, over-privileged service accounts, certificates expiring at 3 a.m.
What scale changes: at millions of live sessions, a single missing check is a cross-tenant data exposure in a company that handles payment data, not a bug ticket. As an intern you would live in exactly this layer — reviewing auth flows, hardening session handling, and writing checks that deny by default. So this chapter is built around failure modes you might actually be asked to diagnose.
The JD explicitly lists "basics of cryptography, authentication, and access control". The loop is verbal depth + scenario questions on sessions/auth, not LeetCode crypto. Interviewers want to hear that you can (a) explain primitives in plain language with correct tradeoffs, and (b) reason about real failure modes — exactly what your resume already shows:
- PeerWatch SHA-256 chunk verification → expect "why SHA-256? why per-chunk? hashing vs encryption?" Have a three-line answer ready: SHA-256 is a one-way integrity check, per-chunk hashing lets one corrupted chunk be detected and re-fetched instead of re-sending the whole file, and MD5/SHA-1 were ruled out because of practical collision attacks.
- Session registry
(pool, uid)cross-tenant fix with fail-closed UID → expect "what is session hijacking? what does fail-closed mean? how did you make authorization decisions per-tenant?" Tell it as a security story: the key was tenant pool only, so one tenant's session could resolve against another tenant's pool; adding the UID made authorization per (pool, uid), and any lookup without a verified UID denied access instead of falling back to a shared identity.
Rule: connect every concept below to one of those two projects in one sentence.
2. Concepts, simply explained
2.1 CIA triad + AAA + non-repudiation (the vocabulary of everything else)
| Property | Meaning | Example at Walmart scale |
|---|---|---|
| Confidentiality | Only authorized parties can read it | TLS on walmart.com, encrypted card vault |
| Integrity | Data wasn't altered undetectably | SHA-256 chunk hashes in PeerWatch; signed JWTs |
| Availability | Systems are up when needed | DDoS protection on Black Friday |
| Authentication (AuthN) | "Who are you?" | Login, badge, TOTP |
| Authorization (AuthZ) | "What may you do?" | RBAC/ABAC on admin consoles |
| Accounting/Audit (AAA) | "What did you do?" | Immutable audit logs |
The properties trade off in real designs: signature checks on every request protect integrity but add latency under Black Friday load; long-lived encryption keys buy confidentiality but make rotation and recovery harder. Habit for the loop: name which property a control serves before naming the control.
Non-repudiation = a party cannot later deny an action. Only digital signatures give it (symmetric MACs don't, because either side could have produced the tag). HOW it works: the signer's private key produces the tag, and verification with the public key ties the message to whoever holds that private key — the verifier never holds signing power. Example: a signed deployment approval — the admin can't claim someone else used the shared secret. Accounting/Audit is the operational companion: the signature proves who approved, the log proves what happened next.
Interview angle: "Which property does an HMAC fail to provide, and why?" → non-repudiation, because the verifier holds the same secret and could have forged the tag; a MAC proves only that someone knowing the secret produced the message.
2.2 Symmetric vs asymmetric cryptography
| Symmetric | Asymmetric | |
|---|---|---|
| Keys | One shared key | Public + private key pair |
| Speed | Fast (100–1000x) | Slow |
| Key distribution | Hard problem | Easy (publish public key) |
| Bulk data | ✅ Yes | ❌ No (use for key exchange/signatures) |
| Algorithms | AES (128/256, GCM mode), ChaCha20-Poly1305, 3DES/DES (legacy, 56-bit DES broken; 3DES ≈112-bit effective) | RSA, ECC (ECDSA, ECDH), Diffie-Hellman |
Real answer in practice: hybrid. TLS uses asymmetric (RSA/ECDH) to authenticate and agree on a session key, then symmetric (AES-GCM / ChaCha20) to encrypt the actual traffic. WHY hybrid: the asymmetric part happens once per connection, then traffic runs on symmetric speed; the asymmetric half is also where identity lives — the server certificate proves which site you are talking to before any customer data moves.
RSA. WHAT: the classic public-key system, security from the hardness of factoring n = p·q. Public e = 65537, private d = e⁻¹ mod λ(n); encrypt c = m^e mod n, decrypt m = c^d mod n. 2048-bit minimum; slow, large signatures. Always pad — OAEP for encryption, PSS for signatures (textbook RSA is broken: unpadded RSA leaks structure and small messages can be recovered by taking roots).
ECC. WHAT: elliptic-curve systems — ECDSA for signatures, ECDH for key agreement — with the same security level as RSA in much smaller keys (256-bit ECC ≈ 3072-bit RSA). WHY it matters: smaller keys and signatures mean faster handshakes and less bandwidth — what mobile clients and high-volume TLS want. HOW: security rests on the elliptic-curve discrete logarithm problem, with no efficient classical algorithm known.
Diffie-Hellman (DH/ECDH). WHAT: a key-agreement protocol — two parties agree on a shared secret over an insecure channel without transmitting it (discrete-log hardness). DH alone is unauthenticated — an active attacker can run DH with both sides (MITM); TLS fixes this by signing the exchange with the server certificate. Forward secrecy: ephemeral DH (DHE/ECDHE) means recorded traffic stays unreadable even if the long-term key leaks later. CONCRETE: in the §4 ECDH drill, both sides derive the same bytes from their own private key and the peer's public key — run it with inkey/peerkey swapped to confirm both sides match.
One-liner for the interview: "Symmetric is for speed on data, asymmetric is for key exchange and identity; TLS combines both." Follow-up: "Why not RSA for everything?" → too slow for bulk data; asymmetric crypto bootstraps a session key and gets out of the way.
2.3 Hashing vs encryption + salts, rainbow tables, bcrypt/Argon2
| Hashing | Encryption | |
|---|---|---|
| Reversible? | No (one-way) | Yes (with key) |
| Purpose | Integrity, fingerprints | Confidentiality |
| Example | SHA-256, SHA-3, BLAKE2, MD5/SHA-1 = broken | AES, RSA |
Rainbow tables and salts. WHAT: a rainbow table is a precomputed hash→password mapping — an attacker with a stolen hash database looks up passwords instead of guessing. HOW salting defeats it: a unique random value per password is mixed in before hashing, which kills table reuse (rebuilt per salt) and makes identical passwords hash differently — nothing correlates across accounts. CONCRETE: the §4 salt drill hashes one password with two salts and prints two different digests — that difference is the point.
Slow hashing for passwords. WHAT: password hashes are deliberately slow and memory-hungry. WHY: fast hashes (SHA-256) are wrong for passwords because GPUs do billions/sec, turning a stolen hash database into a weekend cracking project; a slow hash buys time to rotate credentials after a breach. HOW: use bcrypt (cost factor, Blowfish-based), scrypt (memory-hard), or Argon2id (memory+time tunable, PHC winner). OWASP's current baseline: Argon2id at m=19456 (19 MiB), t=2, p=1 as a minimum; for legacy bcrypt, work factor ≥ 10 and a 72-byte password limit.
PeerWatch tie-in: "I used SHA-256 for integrity of chunks — deterministic, fast, collision-resistant. For passwords I'd use Argon2id — the two are different jobs." Keep that answer verbatim; it settles "why SHA-256 if it isn't for passwords" in one breath.
Upgrade path: bcrypt → Argon2id (how a real migration works)
WHAT: the rehash-on-login migration every long-lived auth system needs. WHY at Walmart scale: you cannot reset millions of customer passwords, so the upgrade must be incremental and invisible to shoppers.
- Step 1 — dual verification: keep verifying against the old hash (bcrypt) while writing new hashes as Argon2id; on successful login, recompute with the new algorithm and overwrite the stored hash.
- Step 2 — lazy completion: users who never log in keep old hashes; force-reset or alert on the tail after a deadline, and treat dormant accounts as a separate risk decision.
- Step 3 — parameter ratchet: cost parameters rise with hardware generations. Libraries support this directly — argon2-cffi's
PasswordHasher().check_needs_rehash(hash)reports when an existing hash is below current parameters. - Pepper handling: if a pepper (app-wide secret in config/HSM) exists, it applies to both old and new hashes and is rotated separately — never stored alongside the hash, unlike the salt.
Interview angle: "How do you upgrade password hashing without locking everyone out?" → rehash on successful login, dual-verify during the transition, then force the long tail; mention cost-parameter ratcheting and that salt (public, per-user) and pepper (secret, app-wide) rotate differently.
2.4 Digital signatures
WHAT: a digital signature proves who wrote a message and that it was not altered.
HOW: sign with the private key → verify with the public key. Gives integrity + authenticity + non-repudiation.
signature = Sign(privateKey, hash(message)) — the verifier recomputes the hash of the received message and checks the signature with the public key, so any bit flip fails verification. Examples: code signing, JWT RS256, TLS certificates, SAML assertions. CONCRETE: the §4 drill (openssl dgst -sha256 -sign priv.pem then -verify pub.pem) is the full lifecycle in four commands, and editing one byte of doc.txt makes verification fail — that tamper-evidence is what you are buying.
Contrast HMAC (symmetric MAC): same secret creates and verifies — integrity + authentication but no non-repudiation. Rule of thumb: signatures when a third party must later check the claim (certificates, approvals); HMAC when the same party issues and checks.
Interview angle: "Why RS256 over HS256 in a multi-service setup?" → verifiers hold only the public key, so a compromised verifier cannot mint tokens, and you get non-repudiation over who signed.
2.5 PKI, CAs, chains, revocation, expiry outages
PKI = the trust system: Root CA → Intermediate CA(s) → leaf certificate (server cert). Your browser trusts roots baked into its store; it validates a site by walking the chain of trust up to a trusted root (each cert signed by the one above). HOW validation works: the client checks each signature up the chain, expiry dates, and hostname-vs-SANs; the root key stays offline and intermediates sign day-to-day, so a compromised intermediate is revocable without re-trusting the whole web. WHY at Walmart: customer-facing TLS and internal service identity both lean on this machinery — a broken chain is a login outage for millions.
Certificate contents: subject, public key, issuer, validity period, SANs. Read them with the §4 openssl s_client | openssl x509 drill: chain, issuer, and the expiry date monitoring should alert on.
- Revocation (cert leaked before expiry):
- CRL (Certificate Revocation List): CA publishes a periodically-updated list of revoked serial numbers. Big, stale between updates.
- OCSP: client asks the CA's responder "is serial X valid right now?" Real-time, but privacy leak + responder downtime risk.
- OCSP stapling: server fetches its own OCSP response and staples it to the TLS handshake — faster and private.
- CRLite / short-lived certs: modern alternatives (Let's Encrypt issues 90-day certs and automates renewal).
- Expiry outages — a favorite scenario question: expired certs cause hard failures — Zoom (Aug 2020), Microsoft Teams auth cert (Feb 2020, ~3h), Microsoft 365/Azure AD (Sep 2020), Epic Games internal wildcard (Apr 2021, ~5.5h, monitoring blind spot), Ericsson/O2 mobile network (Dec 2018, hardcoded cert). Lesson: automate renewal + alert at 30/14/7 days. "Certificates don't fail loudly until everything breaks at once."
- Self-signed cert: a certificate that is its own issuer — no CA vouches for it. Fine for internal/test with pinned trust (the client explicitly trusts that one cert or an internal CA); browsers will (correctly) warn otherwise because there is no chain to a trusted root. In internal infra a private CA issuing to services is the common pattern — and neither belongs in front of customers.
Tradeoff: revocation checking is a latency and availability decision as much as a security one — every handshake then depends on a CRL or OCSP responder, which is why stapling and short-lived automated certs won. At Walmart-scale traffic: automated renewal first, revocation as defence in depth.
Key and certificate rotation
WHAT: replacing keys and certificates before they expire or after suspected compromise, without downtime. WHY: a retailer's estate has certs on load balancers, services, and devices; a missed rotation is exactly the 3 a.m. outage from the list above.
- Inventory first: you cannot rotate what you cannot see — track every cert's expiry, owner, and SANs.
- Automate issuance and renewal (ACME): short-lived certs (e.g., 90-day Let's Encrypt) plus automated renewal make rotation a non-event; alert at 30/14/7 days as a backstop.
- Overlapping validity: publish the new key/cert while the old one still verifies — clients holding the old JWKS entry or a cached cert keep working, and you drop the old key after the longest token lifetime.
- Emergency rotation: on suspected key leak, revoke (CRL/OCSP) and rotate immediately; for shared secrets like the Kerberos krbtgt, rotate twice (current + previous version) with a full ticket lifetime between resets — see §2.8.
Interview angle: "How do you rotate JWT signing keys without logging everyone out?" → JWKS with key IDs: mint with the new kid, keep the old key verifying until existing tokens expire (5–15 minute lifetimes make this cheap), then remove it.
2.6 TLS: why SSL is deprecated, 1.2 vs 1.3
SSL (v2/v3) is dead. POODLE broke SSLv3, RC4 and export ciphers broken, no modern AEAD ciphers. "SSL" survives only as a word; everything is TLS now (TLS 1.2/1.3). WHAT POODLE was: a padding-oracle downgrade to SSLv3 that recovered plaintext byte by byte — the lesson: downgrade attacks target the negotiation, which is why TLS 1.3 shrank the option space.
TLS 1.2. RSA or DHE/ECDHE exchange; CBC/GCM ciphers; ~2 round trips; dangerous if misconfigured (BEAST, Lucky13, weak-cipher downgrade). HOW it fails: a site still accepting RC4 or old CBC suites to "support old clients" reopens fixed attacks — configuration, not the version number, decides your real security.
TLS 1.3 (2018): AEAD-only ciphers (AES-GCM, ChaCha20-Poly1305), no static RSA → forward secrecy for all certificate/(EC)DHE handshakes; exceptions are PSK-only resumption and 0-RTT early data, which are not forward-secret (RFC 8446 §2.2). 1-RTT handshake (0-RTT resumption, replay caveats); removed RSA key transport, compression, renegotiation. Client certs optional (mTLS). WHY the removals matter: compression (CRIME/BREACH side channels), renegotiation (Triple Handshake), and static RSA (no forward secrecy) were deleted outright, not left for operators to disable.
Interview angle: "Why is TLS 1.3 harder to misconfigure?" → the dangerous choices were removed: no RSA key transport, no CBC, no compression or renegotiation; only AEAD cipher choice and certificate handling remain.
mTLS for service-to-service in retail infrastructure
WHAT: mutual TLS — both sides of a connection present a certificate, so the client authenticates the server and the server authenticates the client. HOW: the TLS handshake from §4 plus a client certificate in the server's CertificateRequest; the server maps the client cert's identity (SAN/CN) to a service identity and applies policy on it. The command shape is openssl s_client -connect host:443 -cert client.pem -key client.key -CAfile ca.pem.
WHY it matters in retail infra: customer login, orders, payments, and store systems are hundreds of internal services calling each other; network location is not an identity, and a stolen internal token should not be enough to reach a payments service. mTLS gives every workload an identity from an internal CA and lets the callee enforce "only the order service may call me" at the transport layer — the service-to-service half of least privilege.
Pitfalls: automate certificate rotation (back to §2.5) or mTLS manufactures its own expiry outages; and mTLS authenticates the connection, not the end user — user identity must travel in the request (token/claims) so authorization stays per-customer.
Interview angle: "How would you secure service-to-service traffic?" → mTLS with workload certs from an internal CA and automated rotation, plus application-level claims for user identity; network segmentation is the fallback, not the identity.
2.7 MFA / 2FA / TOTP
Auth factors. WHAT: the three categories of evidence — something you know (password), have (phone, hardware key), are (biometric). 2FA = exactly two factors; MFA = two or more. Two passwords ≠ 2FA (same factor). WHY it matters: password theft is the dominant account-takeover path at customer-login scale; the second factor turns a stuffed credential into a dead end.
TOTP (RFC 6238, Google Authenticator style): code = HOTP(shared_secret, floor(unix_time/30)) — 6–8 digits, ~30s window. Secrets are provisioned via QR (base32). HOW it verifies: client and server hold the shared secret and current time step; the server accepts the neighbouring step for clock drift, and should mark each accepted code as used within its window so a phished code cannot be replayed. CONCRETE: the QR is just the base32 shared secret — anyone who photographs it owns the factor until re-provisioning.
Phishing-resistant MFA (strongest first): FIDO2/WebAuthn hardware keys (origin-bound; a fake site can't use the assertion) > push with number-matching (blocks MFA-fatigue, e.g., the 2022 Uber breach) > plain push > SMS OTP (SIM-swap vulnerable — still better than nothing).
Passwordless/passkeys: WHAT: a WebAuthn credential bound to origin; the private key never leaves the authenticator. Syncable passkeys (Apple/Google vault) vs device-bound keys. It replaces the password (not a second factor), and the weak link moves to account recovery — a weaker email/SMS fallback nullifies the design.
Biometrics: local verifier only (never sent over the network), FAR/FRR tradeoff + liveness/anti-spoof, and cannot be rotated after a leak — so used as local unlock for a key, not as a network secret. Interviewers listen for the asymmetry: a leaked fingerprint is forever, a key is rotatable.
Rule to say out loud: MFA stops most account-takeover, not all — real-time phishing proxies (evilginx2) can relay session cookies. At Walmart's login volume, MFA plus rate limiting and breach monitoring turns credential stuffing from a takeover pipeline into noise.
Interview angle: "Why is TOTP better than SMS but not phishing-proof?" → SIM-swap versus an app-held secret; but TOTP secrets are not origin-bound, so a fake site can harvest them — FIDO2 binds the assertion to the origin.
2.8 Kerberos: TGT + the three classic attacks
WHAT: Kerberos is the ticket-based authentication system behind Active Directory — the SSO backbone for associate logins in enterprise environments. HOW the flow works (Active Directory): user → KDC (AS-REQ) → TGT (ticket-granting ticket, cached, ~10h) → for each service, present TGT → service ticket (TGS) → present to the service. Password never travels; the service verifies without hitting the DC each time. WHY: the DC authenticates you once and every later service check is a local ticket verification — what keeps login traffic survivable when millions of associates hit the KDC at shift start.
| Attack | What it abuses | Impact / fix |
|---|---|---|
| Kerberoasting | Any domain user requests TGS for accounts with SPNs; tickets are encrypted with the service account's password hash → crack offline (Hashcat 13100 = RC4/etype 23; AES tickets = 19600/19700, much slower) | Long, random (25+ char) service-account passwords, group managed service accounts (gMSA), force AES-only, monitor Event 4769 anomalies |
| AS-REP roasting | Accounts with pre-auth disabled: DC returns material encrypted with the user's hash without proof of identity → crack offline (no auth needed) | Audit DoesNotRequirePreAuth, re-enable pre-auth, Event 4768 Pre-Auth Type 0 |
| Golden ticket | Forged TGT signed with stolen KRBTGT hash → impersonate anyone, any group, years-long validity; survives password resets | Post-exploitation persistence (needs DA first). Reset krbtgt twice (current+previous versions), wait max ticket lifetime between resets, monitor 4769 without matching 4768 |
| (Silver ticket) | Forged service ticket with a service account hash → one service, bypasses KDC entirely | Rotate service account hashes, gMSA |
Pass-the-hash: the credential-theft walkthrough
WHAT: an attacker holding a stolen NTLM hash authenticates as the user without cracking the password — the hash is the credential. HOW: tools pass the captured hash in the NTLM exchange, so the attacker gets sessions anywhere that account is valid; hashes harvested from one machine (LSASS dumps, backups) unlock lateral movement. It is an NTLM attack — Kerberos' ticket design avoids the exact pattern — but it belongs in the same AD threat discussion as golden tickets: derived credential material is as valuable as the password.
Defence: tier admin accounts so privileged hashes never touch a workstation, enable Credential Guard / Protected Users, manage local admin passwords centrally, and rotate passwords to invalidate captured hashes.
Interview angle: "Kerberoasting vs pass-the-hash?" → Kerberoasting cracks a service account's ticket hash offline to recover the password; pass-the-hash uses a stolen hash directly, no cracking. Both are blunted by strong rotated credentials and controlling where privileged hashes can be captured.
2.9 OAuth 2.0 / OIDC / SAML (high level)
| What it is | What it's for | Format | |
|---|---|---|---|
| OAuth 2.0 | Authorization framework (RFC 6749): delegated access via access tokens | "Let this app read my Google Drive" | Opaque or JWT tokens |
| OIDC | Identity layer on top of OAuth2: adds id_token + UserInfo |
"Log in with Google" (AuthN) | JWT (id_token) |
| SAML 2.0 | Enterprise SSO federation (XML assertions, browser redirects/POSTs) | Corporate SSO to internal apps | XML signed assertions |
Key OAuth concepts. WHAT: OAuth2 lets a user delegate limited access without sharing their password — a scoped, revocable loan of authority. HOW the safest flow works (authorization code flow):
- Step 1 — redirect with
state: the app sends the user to the IdP carrying a randomstatevalue; on return, a mismatch means CSRF and the attempt dies. - Step 2 — consent and code: the user authenticates; the IdP returns a short-lived authorization code to an exact redirect-URI string match (no wildcards — a wildcard is an open redirect into token theft).
- Step 3 — code for tokens: the app exchanges the code at the token endpoint (with PKCE verifier for public clients — RFC 9700 says use PKCE everywhere) for an access token and refresh token.
Other shapes: client credentials (machine-to-machine, no user — what service accounts actually use), device authorization flow (TV/IoT), scopes (the least-privilege dial — request read, not full), refresh tokens. Implicit flow is deprecated (token leaks via URLs/history). Never confuse: OAuth2 gives delegation, OIDC gives identity; access tokens are for the API, id_token is for the client — never accept an id_token as an API credential. SAML vs OIDC: SAML = XML/enterprise/verbose; OIDC = JSON/modern/API-friendly.
WHY Walmart cares: internal platforms federate to corporate SSO (SAML/OIDC) while machine traffic runs on client-credentials tokens; at that scale a confused deputy or loose redirect URI is a cross-tenant incident — state/nonce/PKCE are the boring checks that prevent it. CONCRETE: on a login redirect return, check state matches and the redirect URI matches exactly.
Interview angle: "Why PKCE even for a confidential client?" → it binds the code to the client that requested it, defeating code interception/injection; RFC 9700 says use it everywhere.
2.10 JWT: structure, attacks, hardening
A JWT = base64url(header).base64url(payload).base64url(signature).
// header {"alg":"RS256","typ":"JWT"}
// payload {"sub":"user123","role":"admin","iss":"walmart-idp","aud":"api","exp":1735689600}
Critical point: the payload is Base64, NOT encrypted — anyone can read it. Signing gives tamper-proofing, not secrecy. CONCRETE: the §4 decode snippet splits the token on dots and base64url-decodes the middle with no key at all — so treat claims as public and keep sensitive data server-side keyed by sub/jti.
| Attack | How it works | Defense |
|---|---|---|
alg: none |
Attacker sets "alg":"none", strips signature; naive lib accepts it (case tricks like noNE bypassed blocklists) |
Pin the algorithm server-side (algorithms=["RS256"]); allowlist, never trust the header |
| Algorithm confusion (RS256→HS256) | Attacker signs with the public key as HMAC secret; verifier treats it as the HMAC secret | Same fix: pin algorithm; separate keys |
| Weak HS256 secret | Offline brute-force of short secrets (attacker holds the token) | 256-bit random secret or RS256; per-tenant keys |
Embedded JWK / jku injection |
Header carries attacker's own key | Only use keys from your trusted JWKS endpoint |
| Missing claim checks | Signature valid but exp/aud/iss unchecked → token replayed cross-service |
Validate all claims server-side |
| Kid path traversal | kid used as file path/SQL lookup |
Allowlist key IDs, parameterize lookups |
Token replay, concrete. WHAT: an attacker who captured a valid JWT (proxy logs, XSS, a careless URL) simply sends it again — signatures never expire, exp does. HOW the defences stack: short exp caps the window; a server-side jti denylist kills a token after logout or leak; strict aud/iss checks stop cross-service token reuse; HTTPS plus HttpOnly storage reduce capture in the first place.
Securing JWTs: short-lived access tokens (5–15 min) + refresh token rotation with reuse detection (a replayed refresh token → revoke the whole token family); store in HttpOnly+Secure+SameSite cookie (or memory for SPAs — never localStorage if avoidable, never in URLs); validate aud strictly — a service must reject tokens minted for another service (the JWT version of the cross-tenant bug); server-side denylist of jti in Redis when you need revocation; RS256 so verifiers never hold a secret. If you need instant revocation on every request: server-side sessions are the simpler, correct answer — say this out loud, interviewers love the tradeoff awareness.
Interview angle: "How do you revoke a JWT?" → you don't revoke the token itself: shorten exp, denylist jti server-side, rotate refresh tokens with reuse detection, or use server-side sessions when instant revocation is a requirement.
2.11 Sessions: fixation, hijacking, cookie flags, timeouts, rotation
Session fixation. WHAT: the attacker chooses the victim's session ID before login (e.g., via URL ?JSESSIONID=); the victim logs in; the attacker's known ID is now authenticated. Fix: regenerate the session ID on privilege change (login). Full walkthrough below.
Session hijacking. WHAT: stealing a valid session after login — XSS reading a cookie, network sniffing on plain HTTP, malware, or predictable session IDs. Fix: HttpOnly, Secure, unpredictable random IDs (128+ bits), HTTPS everywhere. CONCRETE: the §4 curl -sI ... | grep -i set-cookie drill shows whether the session cookie sets HttpOnly; Secure; SameSite and whether anything leaks into a URL.
Session fixation: the step-by-step walkthrough
- Step 1 — plant: the attacker gets a session ID from the target site (many sites issue an anonymous ID pre-login) and sends the victim a link containing it (
?JSESSIONID=attacker-known). - Step 2 — authenticate: the victim logs in through that session; the server upgrades the existing ID to authenticated without changing it — this is the bug.
- Step 3 — ride: the attacker uses the same ID and inherits the logged-in session; nothing on the victim's machine is compromised.
- Defence: regenerate the session ID at login (and every privilege change), reject IDs the server never issued to that client, and expire unauthenticated IDs quickly. Cookie flags alone do not fix fixation — the attacker already knows the ID.
- One-line framing: fixation is about who chose the ID; hijacking is about who knows the ID afterwards. Say that sentence and interviewers know you have internalized the difference.
| Cookie flag | Protects against | Notes |
|---|---|---|
HttpOnly |
XSS token theft | JS cannot read the cookie |
Secure |
Network sniffing | Sent over HTTPS only; required with SameSite=None |
SameSite=Lax/Strict |
CSRF | Lax allows top-level GET navigations (SSO redirects work); Strict breaks email/SSO links |
Path/Domain scoping |
Over-broad exposure | Least privilege for cookies |
Cookie prefix. __Host- forces Secure + host-only + no Domain override — use it for session cookies, so a sibling subdomain cannot widen the scope of a cookie the host issued.
Timeouts. WHAT: two clocks on every session — absolute timeout (e.g., 8h) and idle timeout (e.g., 30m). WHY: a stolen session is worth its remaining lifetime; timeouts cap that value even when nothing else detects the theft. Sensitive ops (password change, wire transfer, admin actions) → step-up/re-auth: re-prove identity at the moment of risk.
Rotation. WHAT: mint a new session ID after login and periodically. Invalidate server-side on logout (client "logout" that only deletes the cookie is a bug — the ID still works if captured). CONCRETE: if an ID leaks, rotation at login makes the leaked anonymous ID worthless and server-side invalidation kills captured IDs at logout. Tie-in: your (pool, uid) fix is the same instinct for authorization — bind the session to verified identity data, never a bare handle.
Your (pool, uid) story, framed in this language: "The registry keyed sessions by tenant pool only, so a session from one tenant could resolve against another tenant's pool — an authorization/session-scope bug, not just authN. I made the UID part of the key so authorization was evaluated per (pool, uid), and defaulted to fail-closed: if the UID couldn't be verified, access was denied rather than falling back to a shared or anonymous identity."
2.12 RBAC vs ABAC, least privilege, PAM/JIT
| RBAC | ABAC | |
|---|---|---|
| Based on | Roles/groups ("store-manager") | Attributes/claims (dept, location, time, device posture, risk score) |
| Model | Simple, auditable, easy to reason | Flexible, fine-grained, contextual |
| Scales badly when… | Role explosion (thousands of near-duplicate roles) | Policy complexity/opacity |
| Example | role:order-support → read orders |
allow read order IF order.tenant == user.tenant AND time IN shift AND device.compliant |
Least privilege. WHAT: every identity (human and service) gets the minimum permissions for the minimum time. HOW: scoped roles, expiring grants, and access recertification campaigns where owners re-approve what their teams hold. WHY at Walmart: with 2M+ associates and thousands of service accounts, one over-privileged account starts your worst incident.
PAM (Privileged Access Management): vault admin credentials, session recording, just-in-time elevation. JIT access: standing privileges ≈ 0; engineers request time-boxed elevation with approval (e.g., 4 hours of prod read access). "Standing admin is an incident waiting to happen." Concrete picture: the credential is checked out of a vault for the approved window, the session is recorded, and the grant expires on its own — a compromise outside that window finds nothing to steal.
Fail-closed vs fail-open. WHAT: what the system does when the authorization input is missing, ambiguous, or unverifiable. Rule: deny-by-default — authorization checks must fail closed — exactly your UID fix. Name the flip side: fail-open buys availability at the cost of customer-data safety — the wrong trade at payments-adjacent scale.
Interview angle: "What is standing admin and why is it a problem?" → always-on privileged access waiting to be stolen; the fix is JIT elevation plus vaulting plus session recording. Pair it with "least privilege" and "fail-closed" unprompted.
2.13 Password storage + attack types
WHAT: password storage is one-way by design — you keep only what you need to verify a login. HOW the pieces fit: Argon2id (or bcrypt/scrypt) + unique per-user salt + tuned cost; optionally pepper (app-wide secret in config/HSM, not stored with the hash — unlike the salt, which is stored alongside). Never plaintext, never MD5/SHA-1, never "encrypted" passwords you must decrypt. WHY these choices at customer-login scale: the salt kills rainbow tables and cross-account correlation, the slow hash makes a stolen database expensive to crack (OWASP floor: Argon2id m=19456, t=2, p=1), and the pepper means a database-only leak is still not enough to mount an offline attack. (Migration path: §2.3.)
| Attack | Definition | Mitigation |
|---|---|---|
| Brute force | Try all possible combinations | Rate limiting, lockout/backoff, long passwords, MFA |
| Dictionary attack | Try words from a list (with mutations) | Blocklist breached passwords (k-anonymity HIBP check), passphrases |
| Credential stuffing | Replay leaked username:password pairs from other breaches against your login | MFA, rate limits + bot detection, breach monitoring, device fingerprinting |
| Rainbow table / offline cracking | Precomputed hashes; crack stolen hash DB offline | Salting + slow hashes (Argon2id) |
| Password spraying | One common password against many accounts | Smart lockouts, MFA, deny common passwords |
Interview angle: "Walk me through securing a login page." → Argon2id + salt (+ pepper) storage, rate limiting with backoff and lockout, breached-password blocklist (HIBP k-anonymity check), MFA, session ID rotation at login, audit logging. Six items, thirty seconds — the expected checklist.
3. Real interview Q&A (18 questions)
Q1. Difference between authentication, authorization, and accounting? AuthN proves identity ("who"), AuthZ decides permissions ("what"), Accounting records what happened ("audit"). Sequential: you can't authorize an unknown identity; without logs you can't investigate. Example: TOTP login (AuthN) → policy allows refunds ≤ $500 (AuthZ) → append-only log of every action (Accounting).
Q2. When would you use symmetric vs asymmetric encryption? Symmetric (AES-GCM, ChaCha20) for bulk data — fast, needs a shared key. Asymmetric (RSA, ECC) for key exchange and signatures — solves key distribution. TLS: asymmetric handshake to authenticate and derive a session key, symmetric for payload. Never encrypt large data directly with RSA.
Q3. What is Diffie-Hellman and what problem does it solve? Key agreement over an insecure channel: both sides combine a private value with the other's public value to derive the same shared secret; an eavesdropper sees only public values and can't compute it (discrete log hardness). Ephemeral DH gives forward secrecy: compromise of the long-term key later doesn't decrypt recorded traffic. Caveat: DH alone is unauthenticated — an active attacker can MITM it unless the exchange is authenticated (in TLS, via the server certificate).
Q4. Hashing vs encryption? Can you recover a hashed password? Hashing is one-way (integrity/fingerprints), encryption is reversible (confidentiality). You can't "decrypt" a hash — you can only guess inputs and compare. That's why passwords use slow, salted hashes (Argon2id): to make guessing expensive.
Q5. Why salting? Do rainbow tables still work against salted hashes? A salt is a unique random per-user value mixed in before hashing. It defeats rainbow tables (a table must be rebuilt per salt) and stops identical passwords from producing identical hashes. With a unique salt per user, precomputation is useless; the attacker must attack each hash individually.
Q6. Why did you use SHA-256 in PeerWatch — why not MD5 or encryption? "I needed integrity, not confidentiality — to detect corrupted or tampered chunks during transfer. MD5/SHA-1 have practical collision attacks, so SHA-256 is the safe baseline. Per-chunk hashing meant a bad chunk could be detected and re-fetched instead of re-sending the whole file. For passwords I'd use Argon2id instead — different threat model."
Q7. What is a digital signature and how does it differ from an HMAC? Signature: sign with private key, verify with public — integrity, authenticity, non-repudiation. HMAC: one shared symmetric secret both creates and verifies — integrity + authentication, but either party could have made it, so no non-repudiation. Signatures are used for JWT RS256, certificates, SAML, code signing.
Q8. Walk me through TLS handshake (high level) and why SSL is deprecated. ClientHello ⇄ ServerHello, server sends certificate (chain to a trusted CA), key agreement via (EC)DHE, both derive session keys, finish. TLS 1.3 = 1-RTT, AEAD-only ciphers, forward secrecy mandatory. SSLv3 is dead (POODLE, RC4, export ciphers) — "SSL" today just means TLS colloquially.
Q9. TLS 1.2 vs 1.3 — what improved? 1.3 removes RSA key transport and CBC modes → forward-secret for all certificate/(EC)DHE handshakes (PSK-only and 0-RTT excepted), always AEAD; 1-RTT (and 0-RTT resumption with replay caveats); no compression/renegotiation (attack surface removed); simpler cipher suite list. Downside: can't intercept TLS 1.3 traffic for enterprise inspection without terminating proxies.
Q10. What happens when a certificate expires — and how do you prevent it? Clients hard-fail: no bypass, users see scary errors, services break (real outages: Teams Feb 2020, Zoom Aug 2020, M365/Azure AD Sep 2020, Epic Games Apr 2021, Ericsson/O2 Dec 2018). Prevention: automated renewal (ACME), monitoring/alerts at 30/14/7 days, inventory of all certs (they exist in many places), and runbooks for emergency replacement. Certificates fail silently until they fail all at once.
Q11. CRL vs OCSP? Both revoke certificates before expiry. CRL = CA's periodically published list of revoked serials — simple but can be large and stale. OCSP = real-time query per certificate — fresh, but reveals browsing to the CA and adds a dependency on responder uptime. OCSP stapling fixes both (server caches and staples the response). Modern trend: short-lived certs + automation reduce reliance on revocation entirely.
Q12. Explain TOTP and the strength hierarchy of MFA. TOTP derives a code from a shared secret + time step (30s window) per RFC 6238 — the server verifies the code offline with the same secret. Hierarchy: hardware FIDO2/WebAuthn keys (origin-bound, phishing-resistant) > authenticator-app TOTP > push (MFA-fatigue risk) > SMS (SIM-swap risk). MFA stops most credential-stuffing, not real-time phishing proxies.
Q13. Explain Kerberos TGT and name one Kerberos attack.
Login → KDC (AS-REQ) → TGT (10h, cached) → TGS-REQ per service → service ticket to the service. Password never crosses the network. Attacks: Kerberoasting (request TGS for SPN accounts, crack the service account's hash offline → mitigate with 25+ char passwords/gMSA); AS-REP roasting (pre-auth disabled accounts leak crackable material with no auth → audit DoesNotRequirePreAuth); golden ticket (forge TGT with stolen krbtgt hash → domain-wide persistence; fix = double krbtgt reset after ticket lifetime).
Q14. OAuth2 vs OIDC vs SAML?
OAuth2 = authorization delegation (access tokens, scopes, e.g., "let app X read my Drive"). OIDC = identity layer on OAuth2 (adds id_token = JWT) for login. SAML = enterprise SSO with signed XML assertions via browser redirects. Modern consumer login = OIDC; legacy enterprise federation = SAML; delegated API access = OAuth2.
Q15. JWT structure + how would you attack and secure one?
Three Base64URL parts: header (alg), payload (claims — not encrypted), signature. Attacks: alg:none, RS256→HS256 confusion (sign with the public key as HMAC secret), weak HS256 secret brute-force, embedded JWK injection, missing exp/aud/iss checks. Secure by pinning the algorithm server-side, validating claims, RS256, 5–15 min expiry + rotating refresh tokens with reuse detection, HttpOnly+Secure+SameSite storage.
Q16. Session fixation vs session hijacking? How do you prevent each? Fixation = attacker chooses the victim's session ID pre-login and inherits the authenticated session → fix: regenerate session ID at login (and other privilege changes). Hijacking = attacker steals a valid session ID (XSS, sniffing, malware) → fix: HttpOnly/Secure/SameSite cookies, HTTPS everywhere, unpredictable IDs, idle+absolute timeouts, rotation. Logout must invalidate server-side.
Q17. localStorage vs HttpOnly cookie for tokens?
localStorage: XSS-readable (token theft) but CSRF-immune. HttpOnly cookie: JS-invisible but auto-sent → needs SameSite + CSRF tokens. Default: HttpOnly+Secure+SameSite cookie, ideally a backend-for-frontend keeping tokens off the browser. Caveat: with XSS the attacker acts as the user anyway — no storage choice fully saves you.
Q18. RBAC vs ABAC — and what does "fail-closed" mean in your session fix?
RBAC grants by role (simple, auditable, prone to role explosion); ABAC grants by attributes/policy (tenant, device, time, risk) — finer-grained, more complex. Enterprise reality is RBAC baseline + ABAC for tenant/row-level checks. "Fail-closed" = when the authorization input is missing or unverifiable, deny by default. In my registry fix, sessions were keyed by (pool, uid) so cross-tenant lookups were impossible by construction, and any lookup without a verified UID denied access instead of degrading to a shared identity.
Bonus scenario Qs: "A user reports unknown orders — what do you check?" (session logs, reset flow, cookie flags, stuffing signals); "Design admin-console login" (SSO + phishing-resistant MFA + JIT + rotation + audit); "2M+ SSO sessions — how do you revoke at scale?" (short-lived tokens + jti denylist/Redis + BFF, not long-lived JWTs); "PCI payments — where do crypto controls sit?" (TLS everywhere, HSM/tokenization, no PAN in logs, step-up MFA).
4. Hands-on drills (run these before the interview)
Hashing (matches PeerWatch)
# SHA-256 of a file / of a chunk
openssl dgst -sha256 file.bin
echo -n "chunk-bytes" | sha256sum
# Compare two files' hashes
sha256sum a.bin b.bin
# Show why salting matters (same password -> different hashes)
python3 - <<'EOF'
import hashlib, os
pw = b"Summer2026!"
for _ in range(2):
salt = os.urandom(16)
print((salt + hashlib.sha256(salt + pw).digest()).hex())
EOF
# Modern password hashing (Python argon2-cffi)
python3 -c "from argon2 import PasswordHasher; print(PasswordHasher().hash('pw'))"
Symmetric / asymmetric basics
# AES-256-CBC encrypt / decrypt (openssl enc intentionally rejects GCM/CCM — AEAD tag can't be validated mid-stream; use openssl cms or Python cryptography for real AEAD)
openssl enc -aes-256-cbc -pbkdf2 -salt -in secret.txt -out secret.enc
openssl enc -d -aes-256-cbc -pbkdf2 -in secret.enc -out secret.out
# RSA keypair, sign a file, verify (genpkey; genrsa is deprecated in OpenSSL 3.x)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out priv.pem
openssl pkey -in priv.pem -pubout -out pub.pem
openssl dgst -sha256 -sign priv.pem -out sig.bin doc.txt
openssl dgst -sha256 -verify pub.pem -signature sig.bin doc.txt # Verified OK
# ECDH key agreement (same shared secret both sides)
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out alice.pem
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out bob.pem
openssl pkey -in alice.pem -pubout -out alice_pub.pem
openssl pkey -in bob.pem -pubout -out bob_pub.pem
openssl pkeyutl -derive -inkey alice.pem -peerkey bob_pub.pem | xxd
# (swap inkey/peerkey to verify both sides derive the same secret)
# TLS: inspect any site's certificate chain + expiry
openssl s_client -connect walmart.com:443 -servername walmart.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
# Check TLS 1.3 vs 1.2 support
openssl s_client -tls1_3 -connect walmart.com:443 -servername walmart.com </dev/null
JWT decode & tamper demo
# Decode payload (Base64URL, NOT encrypted — this is the point)
python3 -c "
import base64, json, sys
p = sys.argv[1].split('.')[1]
p += '=' * (-len(p) % 4)
print(json.dumps(json.loads(base64.urlsafe_b64decode(p)), indent=2))
" "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwicm9sZSI6ImFkbWluIn0.SIGNATURE"
# Try the alg:none trick against a lab endpoint (e.g., jwt_tool / PyJWT; PyJWT ≥2.10 maps algorithm=None to HS256 — pass algorithm="none" explicitly)
python3 -c "
import jwt # PyJWT
print(jwt.encode({'sub':'admin','role':'admin'}, key='', algorithm='none'))
"
# Verify the unsigned token decodes only when none is explicitly allowed:
# jwt.decode(tok, key="", algorithms=["none"])
# Fix demonstration: pin the algorithm
jwt.decode(token, pub_key, algorithms=['RS256'], audience='api', issuer='idp')
Session cookie audit (browser DevTools or curl)
curl -sI https://example.com/login | grep -i set-cookie
# Expect: HttpOnly; Secure; SameSite=Lax/Strict + no token in URL
5. 1-day quick revision table
| Time | Topic | Must recall in 30 seconds | Your hook |
|---|---|---|---|
| 0:00–0:30 | CIA + AAA + non-repudiation | Definitions; only signatures → non-repudiation | — |
| 0:30–1:15 | Symmetric vs asymmetric | AES/ChaCha/DES vs RSA/ECC/DH; hybrid TLS | — |
| 1:15–1:45 | RSA + DH high-level | Factoring vs discrete log; forward secrecy | — |
| 1:45–2:30 | Hashing vs encryption, salting, bcrypt/Argon2 | One-way vs reversible; rainbow tables; slow hashes for passwords | PeerWatch SHA-256 |
| 2:30–3:00 | Digital signatures | Private sign / public verify; vs HMAC | — |
| 3:00–3:45 | PKI / CA / chain / CRL-OCSP / expiry outages | Chain of trust; revocation tradeoffs; automate renewal | — |
| 3:45–4:15 | TLS 1.2 vs 1.3, SSL deprecated | POODLE; 1-RTT; AEAD; FS mandatory | — |
| 4:15–5:00 | MFA/2FA/TOTP | RFC 6238 30s window; FIDO2 > TOTP > push > SMS | — |
| 5:00–5:45 | Kerberos TGT + Kerberoasting/AS-REP/golden | Flow + one attack each + fix | — |
| 5:45–6:30 | OAuth2 / OIDC / SAML | Delegation vs identity vs enterprise SSO | — |
| 6:30–7:30 | JWT structure + attacks + hardening | alg:none, RS256→HS256, weak secret, pin alg | — |
| 7:30–8:30 | Sessions: fixation/hijacking/flags/timeout/rotation | Cookie flag table; regen ID on login | (pool, uid) fix |
| 8:30–9:00 | RBAC vs ABAC, least privilege, PAM/JIT | Role explosion; JIT elevation; fail-closed | fail-closed UID |
| 9:00–9:30 | Password storage + stuffing vs brute vs dictionary | 4-row attack table | — |
| 9:30–10:30 | Drill Q&A aloud | Q1–Q18 in STAR/60-second answers | connect to projects |
6. Common mistakes (in interviews and in code)
- "SSL certificate" / "decrypt a hash" — say TLS; hashes are verified, not decrypted. Instant credibility loss.
- Confusing hashing with encryption — "I encrypted the passwords with SHA-256" is wrong on two counts.
- Using fast hashes (SHA-256) for passwords — fine for chunk integrity (PeerWatch), wrong for credential storage (use Argon2id/bcrypt).
- Storing JWTs in localStorage and calling it secure — XSS steals them; know the XSS-vs-CSRF tradeoff and the BFF pattern.
- Trusting the JWT
algheader — always pin algorithms server-side; mentionalg:noneand RS256→HS256 confusion unprompted if JWTs come up. - Calling JWTs "better than sessions" — they trade revocation for statelessness; the mature answer names the tradeoff and sometimes picks server-side sessions.
- Forgetting session ID regeneration at login — that's session fixation 101; say it proactively in session questions.
- "Logout = delete the cookie" — server-side invalidation is required.
- Saying 2FA when you mean MFA, or calling two passwords "two-factor."
- Describing OAuth2 as an authentication protocol — it's authorization; OIDC adds identity.
- Mixing up Kerberoasting and AS-REP roasting — Kerberoasting = TGS/SPN/service accounts/needs auth; AS-REP = pre-auth disabled/no auth needed; golden ticket = forged TGT from krbtgt (persistence, not initial access).
- Designing fail-open checks — authorization must deny by default; your own project proves you know this, so use the words "fail-closed" and "least privilege" explicitly.
- Forgetting MFA limitations — push fatigue, SIM swap, phishing proxies; nuance scores points.
- Weak secrets / no expiry on tokens, no rate limiting on login — when asked "how would you secure login", always hit: Argon2id storage + rate limit/backoff + MFA + session rotation + audit logging.
- Rambling — the loop is verbal depth: answer in 45–60 seconds, structure as definition → tradeoff → example from PeerWatch/session fix, then stop and let them probe.
- Citing a wrong cert-outage year/company — cite Epic Games Apr 2021 / Teams Feb 2020 / Ericsson-O2 Dec 2018 or don't cite a year at all.