EngineeringSolution ArchitectSecurity and Observability

Session 01 - OWASP Top 10 cho .NET

Tổng Quan OWASP Top 10 (2021)

OWASP Top 10 là danh sách 10 rủi ro bảo mật web application nghiêm trọng nhất, được cập nhật định kỳ. Dưới đây là phân tích từng risk với context .NET cụ thể.

A01 - Broken Access Control

Risk: User truy cập tài nguyên ngoài quyền hạn.

csharp
// VULNERABLE: Không kiểm tra ownership
[HttpGet("orders/{orderId}")]
public async Task<IActionResult> GetOrder(int orderId)
{
    var order = await _db.Orders.FindAsync(orderId);
    return Ok(order); // Bất kỳ user nào cũng xem được order người khác
}

// SECURE: Kiểm tra ownership + authorization
[HttpGet("orders/{orderId}")]
[Authorize]
public async Task<IActionResult> GetOrder(int orderId)
{
    var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
    var order = await _db.Orders
        .Where(o => o.Id == orderId && o.UserId == userId)
        .FirstOrDefaultAsync();

    if (order is null) return NotFound();
    return Ok(order);
}

Best practices:

  • Dùng Policy-based authorization thay vì kiểm tra role cứng
  • Implement resource-based authorization với IAuthorizationHandler
  • Default deny - chỉ cho phép những gì explicitly granted

A02 - Cryptographic Failures

csharp
// VULNERABLE: MD5 cho password
var hash = MD5.HashData(Encoding.UTF8.GetBytes(password));

// SECURE: ASP.NET Identity PasswordHasher (PBKDF2 with auto-salt)
var hasher = new PasswordHasher<ApplicationUser>();
var hashed = hasher.HashPassword(user, password);
var result = hasher.VerifyHashedPassword(user, hashed, inputPassword);

Checklist:

  • Dùng DataProtection API cho encryption at rest
  • TLS 1.2+ cho tất cả connections
  • Không hardcode secrets - dùng Azure Key Vault hoặc User Secrets

A03 - Injection

SQL Injection

csharp
// VULNERABLE: String concatenation
var sql = $"SELECT * FROM Users WHERE Name = '{input}'";
await _db.Users.FromSqlRaw(sql).ToListAsync();

// SECURE: Parameterized query
await _db.Users
    .FromSqlInterpolated($"SELECT * FROM Users WHERE Name = {input}")
    .ToListAsync();

// BETTER: Use LINQ (EF Core auto-parameterizes)
await _db.Users.Where(u => u.Name == input).ToListAsync();

Command Injection

csharp
// VULNERABLE
Process.Start("cmd", $"/c ping {userInput}");

// SECURE: Validate và whitelist
if (!IPAddress.TryParse(userInput, out var ip))
    return BadRequest("Invalid IP address");

A04 - Insecure Design

Mitigation pattern: Threat modeling early in SDLC

Design IssueMitigation
Không rate limitImplement RateLimiter middleware (.NET 7+)
Thiếu input validationFluentValidation + DataAnnotations
Business logic bypassServer-side validation, không trust client
csharp
// Rate limiting trong .NET 7+
builder.Services.AddRateLimiter(opts =>
{
    opts.AddFixedWindowLimiter("api", config =>
    {
        config.PermitLimit = 100;
        config.Window = TimeSpan.FromMinutes(1);
        config.QueueLimit = 0;
    });
    opts.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});

app.UseRateLimiter();

A05 - Security Misconfiguration

csharp
// Security Headers Middleware
public class SecurityHeadersMiddleware
{
    private readonly RequestDelegate _next;

    public SecurityHeadersMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context)
    {
        var headers = context.Response.Headers;

        // Chống clickjacking
        headers["X-Frame-Options"] = "DENY";

        // Chống MIME-type sniffing
        headers["X-Content-Type-Options"] = "nosniff";

        // Chống XSS (legacy browsers)
        headers["X-XSS-Protection"] = "1; mode=block";

        // Content Security Policy
        headers["Content-Security-Policy"] =
            "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'";

        // Referrer Policy
        headers["Referrer-Policy"] = "strict-origin-when-cross-origin";

        // Strict Transport Security
        headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains";

        // Không expose server info
        headers.Remove("Server");
        headers.Remove("X-Powered-By");

        await _next(context);
    }
}

A06 - Vulnerable and Outdated Components

bash
# Scan NuGet vulnerabilities
dotnet list package --vulnerable --include-transitive

# Trong CI/CD pipeline
dotnet list package --vulnerable --format json | jq '.projects[].frameworks[].topLevelPackages[] | select(.vulnerabilities)'

Best practices:

  • Enable Dependabot hoặc Renovate cho auto PR updates
  • Audit transitive dependencies - không chỉ direct
  • Pin major versions, auto-update patch versions

A07 - Identification and Authentication Failures

csharp
// ASP.NET Identity configuration tối ưu
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(opts =>
{
    // Password policy
    opts.Password.RequiredLength = 12;
    opts.Password.RequireDigit = true;
    opts.Password.RequireUppercase = true;
    opts.Password.RequireNonAlphanumeric = true;

    // Lockout policy
    opts.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
    opts.Lockout.MaxFailedAccessAttempts = 5;
    opts.Lockout.AllowedForNewUsers = true;

    // User settings
    opts.User.RequireUniqueEmail = true;
    opts.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();

// JWT configuration với rotation
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(opts =>
    {
        opts.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ClockSkew = TimeSpan.FromMinutes(1), // Giảm từ default 5 phút
            ValidIssuer = config["Jwt:Issuer"],
            ValidAudience = config["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(config["Jwt:Key"]!))
        };
    });

A08 - Software and Data Integrity Failures

  • Verify NuGet package signatures
  • Dùng lock files (packages.lock.json) cho reproducible builds
  • CI/CD pipeline: restrict who can modify deployment scripts
  • Implement Subresource Integrity (SRI) cho CDN scripts

A09 - Security Logging and Monitoring Failures

csharp
// Audit logging cho security events
public class SecurityAuditService
{
    private readonly ILogger<SecurityAuditService> _logger;

    public SecurityAuditService(ILogger<SecurityAuditService> logger)
        => _logger = logger;

    public void LogAuthSuccess(string userId, string ipAddress)
    {
        _logger.LogInformation(
            "AUTH_SUCCESS: UserId={UserId} IP={IpAddress} Time={Time}",
            userId, ipAddress, DateTimeOffset.UtcNow);
    }

    public void LogAuthFailure(string username, string ipAddress, string reason)
    {
        _logger.LogWarning(
            "AUTH_FAILURE: Username={Username} IP={IpAddress} Reason={Reason}",
            username, ipAddress, reason);
    }

    public void LogPrivilegeEscalation(string userId, string action)
    {
        _logger.LogCritical(
            "PRIVILEGE_ESCALATION: UserId={UserId} Action={Action}",
            userId, action);
    }
}

A10 - Server-Side Request Forgery (SSRF)

csharp
// VULNERABLE: User controls URL
[HttpGet("fetch")]
public async Task<IActionResult> Fetch([FromQuery] string url)
{
    var content = await _httpClient.GetStringAsync(url);
    return Ok(content);
}

// SECURE: Whitelist allowed domains
private static readonly HashSet<string> AllowedHosts = new()
{
    "api.trusted-partner.com",
    "cdn.myapp.com"
};

[HttpGet("fetch")]
public async Task<IActionResult> Fetch([FromQuery] string url)
{
    if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
        return BadRequest("Invalid URL");

    if (!AllowedHosts.Contains(uri.Host))
        return Forbid();

    if (uri.Scheme != "https")
        return BadRequest("HTTPS required");

    var content = await _httpClient.GetStringAsync(uri);
    return Ok(content);
}

Security Checklist Summary

CategoryActionPriority
AuthenticationMFA, strong password policyP1
AuthorizationResource-based, least privilegeP1
Input ValidationServer-side, whitelist approachP1
EncryptionTLS 1.2+, Key Vault for secretsP1
HeadersSecurity headers middlewareP2
DependenciesAutomated vulnerability scanningP2
LoggingSecurity events, no sensitive data in logsP2
Rate LimitingPer-user, per-endpointP2