Week Introduction
Software vulnerabilities are not random bugs โ they're flaws in how programs handle unexpected input, manage memory, or enforce security boundaries. Attackers exploit the gap between what developers intended and what the code actually does.
This week explores the software security lifecycle: how bugs emerge during development, how they become exploitable vulnerabilities, and why secure development practices are essential defensive controls. You'll learn to think about code from an attacker's perspective โ where assumptions break down.
Learning Outcomes (Week 8 Focus)
By the end of this week, you should be able to:
- LO6 - Software Security: Explain how common vulnerability classes (injection, memory errors, logic flaws) arise and how they're exploited
- LO2 - Technical Foundations: Connect software behavior to security outcomes (understand "why" exploits work, not just "what" they do)
- LO4 - Risk Reasoning: Prioritize software vulnerabilities using CVSS, exploitability, and business context
Lesson 8.1 ยท From Bug to Vulnerability: When Mistakes Become Security Flaws
Definition: Bug vs Vulnerability
-
Bug: Any deviation from intended program behavior (functional error)
Example: Calculator displays wrong result, button doesn't respond, formatting error
Impact: Usability issue, incorrect output, annoying but not exploitable -
Vulnerability: A bug that can be exploited to violate security
properties (CIA triad)
Example: Input validation bug allows SQL injection, memory error enables code execution
Impact: Confidentiality breach, integrity violation, availability disruption
Critical insight: Context determines if bug becomes vulnerability
The same bug can be:
- Harmless in offline calculator app (no security boundary)
- Critical vulnerability in web payment system (handles untrusted input, processes money)
How bugs arise (common root causes):
-
1. Incorrect assumptions about input
Developer assumes: "Users will only enter numbers in this field"
Reality: Attacker enters' OR '1'='1(SQL injection)
Why it happens: Developers think about valid use cases, not adversarial input -
2. Boundary condition errors
Developer assumes: "This array will never have more than 100 items"
Reality: Attacker sends 1000 items, overflows buffer
Why it happens: Edge cases not tested, assumptions not validated -
3. Race conditions and timing issues
Developer assumes: "These two operations will happen in order"
Reality: Concurrent requests create race condition, bypass security check
Why it happens: Complexity of multi-threaded systems -
4. Logic errors in security checks
Developer assumes: "If user is authenticated, they can access this resource"
Reality: Missing authorization check โ any authenticated user accesses any resource
Why it happens: Confusion between authentication and authorization -
5. Dependency vulnerabilities
Developer assumes: "This third-party library is secure"
Reality: Library has known CVE, app inherits vulnerability
Why it happens: Unpatched dependencies, transitive dependencies
Why software bugs are inevitable:
- Complexity: Modern apps = millions of lines of code, hundreds of dependencies
- Time pressure: Ship fast vs test thoroughly trade-off
- Human fallibility: Developers make mistakes, miss edge cases
- Evolving requirements: Code changes introduce regressions
Lesson 8.2 ยท Common Vulnerability Classes (OWASP/CWE Perspective)
Core principle: Most vulnerabilities fall into recurring patterns. Understanding vulnerability classes helps predict and prevent them.
Major vulnerability categories (from OWASP Top 10 / CWE):
-
1. Injection Flaws (SQL, Command, LDAP, etc.)
Root cause: Untrusted data interpreted as code/commands
How it works: Attacker inserts malicious input that gets executed by interpreter
Example: SQL injection โusername: admin' OR '1'='1bypasses login
Impact: Data breach, authentication bypass, remote code execution
Defense: Parameterized queries, input validation, least privilege database accounts -
2. Broken Authentication / Session Management
Root cause: Weak credential handling, predictable sessions, missing MFA
How it works: Attacker guesses/steals credentials or hijacks sessions
Example: Session tokens in URL, weak password reset, no account lockout
Impact: Account takeover, identity theft, unauthorized access
Defense: Strong password policies, MFA, secure session management (HTTPOnly cookies, short expiry) -
3. Broken Access Control (Authorization Failures)
Root cause: Missing or incorrect permission checks
How it works: Authenticated user accesses resources they shouldn't (IDOR, privilege escalation)
Example: Change URL from/user/123/profileto/user/456/profileโ access other user's data
Impact: Unauthorized data access, privilege escalation
Defense: Server-side authorization checks, deny-by-default, access control testing -
4. Cross-Site Scripting (XSS)
Root cause: Unescaped user input displayed in web pages
How it works: Attacker injects JavaScript that executes in victim's browser
Example: Comment field contains<script>steal(cookie)</script>โ executes when others view comment
Impact: Session hijacking, credential theft, malware delivery
Defense: Output encoding, Content Security Policy (CSP), HTTPOnly cookies -
5. Memory Safety Issues (Buffer Overflow, Use-After-Free)
Root cause: Unsafe memory operations in languages like C/C++
How it works: Attacker overflows buffer to overwrite adjacent memory (code pointers, return addresses)
Example: Send 1000 bytes to function expecting 100 โ overflow overwrites return address, hijacks control flow
Impact: Remote code execution, privilege escalation
Defense: Memory-safe languages (Rust, Go), bounds checking, ASLR, DEP -
6. Insecure Deserialization
Root cause: Trusting serialized data from untrusted sources
How it works: Attacker crafts malicious serialized object that executes code when deserialized
Example: Java deserialization gadget chains leading to RCE
Impact: Remote code execution, authentication bypass
Defense: Avoid deserializing untrusted data, integrity checks, least privilege
Pattern recognition for defenders:
When reviewing code or assessing systems, ask:
- Where does untrusted input enter? (Web forms, APIs, file uploads, network packets)
- Is input validated before use? (Allow-list, sanitization, encoding)
- Where are authorization checks? (Server-side, per-resource, least privilege)
- How is memory managed? (Bounds checking, safe languages, automated tools)
- Are sessions/credentials secure? (MFA, secure storage, proper expiry)
Lesson 8.3 ยท What Is an Exploit? From Vulnerability to Attack
Definition: An exploit is a technique or code that takes advantage of a vulnerability to achieve an attacker's goal (data theft, code execution, privilege escalation, denial of service).
Vulnerability vs Exploit vs Payload:
-
Vulnerability: The weakness in the software (the "what")
Example: Buffer overflow in login function (CWE-120) -
Exploit: The method to trigger the vulnerability (the "how")
Example: Crafted username with 500 'A' characters overflows buffer -
Payload: The malicious code delivered via exploit (the "goal")
Example: Shellcode that spawns reverse shell, giving attacker remote access
Exploit development lifecycle (attacker perspective):
- Discovery: Find vulnerability (fuzzing, code review, public disclosure)
- Analysis: Understand root cause and exploitability (can I control execution?)
- Weaponization: Develop reliable exploit (bypasses ASLR/DEP, works across versions)
- Delivery: Get exploit to target (phishing, watering hole, direct attack)
- Execution: Trigger vulnerability, deliver payload, establish persistence
Why exploits are difficult (defender advantage):
- Reliability: Exploits often crash systems before succeeding (gets detected)
- Defenses: ASLR, DEP, CFI, stack canaries make exploitation harder
- Patching: Window of exploitability closes once patch is released
- Detection: IDS/IPS, endpoint protection can catch exploit attempts
Types of exploits (by delivery/scope):
-
Remote exploits: Triggered over network without authentication
Example: EternalBlue (WannaCry) โ SMB vulnerability, no user interaction
Risk level: Critical (wormable, massive scale) -
Local exploits: Require existing access to escalate privileges
Example: Privilege escalation from standard user to root/admin
Risk level: High (used for lateral movement after initial compromise) -
Client-side exploits: Require user action (click link, open file)
Example: Malicious PDF exploiting Adobe Reader vulnerability
Risk level: Medium-High (requires social engineering)
Exploit maturity levels (how easy is exploitation?):
- Theoretical: Vulnerability exists but no exploit code available
- Proof-of-Concept (PoC): Demonstrates vulnerability, unreliable/crashes
- Functional: Works reliably in controlled environment
- Weaponized: Production-ready, bypasses defenses, used in the wild
Lesson 8.4 ยท Secure Software Development Lifecycle (SSDLC)
Core insight: Finding and fixing bugs after deployment is 10-100x more expensive than preventing them during development. Security must be built in, not bolted on.
Why "security as afterthought" fails:
- Architectural flaws can't be patched (require redesign)
- Deployed code is in attacker's hands (reverse engineering, fuzzing)
- Legacy systems accumulate vulnerabilities faster than they're patched
- Users delay updates (unpatched systems remain vulnerable for years)
Secure SDLC phases (security at each stage):
-
1. Requirements & Design
Security activities: Threat modeling, security requirements, abuse cases
Goal: Identify security boundaries, trust assumptions, high-risk components
Example: "Payment processing must use end-to-end encryption, not store full card numbers" -
2. Implementation (Coding)
Security activities: Secure coding standards, code review, static analysis (SAST)
Goal: Prevent common vulnerability classes (injection, XSS, memory errors)
Example: Mandatory use of parameterized queries, input validation frameworks -
3. Testing
Security activities: Dynamic testing (DAST), penetration testing, fuzzing
Goal: Find vulnerabilities in running application before attackers do
Example: Automated scanners test for OWASP Top 10, manual pentest simulates attacker -
4. Deployment
Security activities: Security configuration review, secrets management, least privilege
Goal: Deploy securely configured, harden production environment
Example: Disable debug modes, rotate credentials, enable security logging -
5. Operations & Maintenance
Security activities: Patch management, monitoring, incident response, dependency updates
Goal: Maintain security posture over time, respond to new threats
Example: Monthly patching cycle, SIEM alerts for anomalies, CVE monitoring
Key secure development practices:
- Input validation: Never trust user input โ validate type, length, format, range
- Output encoding: Escape data before rendering (HTML, SQL, shell contexts)
- Least privilege: Code runs with minimum necessary permissions
- Defense in depth: Multiple layers of security (authentication + authorization + encryption + logging)
- Fail securely: Errors deny access by default, don't leak sensitive info
- Security by design: Consider security from day one, not after features are built
Modern tooling for secure development:
- SAST (Static Application Security Testing): Analyze source code for vulnerabilities (SonarQube, Checkmarx)
- DAST (Dynamic Application Security Testing): Test running app for vulnerabilities (OWASP ZAP, Burp Suite)
- SCA (Software Composition Analysis): Identify vulnerable dependencies (Snyk, Dependabot)
- Secret scanning: Detect hardcoded credentials in code (GitGuardian, TruffleHog)
- Fuzzing: Automated testing with malformed inputs (AFL, libFuzzer)
Lesson 8.5 ยท Why Software Security Is Hard (and Getting Harder)
Fundamental challenges that make secure software difficult:
-
1. Complexity is the enemy of security
Reality: Modern apps = millions of lines of code + hundreds of dependencies
Problem: Bugs hide in complexity, interactions create emergent vulnerabilities
Example: Average web app uses 100+ npm packages, each with their own dependencies (supply chain risk) -
2. Defenders must be right every time, attackers only once
Reality: One missed input validation can compromise entire system
Problem: Exhaustive testing is impossible (infinite input combinations)
Example: Equifax breach โ one unpatched Apache Struts vulnerability -
3. Legacy code and technical debt
Reality: Production systems run code written 10-20 years ago
Problem: Unsafe languages (C/C++), outdated libraries, no security reviews
Example: Critical infrastructure still runs COBOL, Windows XP in medical devices -
4. Speed vs security trade-off
Reality: Business pressure to ship fast (features > security)
Problem: Security testing cut to meet deadlines, technical debt accumulates
Example: "Move fast and break things" culture deprioritizes security -
5. Evolving attack surface
Reality: Cloud, mobile, IoT, AI create new vulnerability classes
Problem: Defenders must learn new platforms faster than attackers exploit them
Example: AI prompt injection, cloud misconfigurations, IoT botnets
Why perfect code is impossible:
- Humans write code, humans make mistakes (cognitive limitations)
- Requirements change, code rots (today's secure code becomes tomorrow's legacy)
- Emergent behavior from component interactions (works individually, fails together)
- Zero-days exist (unknown vulnerabilities in "secure" code)
Realistic security posture:
Accept that vulnerabilities will exist. Focus on:
- Reducing vulnerability density: Secure coding, code review, testing
- Reducing time to patch: Fast incident response, automated updates
- Limiting blast radius: Least privilege, sandboxing, segmentation
- Detecting exploitation early: Monitoring, logging, anomaly detection
Self-Check Questions (Test Your Understanding)
Answer these in your own words (2-3 sentences each):
- What is the difference between a bug and a vulnerability? Give one example of each.
- Explain one common vulnerability class (injection, XSS, broken access control, etc.). How does it arise and what's the impact?
- What is an exploit? How does it differ from the vulnerability itself?
- Why is security "by design" cheaper than security "by patch"? Connect to SDLC phases.
- Why is achieving "perfect software security" impossible? Name at least two fundamental challenges.
Lab 8 ยท Vulnerability Analysis and Secure Design
Time estimate: 40-50 minutes
Objective: Analyze how coding errors become security vulnerabilities. You will trace the path from bug to exploit to impact, then propose secure development practices that would have prevented the vulnerability.