DEV Community

Código seguro com OWASP e SSDLC - 3 OWASP API Security Top 10

Image description

Fala galera,

Tudo beleza?

Dando continuidade ao conteudo de Código Seguro com OWASP e SSDLC, hoje vamos falar do OWASP API Security Top 10.

Lembrando que nessa série ja abordamos o : Owasp TOP 10 e o ASVS.

Quando eu falei do Owasp TOP 10 eu especifiquei um panorama geral de todas as aplicações, porem um pouco mais focado o OWASP API Security Top 10 é uma lista que destaca as principais vulnerabilidades de segurança encontradas em APIs (Application Programming Interfaces).

Essa lista serve como um guia para desenvolvedores, arquitetos e equipes de segurança garantirem que suas APIs estejam protegidas contra as ameaças mais comuns.

Então vamos dar uma olhada em cada vulnerabilidade, junto com um exemplo prático em .NET para ilustrar como essas vulnerabilidades podem ocorrer e como mitigá-las.

Image description

1 Broken Object Level Authorization

Essa falha ocorre quando uma API não implementa de forma adequada a autorização de nível de objeto, permitindo que um usuário acesse dados ou objetos de outros usuários sem a devida permissão.

Imagine que temos um controlador que permite que usuários acessem suas próprias contas. Se não validarmos corretamente o ID do usuário, um atacante pode acessar informações de outras contas.

[HttpGet("{id}")]
public IActionResult GetAccount(int id)
{
    var account = _accountService.GetAccountById(id);
    if (account == null)
    {
        return NotFound();
    }
    return Ok(account);
}

Enter fullscreen mode Exit fullscreen mode

Neste exemplo, um usuário mal-intencionado poderia acessar qualquer conta, alterando o parâmetro id. A solução seria garantir que o ID pertence ao usuário autenticado.

[HttpGet("{id}")]
public IActionResult GetAccount(int id)
{
    var account = _accountService.GetAccountByIdAndUserId(id, User.Identity.GetUserId());
    if (account == null)
    {
        return NotFound();
    }
    return Ok(account);
}
Enter fullscreen mode Exit fullscreen mode

2 Broken Authentication

Autorização e Autenticação parecem a mesma coisa mas não são. A autenticação quebrada pode permitir que atacantes comprometam tokens de autenticação ou senhas, assumindo a identidade de outros usuários. Isso pode acontecer devido a tokens JWT fracos, gerenciamento de sessão inadequado, ou falhas na política de senhas.

Uma API que aceita senhas fracas pode ser comprometida facilmente. Suponha que estamos usando uma autenticação baseada em token:

public IActionResult Login(string username, string password)
{
    var user = _userService.Authenticate(username, password);
    if (user != null)
    {
        return Ok(new { Token = _tokenService.GenerateToken(user) });
    }
    return Unauthorized();
}

Enter fullscreen mode Exit fullscreen mode

Implemente uma política de senhas fortes e valide corretamente os tokens de autenticação, além de utilizar por exempplo PasswordHasher para armazenar as senhas com segurança:

public IActionResult Login(string username, string password)
{
    var user = _userService.Authenticate(username, password);
    if (user != null)
    {
        var hashedPassword = _passwordHasher.HashPassword(user, password);
        if (_passwordHasher.VerifyHashedPassword(user, hashedPassword, password))
        {
            return Ok(new { Token = _tokenService.GenerateToken(user) });
        }
    }
    return Unauthorized();
}

Enter fullscreen mode Exit fullscreen mode

3 Excessive Data Exposure

Lembra do as vezes menos é mais? APIs às vezes retornam mais dados do que o necessário, o que pode expor informações sensíveis que não deveriam ser acessíveis ao cliente.

Uma API que retorna todos os dados de um usuário sem filtrar as informações sensíveis:

public IActionResult GetUser(int id)
{
    var user = _userService.GetUserById(id);
    return Ok(user);  // Retornando todos os dados, incluindo dados sensíveis
}

Enter fullscreen mode Exit fullscreen mode

Retorne apenas os dados necessários e utilize DTOs (Data Transfer Objects) para filtrar a informação sensível:

public IActionResult GetUser(int id)
{
    var user = _userService.GetUserById(id);
    var userDto = new UserDto { Name = user.Name, Email = user.Email }; // Expondo apenas os dados necessários
    return Ok(userDto);
}

Enter fullscreen mode Exit fullscreen mode

4 Lack of Resources & Rate Limiting

Se sua API não for o ultraman zero beyond, ela precisa ter limites! (Ok essa referencia é só para quem gosta de Tokusatsu). APIs que não limitam adequadamente a quantidade de requisições podem sofrer ataques de negação de serviço (o famoso DoS), esgotando recursos e causando indisponibilidade.

Usar RateLimiting com AspNetCoreRateLimit para limitar o número de requisições por cliente.

services.AddInMemoryRateLimiting();
services.Configure<IpRateLimitOptions>(options =>
{
    options.GeneralRules = new List<RateLimitRule>
    {
        new RateLimitRule
        {
            Endpoint = "*",
            Limit = 1000,
            Period = "1h"
        }
    };
});

Enter fullscreen mode Exit fullscreen mode

5 Broken Function Level Authorization

Notem como autorização é importante, por isso no top 10 existem niveis diferentes pra cada tipo. Essa vulnerabilidade ocorre quando funções diferentes na API não possuem restrições de autorização adequadas, permitindo que usuários acessem funcionalidades para as quais não possuem permissão.

Uma API que permite que qualquer usuário acesse funções administrativas.

[HttpPost]
public IActionResult DeleteUser(int id)
{
    _userService.DeleteUser(id);
    return Ok();
}

Enter fullscreen mode Exit fullscreen mode

Implemente checagens de autorização no nível de função, garantindo que apenas administradores possam realizar certas operações.

[Authorize(Roles = "Admin")]
[HttpPost]
public IActionResult DeleteUser(int id)
{
    _userService.DeleteUser(id);
    return Ok();
}

Enter fullscreen mode Exit fullscreen mode

6 Mass Assignment

Atribuição massiva ocorre quando os dados recebidos da requisição permitem que um atacante defina campos sensíveis que deveriam ser restritos, como privilégios de administrador. Isso tambem ocorre quando é possivel acessar regras de negócio que não deveriam ser expostas.

Uma API que permite que o cliente forneça dados arbitrários para atualizar um usuário.

[HttpPost]
public IActionResult UpdateUser([FromBody] User user)
{
    _userService.UpdateUser(user);
    return Ok();
}

Enter fullscreen mode Exit fullscreen mode

Utilize DTOs para garantir que apenas os campos permitidos sejam atualizados.

public class UpdateUserDto
{
    public string Name { get; set; }
    public string Email { get; set; }
}

[HttpPost]
public IActionResult UpdateUser([FromBody] UpdateUserDto userDto)
{
    _userService.UpdateUser(userDto);
    return Ok();
}

Enter fullscreen mode Exit fullscreen mode

7 Security Misconfiguration

A configuração incorreta de componentes de segurança, como falhas no CORS, permissões de arquivos inadequadas, ou erros nos cabeçalhos de segurança, pode expor a API a ataques.

Um erro frequente é permitir CORS para qualquer origem sem restrição.

services.AddCors(options =>
{
    options.AddDefaultPolicy(builder =>
    {
        builder.AllowAnyOrigin()
               .AllowAnyMethod()
               .AllowAnyHeader();
    });
});

Enter fullscreen mode Exit fullscreen mode

Restrinja as origens permitidas e implemente corretamente os cabeçalhos de segurança.

services.AddCors(options =>
{
    options.AddDefaultPolicy(builder =>
    {
        builder.WithOrigins("https://siteConfiavel.com")
               .AllowAnyMethod()
               .AllowAnyHeader();
    });
});

Enter fullscreen mode Exit fullscreen mode

8 Injection

Falhas de injeção, como SQL Injection ou NoSQL Injection (sim elas existem tambem), ocorrem quando a entrada de dados não é validada corretamente, permitindo a execução de comandos maliciosos.

Por exemplo uma API vulnerável a SQL Injection:

public IActionResult GetUser(string username)
{
    var query = $"SELECT * FROM Users WHERE Username = '{username}'";
    var user = _dbContext.Users.FromSqlRaw(query).FirstOrDefault();
    return Ok(user);
}

Enter fullscreen mode Exit fullscreen mode

Use consultas parametrizadas para evitar injeção de SQL.

public IActionResult GetUser(string username)
{
    var user = _dbContext.Users
                         .FromSqlRaw("SELECT * FROM Users WHERE Username = @username", new SqlParameter("@username", username))
                         .FirstOrDefault();
    return Ok(user);
}
Enter fullscreen mode Exit fullscreen mode

9 Improper Assets Management

Muitas vezes precisamos atualizar APIs ou por erro, melhoria ou necessidades especificas por cliente. APIs podem expor versões antigas ou descontinuadas, o que pode ser um vetor de ataque se essas versões contiverem vulnerabilidades conhecidas.

Suponha que há duas versões de uma API, mas a versão antiga ainda está acessível e vulnerável.

[Route("api/v1/[controller]")]
public class UserControllerV1 : ControllerBase
{
    // Código antigo, ainda acessível
}
Enter fullscreen mode Exit fullscreen mode

Desative e remova versões antigas e implemente políticas de versionamento claras.

[Route("api/v2/[controller]")]
public class UserControllerV2 : ControllerBase
{
    // Nova versão da API com melhorias de segurança
}
Enter fullscreen mode Exit fullscreen mode

10 Insufficient Logging & Monitoring

A falta de monitoramento adequado permite que ataques passem despercebidos e não sejam identificados a tempo, comprometendo a segurança da API. Alem disso o excesso de informação que não deveria ser retornada (um log interno com id's e etc) pode ser um prato cheio para quem quer saber uma falha, ou vulnerabilidade de sua API.

Um exemplo simples não registrar tentativas de login falhas ou acessos maliciosos.

// Nenhum registro de falha de autenticação
public IActionResult Login(string username, string password)
{
    var user = _userService.Authenticate(username, password);
    if (user == null)
    {
        return Unauthorized();
    }
    return Ok();
}

Enter fullscreen mode Exit fullscreen mode

Implemente logging adequado e use ferramentas de monitoramento.

public IActionResult Login(string username, string password)
{
    var user = _userService.Authenticate(username, password);
    if (user == null)
    {
        _logger.LogWarning($"Falha de autenticação para o usuário: {username}");
        return Unauthorized();
    }
    return Ok();
}
Enter fullscreen mode Exit fullscreen mode

São exemplos bem simples, porem implementar as boas práticas sugeridas no OWASP API Security Top 10 é fundamental para proteger suas APIs contra as vulnerabilidades mais comuns. O uso de boas práticas de segurança, como autenticação forte, autorização robusta, criptografia e monitoramento adequado, é essencial para garantir a segurança das aplicações.

Participei de uma live no canal do Microsoft Reactor com meu amigo e MVP Renato Groffe onde abordamos e detalhamos mais esse top 10 :

Alem disso gravamos 2 Episódios sobre segurança em nosso DevShow Podcast!

Espero ter ajudado!

Aquele abraço!

Top comments (0)