OWASP

OWASP Top 10

OWASP (Open Worldwide Application Security Project) is a non-profit that publishes the most widely used web application security standard: the OWASP Top 10. Updated every 3-4 years, it ranks the most critical security risks based on real-world vulnerability data. For .NET engineers, the Top 10 is the baseline security checklist for any web application.

OWASP Top 10 (2021)

A01: Broken Access Control

What: Users can access resources or perform actions they are not authorized for. Most common vulnerability in 2021 (94% of tested apps).
Example: A user changes ?userId=123 to ?userId=456 in a URL and accesses another user's data.
Mitigation: Enforce authorization server-side on every request. Use ASP.NET Core policy-based authorization. Deny by default — explicitly grant access, never rely on obscurity.

// ASP.NET Core: resource-based authorization
var authResult = await _authorizationService.AuthorizeAsync(User, resource, "OwnerPolicy");
if (!authResult.Succeeded) return Forbid();

A02: Cryptographic Failures

What: Sensitive data exposed due to weak or missing encryption. Formerly called "Sensitive Data Exposure".
Example: Passwords stored as MD5 hashes, HTTP instead of HTTPS, weak TLS cipher suites.
Mitigation: Use bcrypt/Argon2 for passwords (never MD5/SHA1). Enforce HTTPS everywhere. Use AES-256-GCM for data at rest. See Encryption.

A03: Injection

What: Untrusted data sent to an interpreter as part of a command or query. SQL injection, LDAP injection, OS command injection.
Example: SELECT * FROM users WHERE name = ' + userInput + ' — attacker inputs ' OR '1'='1.
Mitigation: Use parameterized queries (EF Core, Dapper with parameters). Never concatenate user input into SQL. Use ORMs. Validate and sanitize all input.

// Safe: parameterized query with Dapper
var user = await conn.QueryFirstOrDefaultAsync<User>(
    "SELECT * FROM Users WHERE Email = @Email",
    new { Email = userEmail });

A04: Insecure Design

What: Architectural flaws that cannot be fixed by correct implementation. Missing threat modeling, no rate limiting, no fraud controls.
Example: A password reset flow that allows brute-forcing the reset token because there is no rate limit or token expiry.
Mitigation: Threat model during design. Apply rate limiting (see Rate Limiting). Use secure design patterns.

A05: Security Misconfiguration

What: Default credentials, unnecessary features enabled, verbose error messages, missing security headers.
Example: A production app with app.UseDeveloperExceptionPage() enabled, exposing stack traces to users.
Mitigation: Disable developer exception pages in production. Set security headers (CSP, HSTS, X-Frame-Options). Remove default accounts. Audit cloud storage permissions.

// ASP.NET Core: only use developer exception page in development
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

A06: Vulnerable and Outdated Components

What: Using libraries, frameworks, or OS components with known vulnerabilities.
Example: A NuGet package with a known RCE vulnerability that has not been updated.
Mitigation: Use dotnet list package --vulnerable to scan for vulnerable packages. Enable Dependabot. Keep dependencies updated. Remove unused packages.

A07: Identification and Authentication Failures

What: Weak authentication mechanisms, credential stuffing, missing MFA, insecure session management.
Example: No account lockout after failed login attempts, allowing brute-force attacks.
Mitigation: Use ASP.NET Core Identity with lockout enabled. Enforce MFA for sensitive operations. Use secure session cookies (HttpOnly, Secure, SameSite=Strict).

A08: Software and Data Integrity Failures

What: Code and infrastructure that does not protect against integrity violations. Insecure deserialization, CI/CD pipeline attacks.
Example: A CI/CD pipeline that pulls dependencies from untrusted sources without verifying checksums.
Mitigation: Verify NuGet package signatures. Pin dependency versions. Use trusted package sources. Validate deserialized data.

A09: Security Logging and Monitoring Failures

What: Insufficient logging and monitoring, allowing attacks to go undetected.
Example: A successful SQL injection attack that is not logged, allowing the attacker to exfiltrate data over days.
Mitigation: Log all authentication events (success and failure), authorization failures, and input validation failures. Use structured logging (Serilog, Application Insights). Set up alerts for anomalous patterns.

A10: Server-Side Request Forgery (SSRF)

What: The server makes HTTP requests to attacker-controlled URLs, potentially accessing internal services.
Example: An image upload feature that fetches images by URL — attacker provides http://169.254.169.254/latest/meta-data/ (AWS metadata endpoint).
Mitigation: Validate and allowlist URLs before making server-side requests. Block requests to private IP ranges. Use network-level controls (VPC security groups).

Pitfalls

Checklist Security (False Sense of Compliance)

What goes wrong: a team works through the OWASP Top 10 as a checklist, marks each item 'done,' and considers the application secure. The Top 10 is a minimum baseline, not a comprehensive security program.

Why it matters: the Top 10 covers the most common vulnerabilities, not all vulnerabilities. Application-specific logic flaws, business logic bypasses, and supply chain attacks are not covered.

Mitigation: use the Top 10 as a starting point. Add threat modeling, penetration testing, and security code review. Treat security as a continuous process, not a one-time audit.

Stale Dependency Scanning

What goes wrong: dotnet list package --vulnerable is run once during setup and never again. New CVEs are published daily; a package that was safe last month may be vulnerable today.

Mitigation: automate dependency scanning in CI (GitHub Dependabot, OWASP Dependency-Check). Set up alerts for new CVEs in your dependency tree. Pin dependency versions and review updates regularly.

Tradeoffs

Security scanning depth vs CI speed

Approach Coverage CI Impact When to use
SAST (static analysis) Code patterns, known vulnerabilities Low (seconds) Every PR
DAST (dynamic analysis) Runtime vulnerabilities, auth bypasses High (minutes) Nightly or pre-release
Penetration testing Business logic, chained vulnerabilities Very high (days) Quarterly or pre-launch
Dependency scanning Known CVEs in dependencies Low (seconds) Every PR

Decision rule: run SAST and dependency scanning on every PR (fast, automated). Run DAST nightly against a staging environment. Schedule penetration testing quarterly or before major releases. Do not skip DAST because it is slow — it catches vulnerabilities that static analysis cannot.

Questions

References


Whats next