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

Ruben Marcus
9 min readJul 5, 2020

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.

Abaixo vamos discutir, os erros mais comuns de segurança em aplicações web e como mitiga-los ou corrigi-los em nossa aplicação Strapi + Next.js:

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.

CRSF ou Cross-site request forgery, é quando alguém utiliza de uma técnica maliciosa para conseguir através de um request seja via Postman ou browser conseguir atingir nossa base de dados, apagar dados de usuários por exemplo, roubar dados de sessão ( como cartão de crédito, endereços etc) entre outras coisas.

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:

  • 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.

No GraphQL:

  • 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();
});
}
};
};

Para ser autenticado você precisa mandar um JWT no header. Veja aqui na documentação de autenticação do Strapi como fazer.

No Next.js:

  • 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:

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:

Esse é o link do Product Board. Nele vemos que o time do Strapi planeja features como: 2FA( Autenticação de dois fatores) , Token Rolante ( JWT), SSO ( Google, Twitter, Facebook, GitHub), dentre outros que já estão sendo testados: como Permissões e Regras por usuário e Permissões a níveis de campo.

Ferramentas de checagem:

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

Sentry: Sentry é uma ferramenta para monitoramento de erros de webapps. Tem suporte a diversas tecnologias e plataformas. É facilmente integrável com GraphQL, Strapi ou Next.js. Possui uma versão free para desenvolvedores.

Sqreen: Sqreen é uma plataforma de monitoramento de segurança de webapps. Pode trazer dados em tempo real de exploits em potencial, te proteger de ataques e atividades maliciosas.

O Strapi tem suporte ao Sqreen.

No Next.js você também pode usar o Sqreen, mas a configuração é um pouco mais complicada

LGTM: LGTM é uma ferramenta open-source utilizada por grandes players do mercado, como Google, Microsoft, Nasa e Dell, que verifica vulnerabilidades no seu código através de um repositório no Github ou BitBucket.
Tem uma ferramenta de code review automático e é bastante poderoso, possui alertas para te avisar sobre problemas no código e também comparativos e histórico.

SonarCloud: SonarQube é uma feramenta muito poderosa, que não só verifica Bugs e Vulnerabilidades no seu código, como alguns parâmetros como Mantenabilidade de código, Coverage de Testes, Codesmells, Duplicações de código, ele analisa seu código e pode barrar um P/R ou M/R no Github, GitLab, Azure DevOps ou BitBucket caso não atinja a qualidade de código esperada. O SonarCloud possui também um plugin para IDES que verifica em real time

Mozilla Observatory: Ferramenta da Mozilla que vai ajudar a trazer Insights sobre a segurança do seu website.

DigiCert SSL Tools: Vai checar dados do seu certificado SSL, mostrar possíveis vulnerabilidades, o Certificate Chain e a Configuração de servidor.

Qualys SSL Labs: Ferramenta um pouco mais completa que a da DigiCert.

Pen-test Tool: Website Vulnerability: Site que possui verificação de SQL Injection, XSS, Inclusão de arquivos, Execução de comandos remotos , porém é pago.

Sucuri SiteChecker: Sucuri é bem conhecido no mundo de segurança web. Detecta se seu site está blacklisted no Google, se tem links não seguros, entre outros parametros de segurança

Bom pessoal, obrigado se você chegou aqui e teve paciência, a intenção era ter dado uma idéia geral de como mitigar e solucionar diversos problemas de segurança e vulnerabilidade em aplicações web com Next.js e Strapi, antes de começarmos a usar a Stack, sendo que os conceitos aqui apontados podem ser utilizados e verificados em qualquer aplicação web não só com Node.js e JavaScript/TypeScript mas com outras linguagens e que utilizem Rest APis ou GraphQL Apis. Esse é um assunto muito extenso que poderia render vários artigos,mas tentei resumir nesse aqui.

Referências:

--

--