Ruben Marcus

Jul 5, 2020

9 min read

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

Segurança pra quê?

XSS/CRSF:

Click Jacking:

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?

  • Entendendo o arquivo de Configuração do Strapi & sua segurança:
    O Strapi possui uma documentação rica que nos mostra como garantir a segurança do CMS :
    Possui configurações para XSS, P3P, Hsts , X-Frame-Options (Clickjacking), CORS (muito útil para setar que domínios podem acessar sua aplicação, que headers podem ser expostos),
    IP (Consegue configurar que IPS enxergam ou não sua aplicação)
  • 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.
  • DOS (Denial of Service): Você precisa limitar suas queries. Um hacker mal intencionado, se descoberto sua API GraphQL, pode montar uma série de queries que podem sobrecarregar seu servidor. Esse é um ótimo artigo no blog do Apollo que ensina alguns casos de queries maliciosas e como evitá-las.
  • 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();
});
}
};
};
  • Validando os campos: A validação de campos de forms, não serve apenas para guiar seu usuários, mas também garantir a integridade das informações transmitidas do client para o server. Isso evita uma série de códigos maliciosos serem inputados em nossos Serviços. O usuário pode ainda tentar manipular os dados, editando o HTML no DevTools, mas isso é outro problema..
  • 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:

Cacheamento de APIS:

Roadmap de Segurança do Strapi:

Ferramentas de checagem:

Referências:

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

Love podcasts or audiobooks? Learn on the go with our new app.