Como você sabe, a maioria dos ataques de hackers do BlackHat visa comprometer os dados do servidor de aplicativos e serviços da web. Ao mesmo tempo, a parte do cliente é atacada pelo menos hoje. De acordo com a definição seca, qualquer ataque é um conjunto de medidas por parte de um hacker direcionado à rede e transferência de dados, dados e sua substituição, infraestrutura e recursos técnicos da implementação do aplicativo da web. Portanto, empresas internacionais exigem que os engenheiros de desenvolvimento adotem uma abordagem mais responsável e completa da segurança dos aplicativos clientes.
No exemplo do meu projeto, falarei sobre como os aplicativos clientes estão atacando hoje e como você pode evitar essas ameaças.
As 10 principais ameaças para 2013 - 2017.Como você pode ver, entre as principais ameaças, injeção, acionamento de erros, desvio de autenticação e dados confidenciais inseguros estão em primeiro lugar. A ameaça de usar componentes com vulnerabilidades conhecidas ainda é relevante. Novas ameaças também apareceram: invasão do mecanismo de controle de acesso, desserialização e serialização inseguras de dados, registro e monitoramento insuficientemente detalhados.
Em 2001, Mark Curfy e Dennis Groves fundaram o OWASP (Open Web Application Security Project). Este é um projeto internacional de código aberto para troca de experiências no combate a vulnerabilidades em aplicativos clientes, no qual um grande número de engenheiros de segurança de aplicativos participa. A comunidade da OWASP enche o portal de vários artigos com informações sobre vulnerabilidades, materiais de treinamento, ferramentas para testar e repelir ataques. Ataques reais são descritos, seus aspectos são revelados e o que precisa ser feito para evitar ameaças é descrito.
Para entender quais ameaças são perigosas para um projeto, você precisa testá-lo completamente. Para fazer isso, a rede possui aplicativos, estruturas e serviços online que identificam automaticamente certas vulnerabilidades. Para testes locais, recomendo o uso de aplicativos e estruturas e, para testar projetos em operação, é muito útil adicionar serviços online também.

Mas mesmo que as ferramentas de teste não tenham informado nos relatórios sobre vulnerabilidades significativas (o que é improvável), ainda assim, preste atenção ao armazenamento de dados confidenciais no sistema de controle de versão, construindo o aplicativo, mecanismo de autenticação, algoritmo de hash de senha, criptografia de dados confidenciais e sistemas de registro e monitorar todo o aplicativo da web. Nesse caso, é melhor jogar com segurança e não confiar na automação cega.
Git
Primeiro, vamos falar sobre dados confidenciais no Git. Idealmente, um repositório separado de segredos é alocado para armazenar dados confidenciais. A partir dele, durante a montagem para comissionamento, dados confidenciais são puxados e costurados no aplicativo. Hoje, Hashicorp Vault, Keywhiz, segredos do Docker, Azure Key Vault e vários outros são populares.
Mas e se você não tiver esse armazenamento? Você pode usar ferramentas para codificar e ocultar arquivos com segredos que expandirão os recursos dos sistemas de controle de versão.
A primeira coisa que vem à mente é a solução universal BlackBox. Pode ser usado com qualquer sistema de controle de versão, por exemplo, Mercurial, Git, etc. Além disso, existem duas extensões para o Git: git-crypt e git-secret. Eu recomendo usar o segundo, porque me pareceu o mais conveniente de usar e mais compreensível em termos de descrição na documentação oficial. Após instalar o git-secret, você precisa inicializá-lo no repositório Git. Lembre-se de especificar a extensão a ser usada no arquivo .gitattributes . Em seguida, configure a acessibilidade dos segredos: identifique os usuários aos quais você deseja fornecer acesso a dados confidenciais. Em seguida, adicione arquivos com dados confidenciais e git-secret-hide
os através do git-secret-hide
. Você pode obter arquivos ocultos através do git-secret-reveal.
brew install git-secret //
git secret init //
git secret tell your@gpg.email  //
git secret add <files...> //
git secret hide  //
git secret reveal  //
Webpack
Outra maneira de eliminar ameaças é configurar o webpack corretamente. Para se proteger contra ataques XSS, XEE e similares, considere aderir às políticas CORS (compartilhamento de recursos de origem cruzada) e CSP (Política de segurança de conteúdo). Nos dois casos, é importante seguir os cabeçalhos para verificar a autenticidade de certos scripts usados no projeto. Os navegadores têm mecanismos para verificar a confiabilidade de uma fonte específica, por exemplo, o Safari emitirá avisos a cada etapa se o CORS e o CSP estiverem configurados incorretamente.
Existem duas maneiras de cumprir o CORS e o CSP. O primeiro é configurar os cabeçalhos para responder às solicitações no lado do servidor. O segundo é registrar as duas políticas por meio de metatags e atributos. O último método é recomendado se você tiver desenvolvedores de back-end preguiçosos, eles sempre estão ocupados e não estão interessados em políticas de segurança. As meta tags podem ser registradas imediatamente ao criar o aplicativo. Plug-ins como html-webpack-plugin, html-webpack-exclude-assets-plugin, script-ext-html-webpack-plugin, csp-html-webpack-plugin e crypto nos ajudarão com isso. Além disso, se você tiver recursos de terceiros em seu projeto (por exemplo, links para fontes externas usadas em CSS; recursos carregados da CDN e assim por diante), recomendo usar também o webpack-subresource-integridade-plugin. Assim, você informará ao navegador que os recursos carregados no script são confiáveis, não há injeções neles, são inteiros e intocados. E mesmo que alguém tenha injetado dados maliciosos no recurso e você o tenha carregado, você deve estar preparado para isso e proteger seu projeto contra essas ameaças.
Quero prestar especial atenção à ordem em que as instâncias de classe para os plug-ins são criadas. A ordem deve ser assim:
const SHA256 = (str) => CRYPTO.createHash('sha256').update( str, 'utf8').digest('base64'); const sha256Str = SHA256( '' + Date.now() ); […] new HtmlWebpackPlugin({ filename: 'index.html', template: 'public/index.html' }), new ScriptExtHtmlWebpackPlugin({ custom: [{ test: /\.js$/, attribute: 'nonce', value: 'nonce-' + sha256Str }] }), new HtmlWebpackExcludeAssetsPlugin(), new CspHtmlWebpackPlugin({ 'base-uri': '\'self\'', 'object-src': '\'none\'', 'script-src': ['\'self\'', '\'unsafe-eval\'', '\'nonce-' + sha256Str + '\''], 'style-src': ['\'unsafe-inline\'', '\'self\''] }, { devAllowUnsafe: false, enabled: true, hashingMethod: 'sha256' }), new SriPlugin({ hashFuncNames: ['sha256', 'sha384'], enabled: true }), […]
Em seguida, durante a montagem, a <hed>
exibirá a <hed>
http-equiv=content-security-policy
. As diretivas serão escritas no atributo content
, que indica quais scripts e recursos podem ser confiáveis.
A diretiva base-uri
mostra qual URL base é usado para carregar scripts, CSS, imagens e muito mais.
Os objetos geralmente não são carregados, portanto, defina none
na diretiva object-sr
c.
A diretiva script-src
se aplica aos scripts JS.
Não se esqueça de registrar um atributo do tipo uma nnce-<hshVlue>
cada vez. Além disso, o hash deve ser calculado usando o algoritmo SHA256 ou SHA512.
Quanto à diretiva style-src
, nosso projeto tem uma peculiaridade: usamos componentes estilizados para escrever CSS para cada componente e isolá-los um do outro. E, portanto, é necessário especificar que em nós o style-src
unsafe-inline
e o self
são usados no style-src
, caso contrário, os componentes estilizados cairão.

A tag de script
será automaticamente definida como não nnce-<hshVlue>
, integrity
e cross-origin
. Eles informam ao navegador que os recursos estão sendo extraídos de fontes confiáveis. Caso contrário, se o navegador perceber que o recurso não corresponde ao CSP ou ao CORS, ele simplesmente não carregará esse script ou arquivo CSS e escreverá algo no console como: "Preste atenção neste script, nesta linha na qual você inicializa ele. Olha, você tem algo errado! .
A documentação MDN , OWASP e W3C fornece diretrizes para impor políticas CSP e CORS. Além disso, quaisquer ferramentas de teste de penetração reportarão a conformidade com as regras CORS e CSP no projeto. Qualquer estrutura ou ferramenta que realize testes automáticos de um projeto apontará falhas.
Autenticação de usuário
Usamos o OpenID Connect e o protocolo Kerberos. Um padrão OpenID bastante comum é usado para autenticar usuários externos.
O Kerberos é mais adequado para a rede interna, no banco é usado para autenticação automática de funcionários. Suponha que exista uma máquina local na qual um funcionário da organização trabalhe. Ele se autenticou uma vez nesta máquina e não precisará digitar o login e a senha novamente em nenhum lugar: o funcionário efetua login em qualquer aplicativo e o sistema a autentica imediatamente. O Kerberos possui configurações sutis para a máquina local, e isso é difícil porque precisa ser configurado para cada computador e cada navegador. Se o Internet Explorer normalmente puxa as configurações padrão e o Chrome puxa as configurações do IE, o Firefox precisa configurá-lo separadamente. O Safari no MacOS X encontrará as configurações em si, mas para o Safari no Windows você precisará especificá-las manualmente.
Você precisa verificar seu aplicativo em todos os navegadores, independentemente de onde quer que funcione. Por exemplo, se eu trabalho no Windows, instalo o Safari localmente e testo meu projeto, e se trabalho no Mac, levanto o Windows em uma máquina virtual para executar o aplicativo nas versões correspondentes dos navegadores.
A autenticação pode ser implementada em aplicativos modernos usando o Passport.js e pacotes de sessão expressa, além do SDK do Auth0.
Se você não conseguir desenvolver um serviço de autenticação por meio do OpenID Connect ou de qualquer outro protocolo, use uma camada proxy, como Auth0 e similares, para que a autenticação ocorra através de uma empresa terceirizada especializada em fornecer aos usuários acesso seguro aos recursos da Internet.
Quando atualizamos alguns aplicativos para o Node.js, recomendamos o uso de pacotes Passport.js, sessão expressa etc. no servidor. Para garantir a segurança no cliente, aumentamos independentemente o componente para autenticação. Não se esqueça de especificar o atributo de preenchimento automático desativado no formulário de autenticação para excluir o preenchimento automático dos campos do formulário.
Hash de senha
O site da OWASP recomenda que você não use mecanismos de hash de senha embutidos no banco de dados. Para isso, é melhor usar pacotes como Argon2, PBKDF2, ccrypt e bcrypt. Na minha prática, eu uso o Argon2 - este é um invólucro para algoritmos GCC, PGP / GPG, etc., mas requer que você instale primeiro o pacote GCC. Esquema de uso do Argon2:
1. GCC >= 4.8 install $ brew install gcc
2. - $ npm install -g node-gyp
3. Argon2 $ npm install argon2
4. import * as ARGON from 'argon2'; ARGON.generateSalt().then( (salt: string) => { ARGON.hash('some-user-password', salt) .then((hash : string) => { console.log('Successfully created Argon2 hash:', hash);
Ofuscação
A ofuscação permite modificar o código para que ele não possa ser analisado em componentes. Afinal, os atacantes - e não apenas eles - costumam usar engenharia reversa: o programador pega um arquivo JS e começa a analisar as fontes. Assim, ele pode aprender os métodos usados ou entender o mecanismo de trabalho de um script específico para implementar código malicioso. Ou use esses mecanismos para invadir um aplicativo da Web e realizar um ataque furtivo.
Os hackers não se metem em problemas. Primeiro, eles conduzem a exploração do recurso, determinam as vulnerabilidades e o vetor de ataque. Por exemplo, eles manipulam dados ou exploram vulnerabilidades contidas em protocolos de transporte. O vetor de ataque pode ter como objetivo as vulnerabilidades de um sistema operacional específico; existem muitas em qualquer sistema UNIX. Porém, as vulnerabilidades só podem ser usadas se o administrador tiver configurado políticas de segurança mal configuradas, por exemplo, definir URLs incorretos que saem para fora.
Assim, para o reconhecimento, a engenharia reversa é usada. É impossível excluí-lo completamente, mas pode ser muito difícil. Para isso, vários ofuscadores são usados, no meu caso - javascript-obfuscator. Com base nele, é feito um plugin para o webpack - webpack-obfuscator. Também para o webpack criado obfuscator-loader. Este pacote possui configurações recomendadas para diferentes níveis de paranóico: baixo, médio e alto, eles podem ser encontrados no site oficial. Se você usar esse ofuscador, lembre-se de que ele funciona muito mal com o mecanismo de minificação incorporado ao webpack. Não use minificação e ofuscação juntos, caso contrário, o ofuscador pode quebrar completamente o código do script.
Além disso, o ofuscador aumenta o volume do script e seu carregamento. Aqui você precisa decidir por si mesmo: ou aprimora a segurança, estabilidade e confiabilidade, mas perde em conveniência e velocidade; se preocupam com a velocidade, mas esquecem a segurança, seguem as orientações.
Registro e monitoramento de ameaças
Existe uma ameaça como o uso de pacotes com vulnerabilidades já conhecidas. Analisadores de ameaças como auditoria npm, Snyk e LGTM ajudarão nessas situações. A auditoria Npm é um utilitário padrão incorporado ao npm, mas você precisa chamar constantemente esse comando ou criar muletas. Portanto, aconselho você a usar o Snyk. Este projeto possui seu próprio banco de dados com vulnerabilidades. Quando você inicia o teste, o Snyk acessa esse banco de dados e faz o upload confidencial do relatório no seu projeto do Snyk, que não é acessível a pessoas de fora. É verdade que você pode verificar seu projeto gratuitamente apenas 300 vezes e, ao verificar cada pré-confirmação, essas 300 tentativas gratuitas terminam muito rapidamente. Portanto, é melhor executar um teste para ganchos de pré-push ou pré-mesclagem.
O homem é a vulnerabilidade mais importante de qualquer sistema. Portanto, verifique o projeto antes de começar a criar o aplicativo, porque até o código-fonte pode conter algo malicioso. É bom quando apenas uma pessoa tem acesso ao projeto, mas geralmente trabalhamos em equipe. E se algum tipo de “bem-querido” aparecesse e decidisse deixar a empresa “lindamente” e deixar uma marca? Isso também deve ser lembrado.
Eu recomendo usar o pacote Snyk desde o início do projeto e iniciar a verificação no console. Tudo é simples aqui: após a instalação, defina o login e a senha da conta, e o teste em si pode ser realizado assim:
- Após instalar a dependência npm i snyk —D e especificar “snyk”: true no package.json, execute:
./node_modules/.bin/snyk wizard --dev
- No package.json, adicione scripts e configurações:
{ ... "scripts": { ... "test": "npm run test:snyk && npm run test:jest", ... "test:snyk": "snyk test --dev", ... "prepare": "npm run prepare:snyk", "prepare:snyk": "snyk protect" }, "husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", "pre-commit": "npm run test:snyk && npm run lint && npm run test:jest", "pre-push": [ "npm run test:snyk", "npm run lint", "npm run test:jest", "npm run build:production" ], ... } }, "snyk": true }
Acima, analisamos uma verificação local em busca de ameaças à segurança. Para verificar os pacotes em busca de ameaças conhecidas, também recomendo o uso do LGTM. Use este projeto em conjunto com o GitHub ou o Bitbucket (até você tentar, não era necessário), e o código será verificado imediatamente a cada push.
Monitoramento de aplicativos
Na esfera do Front-end, as ferramentas já estão bem estabelecidas; ferramentas para todos os gostos estão disponíveis para registrar e monitorar a parte do cliente. Os mais famosos são Sentry, TrackJS e InsightOps. O Sentry Server pode ser implantado em seus servidores físicos. Por exemplo, em nossos dois projetos, usamos um servidor separado, que foi totalmente configurado para registrar a operação de aplicativos. Fomos para o URL e largamos todos os logs lá. Se ocorrer um erro no aplicativo, ele será agrupado em um bloco try catch e enviado ao servidor Sentry por meio dos métodos do pacote raven. Tudo é simples e conveniente. Se você vê URLs obscuros no Sentry que não registrou, se vê incorporamentos ou mensagens obscuras, eles estão tentando invadir você. Na minha prática, isso acontecia regularmente. Por exemplo, um dos projetos - um serviço para contornar bloqueadores de anúncios e antivírus - estava constantemente tentando neutralizar e quebrá-lo.
Para o monitoramento, eu também recomendo o uso do Grafana. É importante considerar um sistema de critérios e indicadores que serão monitorados pelo sistema. Ativamos o tráfego, o retorno da publicidade, o grau de exibição de anúncios, o número de banners provenientes do Yandex etc. (projetos no grupo Rambler). Precisávamos entender como o Yandex trabalha com nossas solicitações, porque é um serviço de terceiros, o que significa que precisa ser monitorado, porque, se falhar, todo o projeto poderá entrar em colapso completamente.
Se você monitorar toda a comunicação com serviços de terceiros, encontrará rapidamente qualquer erro. A história é da minha prática: vimos que a partir do Yandex, as respostas de publicidade deixaram de aparecer. Aconteceu que eles tiveram problemas técnicos e toda a rede de publicidade caiu completamente. E não foi a Yandex quem nos informou primeiro, mas ligamos para eles e pedimos para ver o que estava acontecendo com seus serviços.
Qual é a melhor maneira de monitorar? Pegue uma URL pequena, escreva os parâmetros GET e envie uma solicitação GET para esta URL. No lado do servidor, processe esse URL, grave o log no banco de dados e aumente o monitoramento para o Grafana. Tudo é simples.
Isso é tudo. No futuro, tentarei continuar escrevendo sobre o tópico de proteger aplicativos da Web contra ameaças. Para todos que leram até o fim - desejo segurança aos seus projetos)))
Lista de fontes para leitura sobre o tópico:
www.owasp.org/index.php/Main_Page
tproger.ru/translations/webapp-security
S. Hawks. Aplicativo de página única ainda mais rápido: segurança
Seacord, Robert C. O padrão de codificação segura CERT C / Robert C. Seacord. - 2008
Chetan Karande. Protegendo aplicativos de nó - 2017
Steven Palmer. Vulnerabilidades de aplicativos da Web detectam, exploram e impedem - 2011
Robert Shimonski, Sean-Philip Oriyano. Ataques e defesa do cliente - 2012
Marcus Pinto, Dafydd Stuttard. O manual do hacker de aplicativos da Web: Encontrando e explorando falhas de segurança, 2ª edição - 2011
Karl Duuna. Proteja seu aplicativo da web Node.js. - 2015