Skip to content

OWASP Top 10


Definition

OWASP Top 10

OWASP (Open Web Application Security Project) - Top 10 most critical web application security risks. These cover ~95% of attacks on web applications.


A01: Broken Access Control

// BROKEN ACCESS CONTROL: Users acting outside permissions

// VULNERABLE: Direct object reference without authorization
@GetMapping("/api/users/{userId}/orders")
public List<Order> getUserOrders(@PathVariable String userId) {
    // Anyone can access any user's orders by changing userId!
    return orderRepository.findByUserId(userId);
}

// FIXED: Check authorization
@GetMapping("/api/users/{userId}/orders")
@PreAuthorize("#userId == authentication.principal.id or hasRole('ADMIN')")
public List<Order> getUserOrders(@PathVariable String userId) {
    return orderRepository.findByUserId(userId);
}

// VULNERABLE: Insecure direct object reference (IDOR)
@GetMapping("/documents/{id}")
public Document getDocument(@PathVariable Long id) {
    return documentRepository.findById(id);  // No ownership check!
}

// FIXED: Verify ownership
@GetMapping("/documents/{id}")
public Document getDocument(@PathVariable Long id) {
    Document doc = documentRepository.findById(id);
    if (!doc.getOwnerId().equals(getCurrentUserId())) {
        throw new AccessDeniedException("Not your document");
    }
    return doc;
}

// PREVENTION:
// • Deny by default
// • Implement access control at server-side
// • Log access control failures
// • Rate limit API calls
// • Invalidate sessions after logout

A02-A03: Crypto & Injection

// A02: CRYPTOGRAPHIC FAILURES

// VULNERABLE: Weak hashing
String hash = MD5.hash(password);  // MD5 is broken!

// FIXED: Use bcrypt
String hash = BCrypt.hashpw(password, BCrypt.gensalt(12));

// VULNERABLE: Sensitive data in URL
GET /api/users?ssn=123-45-6789

// FIXED: Use POST body or encrypt
POST /api/users
{ "ssn": "encrypted_value" }

// PREVENTION:
// • Use TLS 1.2+ for data in transit
// • Use strong algorithms (AES-256, RSA-2048+)
// • Use bcrypt/scrypt/Argon2 for passwords
// • Don't store sensitive data unnecessarily

// A03: INJECTION

// VULNERABLE: SQL Injection
String query = "SELECT * FROM users WHERE name = '" + userInput + "'";
// Input: ' OR '1'='1' --  → Returns all users!

// FIXED: Parameterized queries
PreparedStatement stmt = conn.prepareStatement(
    "SELECT * FROM users WHERE name = ?"
);
stmt.setString(1, userInput);

// VULNERABLE: Command injection
Runtime.getRuntime().exec("ping " + userInput);
// Input: google.com; rm -rf /

// FIXED: Avoid shell commands, validate input
ProcessBuilder pb = new ProcessBuilder("ping", "-c", "1", hostname);
if (!hostname.matches("^[a-zA-Z0-9.-]+$")) {
    throw new IllegalArgumentException("Invalid hostname");
}

// PREVENTION:
// • Use parameterized queries/ORMs
// • Validate and sanitize all input
// • Escape output for context (HTML, SQL, etc.)
// • Use allowlists, not blocklists

A04-A06: Design & Config

// A04: INSECURE DESIGN

// Problem: Flawed architecture, not just bugs
// Example: Password reset via security questions (weak by design)

// PREVENTION:
// • Threat modeling during design
// • Security requirements in user stories
// • Use secure design patterns
// • Limit resource consumption (rate limiting)

// A05: SECURITY MISCONFIGURATION

// VULNERABLE configurations:
// - Default credentials (admin/admin)
// - Unnecessary features enabled
// - Detailed error messages in production
// - Missing security headers

// FIXED: Proper configuration
@Configuration
class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .headers(headers -> headers
                .contentSecurityPolicy(csp -> csp
                    .policyDirectives("default-src 'self'"))
                .frameOptions(frame -> frame.deny())
                .xssProtection(xss -> xss.enable())
            )
            .csrf(csrf -> csrf.enable());
        return http.build();
    }
}

// Security headers to add:
// X-Content-Type-Options: nosniff
// X-Frame-Options: DENY
// Content-Security-Policy: default-src 'self'
// Strict-Transport-Security: max-age=31536000

// A06: VULNERABLE COMPONENTS

// Check dependencies for vulnerabilities
// Maven: mvn dependency-check:check
// Gradle: ./gradlew dependencyCheckAnalyze
// npm: npm audit

// PREVENTION:
// • Regular dependency updates
// • Automated vulnerability scanning (Dependabot, Snyk)
// • Remove unused dependencies
// • Only use trusted sources

A07-A10: Auth & More

// A07: AUTHENTICATION FAILURES

// VULNERABLE: Weak password policy
if (password.length() >= 6) { /* allow */ }

// FIXED: Strong password requirements
PasswordPolicy policy = new PasswordPolicy();
policy.setMinLength(12);
policy.setRequireUppercase(true);
policy.setRequireLowercase(true);
policy.setRequireDigit(true);
policy.setRequireSpecial(true);

// VULNERABLE: No brute force protection
// Unlimited login attempts

// FIXED: Rate limiting and lockout
@RateLimiter(name = "login", fallbackMethod = "loginFallback")
public Token login(Credentials creds) {
    if (failedAttempts.get(creds.getUsername()) > 5) {
        throw new AccountLockedException();
    }
    // ...
}

// A08: SOFTWARE AND DATA INTEGRITY FAILURES

// VULNERABLE: Unsigned updates, insecure deserialization
ObjectInputStream ois = new ObjectInputStream(untrustedData);
Object obj = ois.readObject();  // Remote code execution!

// FIXED: Avoid Java serialization, use allowlists
// Use signed packages, verify checksums
// CI/CD pipeline integrity checks

// A09: LOGGING AND MONITORING FAILURES
// See Logging best practices file

// A10: SERVER-SIDE REQUEST FORGERY (SSRF)

// VULNERABLE: Fetching arbitrary URLs
@GetMapping("/fetch")
public String fetch(@RequestParam String url) {
    return httpClient.get(url);  // Can access internal services!
}
// Attack: /fetch?url=http://169.254.169.254/metadata

// FIXED: Validate URLs, use allowlist
private static final Set<String> ALLOWED_HOSTS = Set.of("api.example.com");

public String fetch(String url) {
    URL parsed = new URL(url);
    if (!ALLOWED_HOSTS.contains(parsed.getHost())) {
        throw new SecurityException("Host not allowed");
    }
    // Also check for internal IPs, redirects, etc.
}

Tips & Tricks

Interview Tips

  • Know the top 10 categories
  • Give examples of each vulnerability
  • Explain prevention techniques
  • Discuss defense in depth

Common Questions

  • "What is SQL injection? How do you prevent it?"
  • "What are the OWASP Top 10?"
  • "How do you secure a web application?"
  • "What security headers should you use?"

Security Principles

  • Defense in depth (multiple layers)
  • Principle of least privilege
  • Fail securely (deny by default)
  • Don't trust user input
  • Keep security simple

Quick Prevention Checklist

  • [ ] Input validation
  • [ ] Output encoding
  • [ ] Parameterized queries
  • [ ] Strong authentication
  • [ ] Authorization checks
  • [ ] HTTPS everywhere
  • [ ] Security headers
  • [ ] Dependency scanning

Key Insight: Most attacks exploit known vulnerabilities. Follow the OWASP guidelines to prevent 95% of attacks.


  • *