Why This Matters
Security isn't just a checklist item—it's woven into every layer of professional software development, and you're being tested on your ability to identify vulnerabilities, implement defenses, and reason about attack vectors. In Programming Languages and Techniques III, security concepts connect directly to core topics like input handling, data structures, API design, and system architecture. Understanding these practices demonstrates that you can build software that doesn't just work, but works safely under adversarial conditions.
The practices below fall into distinct categories based on what they protect and how they protect it. Some defend against injection attacks by controlling data flow; others manage identity and access; still others focus on protecting data integrity through encryption and secure storage. Don't just memorize individual techniques—know which category each belongs to and why that defense mechanism works. When an exam question asks you to secure a feature, you need to reason from principles, not recall a random list.
Defending Against Injection Attacks
Injection attacks exploit the boundary between code and data—when user input gets interpreted as executable instructions. These defenses ensure that untrusted data never gains unintended control over your application's behavior.
- Whitelist validation—check inputs against expected formats and types, rejecting anything that doesn't match known-good patterns
- Sanitization removes dangerous characters like
<, >, ', and ; that could be interpreted as code or markup
- Defense in depth principle—validation should occur at every trust boundary, not just the UI layer
Protection Against SQL Injection
- Prepared statements with parameterized queries—the database treats user input as data, never as executable SQL
- Input validation as secondary defense—even with prepared statements, validate that inputs match expected types (e.g., integers for IDs)
- Least privilege database accounts—limit what an attacker can access even if injection succeeds
Cross-Site Scripting (XSS) Prevention
- Output encoding/escaping—convert special characters to HTML entities before rendering user content in the browser
- Content Security Policy (CSP) headers—restrict which scripts can execute, blocking inline scripts and unauthorized sources
- Context-aware encoding—different contexts (HTML, JavaScript, CSS, URLs) require different escaping strategies
Compare: SQL Injection vs. XSS—both exploit the code/data boundary, but SQL injection targets the server-side database while XSS targets the client-side browser. If an exam asks about injection attacks, distinguish by where the malicious code executes.
Managing Identity and Access
These practices control who can access your system and what they can do once authenticated. The core principle: never trust, always verify.
Authentication and Authorization
- Authentication verifies identity (who you are); authorization controls permissions (what you can do)—conflating these is a common exam trap
- Multifactor authentication (MFA)—combines something you know, have, or are to resist credential theft
- Role-based access control (RBAC)—assign permissions to roles, then assign users to roles for maintainable access management
Secure Password Storage and Management
- Adaptive hashing algorithms like bcrypt or Argon2—computationally expensive by design to slow brute-force attacks
- Salting adds unique random data to each password before hashing, defeating precomputed rainbow table attacks
- Never store plaintext passwords—even encrypted passwords are vulnerable if the key is compromised; hashing is one-way
Principle of Least Privilege
- Minimum necessary access—users, processes, and services should only have permissions required for their specific function
- Reduces blast radius—if an account is compromised, damage is limited to what that account could access
- Regular permission audits—access needs change over time; stale permissions create unnecessary risk
Compare: Authentication vs. Authorization—authentication asks "are you who you claim to be?" while authorization asks "are you allowed to do this?" A system can have strong authentication but weak authorization (or vice versa), and both must be implemented correctly.
Protecting Sessions and Requests
Web applications maintain state through sessions and cookies, creating opportunities for attackers to hijack legitimate user sessions or forge requests.
Secure Session Management
- Cookie security attributes—
HttpOnly prevents JavaScript access, Secure requires HTTPS, SameSite limits cross-origin sending
- Session ID regeneration—generate a new session ID after login to prevent session fixation attacks
- Timeout and re-authentication—expire idle sessions and require fresh authentication for sensitive operations
Cross-Site Request Forgery (CSRF) Protection
- Anti-CSRF tokens—unique, unpredictable values tied to the user's session that must accompany state-changing requests
- SameSite cookie attribute—set to
Strict or Lax to prevent cookies from being sent with cross-origin requests
- Verify request origin—check
Origin and Referer headers as an additional layer of defense
Compare: XSS vs. CSRF—XSS injects malicious scripts that run as the attacker; CSRF tricks the browser into making requests as the legitimate user. CSRF tokens don't prevent XSS, and output encoding doesn't prevent CSRF—you need both defenses.
Securing Data at Rest and in Transit
Encryption transforms readable data into ciphertext that's useless without the proper key. These practices protect sensitive information from unauthorized access even if other defenses fail.
Encryption and Data Protection
- AES-256 for data at rest—symmetric encryption for stored data; key management is the critical challenge
- TLS for data in transit—encrypts communication between client and server, preventing eavesdropping and tampering
- Key rotation and secure storage—encryption is only as strong as your key management; use hardware security modules (HSMs) or dedicated key management services
Secure API Design and Implementation
- Authentication on every endpoint—APIs are attack surfaces; use tokens (JWT, OAuth) to verify every request
- Rate limiting and throttling—prevent brute-force attacks and denial of service by limiting request frequency
- Input validation applies here too—APIs receive untrusted data just like web forms; validate and sanitize everything
Compare: Encryption at rest vs. in transit—data at rest uses symmetric encryption (same key encrypts and decrypts) while TLS uses asymmetric encryption for key exchange, then symmetric for the session. Know when each applies.
Building Security into the Development Process
Security isn't something you bolt on at the end—it must be integrated into design, implementation, and maintenance phases.
Threat Modeling and Risk Assessment
- STRIDE framework—systematically identify threats: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege
- Attack surface analysis—map all entry points (APIs, forms, file uploads) where untrusted data enters your system
- Risk prioritization—assess likelihood and impact to focus resources on the most critical vulnerabilities first
Secure Coding Practices and Code Reviews
- Security-focused code review—reviewers specifically look for injection vulnerabilities, improper error handling, and hardcoded secrets
- Static analysis tools—automated scanners catch common vulnerabilities like buffer overflows and SQL injection patterns
- Security training culture—developers who understand attack techniques write more defensive code
Error Handling and Logging Best Practices
- Generic error messages to users—never expose stack traces, database schemas, or internal paths that help attackers
- Detailed internal logging—capture enough information to investigate incidents without logging sensitive data like passwords
- Log injection prevention—sanitize data before writing to logs; attackers can exploit log files too
Compare: Threat modeling vs. code review—threat modeling happens before code is written to identify architectural risks; code review happens during development to catch implementation flaws. Both are essential; neither replaces the other.
Maintaining Security Over Time
Software security degrades as new vulnerabilities are discovered and systems evolve. These practices keep your defenses current.
Regular Security Updates and Patch Management
- Dependency scanning—tools like Dependabot or Snyk identify vulnerable libraries in your project automatically
- Staged rollouts—test patches in staging environments before production to avoid breaking changes
- Zero-day response plan—have a process for emergency patches when critical vulnerabilities are disclosed
Secure Configuration Management
- Secure defaults—disable unnecessary features, close unused ports, and require explicit opt-in for dangerous functionality
- Infrastructure as code—version-controlled configuration files make auditing and rollback possible
- Secrets management—never commit API keys, passwords, or certificates to source control; use environment variables or vaults
Compare: Patching vs. secure configuration—patching fixes known vulnerabilities in code; secure configuration prevents misuse of existing features. A fully patched system with default admin credentials is still vulnerable.
Quick Reference Table
|
| Injection Defense | Input validation, prepared statements, output encoding |
| Identity Management | Authentication, authorization, password hashing with bcrypt/Argon2 |
| Session Security | HttpOnly/Secure/SameSite cookies, CSRF tokens, session regeneration |
| Data Protection | AES encryption, TLS, key management |
| Access Control | Principle of least privilege, RBAC, permission audits |
| Proactive Security | Threat modeling, code reviews, static analysis |
| Ongoing Maintenance | Patch management, dependency scanning, secure configuration |
Self-Check Questions
-
Which two practices both defend against injection attacks but target different parts of the system? Explain where each attack executes and why the defense works.
-
A developer stores passwords using SHA-256 without salting. What specific attack does this enable, and which algorithm should they use instead?
-
Compare and contrast XSS and CSRF attacks. What does each exploit, and why doesn't a single defense mechanism stop both?
-
An API endpoint allows authenticated users to access any user's data by changing an ID parameter. Which security principle has been violated, and how would you fix it?
-
Your application has strong authentication but a penetration tester still accessed admin functionality. List three authorization-related issues that could explain this, and describe how threat modeling might have caught them earlier.