Iniciando com Next.js + Strapi: Segurança antes de tudo

Segurança pra quê?

Antes de começar a ver sobre os Content-Types do Strapi, antes de ver a estrutura de arquivos e rotas do Next.js, é bom discutirmos sobre Segurança.
Uma preocupação que costuma não ser acompanhada com a devida atenção em certos times, e que pode acarretar um custo bem alto, quando um projeto for colocado em produção.
Esse artigo é mais um artigo introdutório a stack Next.js +Strapi , vamos ainda abordar TypeScript, Fetch de Dados, Layouts, CI/CD e Deploy, mas antes de tudo vamos abordar segurança.

XSS/CRSF:

XSS ou Cross Site Scripting, é uma técnica maliciosa pra injetar código na nossa aplicação e burlar a segurança para sequestrar dados ou manipular uma sessão do usuário por exemplo. Esse é um artigo muito bom para se aprofundar no assunto.

Click Jacking:

Sabe quando você abre páginas que tendem a enganar o usuário, para digitar dados e no final acabam enviando esses dados para pessoas que querem usar de forma maliciosa? Ou que podem ter malware ou exploits e instalá-los na maquina do usuário?

Vulnerabilidades comuns em Rest APIS:

  • DOS & DDOS (Denial of Service) : Quando um hacker quer derrubar uma API , aplicativo ou site , ele pode disparar requisições em massa para aquele API ou endpoint.
  • Exposição de Informações Sensitivas: Quando expomos dados sensitivos do usuário, especialmente sem criptografia em nossa API. Ids, e-mails, endereços, informações de pagamento etc.
  • Ataques MIM (Man in the Middle) : Quando um hacker tenta interceptar a comunicação de client e servidor , com a intenção de roubar dados.
  • SQL Injection: Injeção de código que altere o comportamento esperado da API e do Banco de Dados. Através de uma injection um hacker consegue roubar informações, quebrar a API, alterar seu funcionamento.
  • Insecure Direct Object References: Quando você expõe uma API com endpoints como /user/id/30, e um usuário tenta acessar um ID que não compete a ele, e consegue, você está expondo Referências diretas de objetos inseguros.

Vulnerabilidades comuns em APIS GraphQL:

  • /graphql?query={__schema{types{name,fields{name}}}} :
    Se seu API GraphQL estiver público, apenas com uma query dessa, o usuário que a usa-la, consegue ver todo o esquema da sua API
  • Queries Maliciosas: Hackers podem montar queries maliciosas, sejam para roubar dados, corromper seu banco de dados, ou derrubar sua API/servidor
  • Brute-Force: Para evitar problemas com hackers tentando quebrar os dados da sua API GraphQL , você pode usar plugins como o GraphQL Rate Limit, que vai limitar quantas vezes os campos vulneráveis da sua query podem ser executados em um intervalo de tempo.

Como evitar tudo isso?

No Strapi:

  • Injeção de Credenciais: Use um arquivo .env, para não ficar injetando credenciais no meio do seu código
  • Validação: Você pode criar um middleware para validar se os dados da sua aplicação já existem e não vão ser duplicados, ou você também pode usar uma lib como o Joi , para fazer validação dos campos da sua API, mas o Strapi já possui algumas validações nativas que você pode definir nos models da sua API, apenas se você usa MongoDB
  • Roles & Permissions: O ideal é você criar uma documentação pra sua API em quais permissões e quais endpoints você vai habilitar, para não acabar caindo no erro de permitir tudo e oferecendo risco aos dados da sua API
  • Policies: Você pode setar as policies da sua API direto no código do Strapi através do ./config/policies para Policies globais e ./api/**/config/policies para endpoints locais. É uma camada extra de segurança para sua aplicação Strapi. Para setar policies com GraphQL , a documentação do Strapi tem uma página exclusiva a isso.
  • Data-Leak: Você pode passar um paramêtro private:true, dentro do parametro no model da sua API, para tirar o valor de ser acessado por qualquer pessoa. Clique aqui para saber mais
  • JWT: você pode exigir que para o usuário acessar endpoints sensíveis da sua aplicação ele esteja logado e utilize JWT.
  • Exposição de Informações Sensitivas: O Strapi permite com a edição dos controllers, quais informações podem ser acessadas nas chamadas dos endpoints. Você pode apagar certos campos e paramêtros dos resultados.
  • Setando Policies para as Queries: Você tem que customizar o Schema da sua API GraphQL, setando as policies desejadas para ter controle de quem ou como se acessa o quê na sua API
  • Acesso não autorizado: Você precisa desabilitar o GraphQL Playground, que já vem desabilitado na versão produção do Strapi (você pode desabilitar para outros ambientes aqui) , depois seu endpoint GraphQL não é mantido por uma rota mas por um middleware.
    É necessario criar um novo middleware, que vai verificar se o endpoint que queremos é o /graphql e se o usuário autenticado é o que queremos:
module.exports = strapi => {
return {
initialize() {
strapi.app.use(async (ctx, next) => {
const handleErrors = (ctx, err = undefined, type) => {
if (ctx.request.graphql === null) {
return (ctx.request.graphql = strapi.errors[type](err));
}

return ctx[type](err);
};

// check if it's a graphql request
if (ctx.request.url === '/graphql' && ctx.request.method === 'POST') {
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
try {
// get token data
const { id } = await strapi.plugins[
'users-permissions'
].services.jwt.getToken(ctx);

if (id === undefined) {
throw new Error('Invalid token: Token did not contain required fields');
}

// check if the id match to the user you want
if (id !== 'my-user-id') {
return handleErrors(ctx, 'You are not authorized to access to the GraphQL API', 'unauthorized');
}
} catch (err) {
return handleErrors(ctx, err, 'unauthorized');
}
} else {
// if no authenticated, return an error
return handleErrors(ctx, 'You need to be authenticated to request GraphQL API', 'unauthorized');
}
}

await next();
});
}
};
};
  • CRSF: Passando o paramêtro Content-Type: application/JSON, nas nossas requisições, força nossa aplicação a não usar requisições simples, e protege contra ataques
  • XSS: Esse guia é muito útil e mostra algumas regras que é bom seguir ao desenvolver nossa aplicação front-end para não ter dor de cabeça depois em questões de segurança e XSS. Esse plugin pro Next.js também ajuda a implementar XSS Protection, ajudando o browser a sanitizar áreas vulneraveis da sua aplicação.
  • Security Headers & ClickJacking: Utilizando X-Frame-Options:DENY ou SAMEORIGIN, você evita que terceiros consigam rodar sua aplicação Next.js dentro de um frame.
    O plugin next-secure-headers, te ajuda com isso. Além de implementar o FrameGuard, ele também implementa XSS Protection, contentSecurityPolicy,nosniff,noopen,forceHTTPSRedirect, referrerPolicy, expectCT.
  • JWT & Tokens Rolantes: Você pode implementar JWT, para a autenticação do seu App para garantir a integridade da sua API e ao acesso a ela, esse é um bom tutorial que ensina isso
  • Mais:
    NextAuth.js : Um plugin para te ajudar com a segurança na autenticação do seu app Next.js

SSL:

Uma etapa antes de publicarmos nosso site para produção é ambientar nosso domínio e servidor ao protocolo HTTPS. HTTPS, protege nossas requisições de serem alvos de ataques Man In the Middle, e também são cruciais para SEO pois impactam no Ranking do Google.
Algumas formas de conseguir certificados SSL gratuitamente para seu site são utilizar o serviço de:

Cacheamento de APIS:

Apesar de não ser apenas uma preocupação com segurança mas também com performance, o cacheamento de APIS pode ser recomendado para que seu site consiga funcionar mesmo em ambientes offline, mas quando se trata de dados dinâmicos, acaba sendo não recomendado, apenas para dados que não mudam constantemente. Esse é um tópico que requere um artigo só pra ele, mas caso você sinta interessado em saber mais sobre isso recomendo ler os seguintes artigos:

Roadmap de Segurança do Strapi:

O time do Strapi, está planejando algumas features que podem ajudar em futuras releases na questão de segurança:

Ferramentas de checagem:

Existem na web alguns sites e ferramentas que testam quão seguro é nossa aplicação, Seguem abaixo alguns deles:

Referências:

Software Engineer | Front-end Specialist @ Grover (https://rubenmarcus.dev)

Software Engineer | Front-end Specialist @ Grover (https://rubenmarcus.dev)