Em alguns artigos recentes, compartilhei como você, como desenvolvedor, pode adicionar segurança ao seu conjunto de habilidades usando os recursos da New Relic. Também me aprofundei em maneiras de atenuar os riscos ocultos de segurança das bibliotecas de software de código aberto. Esses dois blogs se concentraram no código de terceiros e em como ele pode afetar a segurança de seus aplicativos de software. Neste artigo, vou me concentrar na segurança de seu próprio código personalizado, ou seja, o código que você mesmo escreve.

Em geral, há vários métodos que você pode empregar para garantir a segurança do seu código primário. Uma abordagem comum envolve a utilização de ferramentas de análise de código estático, que examinam seu código-fonte antes da implantação em diferentes ambientes, como teste, controle de qualidade e produção. Essa prática é valiosa, pois evita a inclusão de segredos codificados em seu repositório ou em compilações de software. No entanto, essas técnicas só oferecem informações sobre os aspectos estáticos do aplicativo.

Para lidar com essa limitação, o setor geralmente conta com ferramentas dinâmicas de segurança de aplicativos, que realizam testes de caixa preta examinando o aplicativo de uma perspectiva externa. Embora essa abordagem ofereça uma perspectiva adicional, ela ainda revela apenas uma faceta da situação geral de segurança. O ponto crucial da questão é que nenhuma dessas soluções oferece uma visão abrangente.

O teste interativo de segurança de aplicativos (IAST) da New Relic foi projetado precisamente para resolver esse problema. Com o IAST, você pode aprimorar sua observabilidade porque as ferramentas da New Relic já oferecem visibilidade excepcional dos aspectos dinâmicos do seu aplicativo. A natureza do monitoramento de desempenho de aplicativos (APM) é que observamos o código enquanto ele está sendo executado nos sistemas. Isso significa que não apenas vemos o desempenho e os erros, mas também qual versão do código foi implantada em cada instância do serviço e quais métodos estão realmente sendo acionados com base na atividade em tempo real no próprio aplicativo.

Na observação de seus serviços, as preocupações com a segurança dos aplicativos, decorrentes de fontes próprias e de terceiros, são cada vez mais cruciais. O New Relic IAST desempenha um papel fundamental nesse contexto, pois elimina efetivamente a ambiguidade ao detectar rapidamente as vulnerabilidades em seus aplicativos. Ele fornece evidências conclusivas de explorações e seus locais precisos em seu código. Além disso, a ferramenta oferece procedimentos de teste e medidas de atenuação acionáveis e repetíveis, permitindo que você resolva com eficiência os problemas de segurança em ambientes de pré-produção ou desenvolvimento antes que eles se tornem exploráveis. Deixe-me dar um exemplo do que queremos dizer com acionável e repetível: para cada teste de segurança, há um comando curl associado (ou outra forma de script de teste) para que você possa voltar e testar novamente à medida que corrige seu código. O mesmo script de teste pode ser usado para verificar se o problema foi realmente corrigido sem executar todo o conjunto de testes novamente.

Como o primeiro passo em direção à segurança comprovável, o New Relic IAST permite uma verdadeira "mudança à esquerda" na segurança de software, capacitando as equipes de DevOps e de segurança a trabalharem juntas para acelerar a integração contínua e os pipelines de implantação contínua (CI/CD), permitindo que as organizações se concentrem na inovação e, ao mesmo tempo, protejam seus aplicativos no início do ciclo de vida do desenvolvimento.

Outro benefício importante de se concentrar nas vulnerabilidades exploráveis é que as ferramentas tradicionais de segurança de aplicativos muitas vezes não têm contexto, o que leva a um número excessivo de alertas que podem confundir as equipes de DevOps e de segurança, dificultando a identificação de riscos imediatos à segurança e a verificação de melhorias na segurança. Basicamente, o New Relic IAST elimina o ruído (falsos positivos) encontrado em muitas outras soluções e fornece prova de exploração para validação.

Eu disse muitas coisas, então vou lhe mostrar como o New Relic IAST funciona na prática.

Observação: antes de compartilhar como começar a usar o New Relic IAST, quero destacar um aspecto importante. O New Relic IAST simula uma bateria de ataques reais em seu aplicativo.Isso significa que os dados de teste serão usados para simular e testar vulnerabilidades exploráveis. Por esse motivo, o New Relic IAST deve ser usado apenas em ambientes de pré-produção.

Agentes de idiomas da New Relic

Os mais novos agentes New Relic APM agora incluem o recurso IAST. Todos nós sabemos como é fácil adicionar agentes APM a um aplicativo para identificar bugs e problemas de desempenho. Dê uma olhada neste exemplo intuitivo para um ambiente .NET. Agora, sem nenhum esforço extra, também podemos testar seu código personalizado quanto às 10 principais vulnerabilidades exploráveis da OWASP, como ataques de injeção.  Na minha opinião, esse é um benefício incrível do New Relic IAST e muitas partes interessadas vão adorar:

  • TI, porque eles não precisam implantar outro agente.
  • Equipes de segurança, porque isso transforma as equipes de desenvolvimento em um multiplicador de força de segurança.
  • Você, como desenvolvedor, porque já faz parte da sua cadeia de ferramentas que você já usa.

Esse recurso é muito fácil de implementar. No meu exemplo, estou usando o aplicativo OWASP Juice Shop novamente como um ambiente de demonstração.

O Juice Shop foi criado com Node.js e, portanto, adicionei o agente New Relic Node.js mais recente (o IAST foi adicionado na versão v10.3.0) ao meu aplicativo.

Seguimos a abordagem conhecida de executar o seguinte comando dentro do nosso repositório

npm install newrelic

Isso instala a biblioteca do agente New Relic em nosso aplicativo. A maneira mais fácil de configurar o agente é definir essas variáveis de ambiente:

NEW_RELIC_APP_NAME=juice-shop-mysql
NEW_RELIC_LICENSE_KEY=<your New Relic license key>

Agora você pode instalar o restante das dependências do Juice Shop com o npm install e executar o aplicativo com o npm start. Após um breve período, os dados aparecerão em sua conta New Relic na experiência familiar de curadoria para APM.

Sem nenhuma configuração adicional, o agente capturará todas as bibliotecas usadas em seu aplicativo e verificará se há alguma vulnerabilidade conhecida. Esses dados são publicados na seção Gerenciamento de vulnerabilidades do seu serviço no New Relic.

Ativar o New Relic IAST

Agora que o agente está em funcionamento e já está relatando vulnerabilidades para bibliotecas de terceiros, vamos continuar ativando os recursos do IAST.

Interrompo o aplicativo e adiciono mais duas variáveis de ambiente:

NEW_RELIC_SECURITY_ENABLED=true
NEW_RELIC_SECURITY_AGENT_ENABLED=true

A primeira variável de ambiente determina se os dados de segurança são enviados para a New Relic ou não. Quando isso estiver desativado e NEW_RELIC_SECURITY_AGENT_ENABLED for verdadeiro, o módulo de segurança será executado, mas os dados não serão enviados. A segunda permite que você ative ou desative todas as funcionalidades de segurança em geral.

Depois de defini-los, não há mais nada a ser configurado. O agente cuidará do resto para nós quando o aplicativo for executado novamente.

Simulação de ataques no mundo real

Agora que o aplicativo está em execução novamente (executando o npm start again), podemos executar nossos testes de unidade regulares. No repositório do Juice Shop, todos os testes de unidade estão localizados na pasta de testes. Por exemplo, você pode executar os testes de API executando npm run test:api. Apenas acionando esses testes, o agente identificará o contexto da solicitação, ou seja, uma transação no contexto da New Relic, incluindo todos os detalhes de parâmetros, carga útil, etc.

Por exemplo, nosso Juice Shop inclui uma API para fazer o login dos usuários do aplicativo. Esse ponto de extremidade recebe alguma carga útil, incluindo as credenciais do usuário para a autenticação do usuário.

Vamos usar o aplicativo e tentar fazer login no aplicativo com um usuário existente.

Após um breve período, você verá alguma atividade do nosso agente acessando seu aplicativo. Se um problema for identificado pelo agente, ele adicionará uma vulnerabilidade à seção New Relic Vulnerability Management. A grande diferença é que ele só fará isso se a vulnerabilidade for realmente explorável.

Vamos dar uma olhada em um exemplo.

Você pode identificar vulnerabilidades exploráveis com um ponto de exclamação na coluna Explorável. Isso significa que não apenas encontramos um problema, mas também identificamos uma prova de exploração para ele. Outro aspecto importante ao analisar as vulnerabilidades é que essa lista de vulnerabilidades é priorizada com base na gravidade.

Clique no problema de injeção de SQL para obter mais informações sobre o problema e a capacidade exclusiva da New Relic de fornecer prova de explorabilidade. Aqui, os usuários encontrarão uma descrição detalhada da vulnerabilidade e instâncias específicas desse problema em seu código original.

Ao clicar em uma das instâncias de injeção de SQL, você obterá mais informações sobre o local em seu código-fonte e como corrigi-lo.

Correção de uma vulnerabilidade explorável

Um dos principais recursos do New Relic IAST é o teste de repetição fornecido pela New Relic. Na seção Teste da tela, você encontrará um script de teste que pode ser usado para comprovar a capacidade de exploração. No nosso caso, executaremos esse script para provar que a injeção de SQL é realmente um problema real e explorável no Juice Shop.

Vamos abrir um terminal e executar o seguinte comando que copiamos da interface do usuário do New Relic. Observação: adicionei o URL completo na primeira linha do script. Também ajustei ligeiramente o parâmetro data-raw.

curl --location --request POST 'https://wxmqzkpgeu.us-east-1.awsapprunner.com/rest/user/login' \
--header 'x-forwarded-proto:https' \
--header 'user-agent:Mozilla/5.0 (Macintosh;Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, como Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67;' \
--header 'accept:application/json, text/plain, */*' \
--header 'sec-ch-ua-platform:"macOS"' \
--header 'sec-ch-ua-mobile:?0' \
--header 'sec-fetch-site:same-origin' \
--header 'accept-encoding:gzip, deflate, br' \
--header 'accept-language:de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6;' \
--header 'host:wxmqzkpgeu.us-east-1.awsapprunner.com' \
--header 'cookie:language=en;welcomebanner_status=dismiss;cookieconsent_status=dismiss;' \
--header 'origin:https://wxmqzkpgeu.us-east-1.awsapprunner.com' \
--header 'x-envoy-expected-rq-timeout-ms:120000' \
--header 'content-type:application/json' \
--header 'sec-fetch-dest:empty' \
--header 'x-request-id:dfc1b83b-5e24-4cb6-877b-20913a9cd54f' \
--header 'sec-ch-ua:"Not.A/Brand";v="8", "Chromium";v="114", "Microsoft Edge";v="114";' \
--header 'sec-fetch-mode:cors' \
--header 'x-forwarded-for:79.252.203.104' \
--header 'referer:https://wxmqzkpgeu.us-east-1.awsapprunner.com/' \
--header 'x-envoy-external-address:79.252.203.104' \
--data-raw '{"email": "1'"'"' OR TRUE; #","password":"12345"}'

Depois que esse script for executado, você perceberá que recebemos alguns dados JSON de volta com informações do usuário administrador do Juice Shop. Obviamente, isso não é o que o aplicativo deveria fornecer e prova que, na verdade, temos um problema crítico e um risco associado a ele.

O local da vulnerabilidade fornecido pelo New Relic IAST nos mostra que um dos problemas de injeção de SQL está localizado em `/rest/user/login`.

Vamos dar uma olhada no código-fonte do aplicativo e abrir o arquivo `server.ts` (na raiz do repositório). Em algum ponto da linha 543, você verá qual método está sendo realmente chamado quando alguém acessa o endpoint `/rest/user/login`. O método `login()` é executado e pode ser encontrado em `/routes/login.ts`. Como desenvolvedor, posso ver a consulta SQL sendo concatenada ao adicionar a entrada do usuário diretamente na instrução SQL (linha 36).

models.sequelize.query(`SELECT * FROM Users WHERE email = '${req.body.email || ''}'' AND password = '${security.hash(req.body.password || '')}' AND deletedAt IS NULL`, { model: UserModel, plain: true })

Definitivamente, essa não é uma prática recomendada e os desenvolvedores devem evitar criar consultas SQL como essa.

O ideal é que você use consultas parametrizadas. Na estrutura do`sequelize`, isso é chamado de substituições. Portanto, o ideal é usar parâmetros na própria consulta e substituí-los pelo conteúdo usando o conceito de substituições. O código atualizado deve ser semelhante a este:

models.sequelize.query(`SELECT * FROM Users WHERE email = :email AND password = :password AND deletedAt IS NULL`,
 {
 model: UserModel,
 plain: true,
 replacements: {
 email: req.body.email || '',
 password: security.hash(req.body.password || '')
 }
     })

Vamos em frente, corrigir esse problema de código e reimplantar o aplicativo. Agora que a nova versão do nosso aplicativo está em funcionamento e os dados são informados ao New Relic, podemos executar novamente o script curl de teste.

Após a conclusão da execução, não obtemos o mesmo resultado de antes, ou seja, as credenciais de usuário do administrador do Juice Shop. Porém, recebemos uma mensagem informando que fornecemos um e-mail ou senha inválidos. Isso é realmente o que esperávamos e prova que nossa correção no código-fonte original realmente corrigiu o bug.

Se agora voltarmos à interface de usuário do New Relic e navegarmos até a seção Vulnerability Management (Gerenciamento de vulnerabilidades) do nosso aplicativo, você perceberá que ainda identificamos as duas vulnerabilidades exploráveis. No entanto, também observamos que o problema de injeção de SQL foi detectado pela última vez há cerca de quatro horas, mas o problema de XSS refletido ainda existe, pois foi relatado novamente após nossa implementação.

Conclusão

O que mostrei neste exemplo é um ciclo completo de execução de uma varredura interativa de segurança de aplicativos, examinando seu aplicativo e executando testes para encontrar vulnerabilidades exploráveis.

Não apenas identificamos um problema, mas também recebemos algumas instâncias com scripts de teste que pudemos reproduzir para realmente provar que os problemas identificados são de fato exploráveis. Depois de corrigir o problema em nosso código original, criamos uma nova versão do nosso aplicativo e a implantamos. Dessa vez, os testes do nosso agente New Relic IAST não foram capazes de executar com sucesso essa área específica do nosso aplicativo. Consegui comprovar o sucesso da correção executando o mesmo script de teste e validando que isso não é mais um problema em nosso aplicativo.