sábado, 10 de outubro de 2015

Disponibilizando o servidor na porta 80


Esses dias tive que reconfigurar meu servidor (um droplet do digitalocean) e me deparei com um problema antigo. Configurar o servidor na porta 80. Obviamente isso é extremamente básico de se fazer MAAAAAS a maioria das pessoas coloca o sistema em risco quando faz isso.

Primeiramente, porque colocar o servidor na porta 80 ? Os servidores Java que baixamos vem por default rodando na porta 8080 que é uma porta secundária destinada ao protocolo HTTP. Já o servidor padrão do ruby e do nodejs rodam na porta 3000. É uma questão básica de escolha. No entanto se você acessar um site que roda em um servidor configurado na porta diferente da porta 80, você deverá declará-la. Imagine como seria chato acessar o G1 com a url www.g1.com.br:8080. Isso sem contar que você deveria saber qual a porta cada site está rodando. Pra facilitar a vida, convencionou-se que a porta padrão HTTP seria a 80 e caso a porta fosse omitida, então significa que deve-se usar a porta padrão. Resumindo, digitar www.g1.com.br é a mesma coisa que digitar www.g1.com.br:80 . Massa né ? Pode tentar... Ambas funcionarão.

Os sistemas operacionais se comunicam com outros programas através de portas que vão da porta 1 até a porta 65 mil e alguma coisa... No entanto as primeiras mil portas são especiais pois são usadas pelo sistema operacional. Logo, para rodar um programa usando uma dessas portas, precisamos de duas coisas: que a porta não esteja sendo usada e usar a conta de administrador. É aí que começa o problema...

Quando você utiliza a conta de administrador pra iniciar o servidor na porta 80, o processo roda com os privilégios do administrador. CASO você seja vítima de um ataque de shell reverso por exemplo, o atacante poderá fazer absolutamente tudo na sua máquina. Nenhum arquivo será poupado de um ataque com privilégios de administrador. Percebe o tamanho do problema ? Ainda mais sendo tão simples de arrumar.

Ao meu ver, a forma mais simples de arrumar é com o firewall. Você roda o seu servidor com um usuário comum e com privilégios limitados AND na porta 8080 e usa o firewall pra redirecionar o tráfego da porta 80 pra porta 8080. Simples assim! Vou explicar melhor... Você coloca seu site rodando na porta 8080. Pra acessá-lo, bastaria digitar www.meusite.com.br:8080. Quando essa requisição chegar no servidor, o firewall a processará antes de passar para o servidor. No momento que o firewall ver que é uma requisição para a porta 80, ele irá mudar pra porta 8080. Com isso a requisição irá para nosso servidor e o usuário nem vai saber que estamos rodando o servidor na porta 80.

Para fazer essa configuração, vamos começar instalando o iptables (para isso precisamos do root).


Caso seu sistema já esteja com o iptables instalado e atualizado, exibirá uma mensagem igual a essa. Caso não esteja instalado, o apt-get irá baixar os pacotes necessários e instalar. 

Agora para configurar o redirecionamento da porta 80 pra porta 8080, basta digitarmos o seguinte comando:

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

Feito isso, todos pacotes do protocolo TCP vindos pela interface de rede eth0 com porta de origem 80, serão redirecionados para a porta 8080. E o melhor. Caso o sistema seja invadido, o máximo de estrago possível de causar estará de acordo com as permissões que VOCÊ deu para o usuário. Então, veja lá. Abraço !

segunda-feira, 21 de setembro de 2015

Assinando Documentos Digitalmente (e-CPF, e-CNPJ)

Após escrever bastante, achei melhor já colocar essa frase logo no começo:

Certificados digitais existem para você assinar um documento digitalmente e ninguém ter como fraudá-lo ou alterá-lo.

O objetivo desse artigo é demostrar como assinar documentos digitalmente. Primeiramente vou falar um pouco da teoria envolvida no assunto e vou mostrar como fazer isso programaticamente utilizando a linguagem Java.

Antes de começar a falar de assinatura de documentos digitais, precisamos entender alguns conceitos importantes como criptografia de chaves públicas, funções hash e PKI. Mas vou explicar de uma forma bem básica para ficar de fácil entendimento. Logo, se voce já dominar o assunto, tenha isso em mente (pra não ficar me enchendo o saco nos comentários).

A criptografia assimétrica é uma criptografia que utiliza um par de chaves (uma chave pública e uma chave privada) para criptografar um texto. A chave privada é a mais importante e deve ser mantida e sigilo, enquanto a chave pública pode ser distribuída livremente. Tudo que é criptografado com a chave privada, só pode ser descriptografado com a chave pública, e tudo que é criptografado com a chave publica só pode ser descriptografado com a chave privada.
Tendo isso em mente, vamos a uma simples demonstração de como funciona a criptografia assimétrica (que é usada hoje em dia)


Temos acima uma imagem que ilustra mais ou menos como funciona o processo... A imagem foi retirada do site www.rtell.com.br e estou indicando só pra eu não tomar fumo com autoria de imagem... Nem sei sobre o que é o site.

João e Maria querem conversar sem que ninguém consiga ler a conversa. Então cada um entrega sua chave pública para o outro. Quando João escreve uma mensagem, ele criptografa a mensagem com a chave pública de Maria. Assim a única forma de descriptografar a mensagem, é com a chave privada de Maria. Como apenas Maria tem essa chave, apenas ela poderá descriptografar e ler a mensagem escrita por João. Seguindo a mesma lógica, quando Maria escrever pra João, ela irá criptografar com a chave pública de João pois apenas ele tem a chave privada para descriptografar. Caso uma chave privada vaze, tudo que foi escrito usando a chave pública que é par desta chave, poderá ser descriptografado. Logo, a chave privada tem que ser guardada da forma mais segura possível.

Entendido como funciona a criptografia assimétrica, vamos para as funções HASH.
As funções HASH são o mais simples possível. Sua única finalidade é fazer um resumo. Quando uma função hash é aplicada a um arquivo, ele gera um resumo do arquivo, de forma que se um byte for alterado, esse resumo deve ser completamente alterado. Existem vários algoritmos de hash como MD5, SHA-1, SHA-512 e uma caralhada de outros.

Observações importantes sobre hash:

  • O hash é uma função de mão única. Depois que um arquivo é resumido, não é possível voltar ao arquivo original (ou teríamos o melhor compactador do mundo)
  • A diferença entre cada função é o tamanho do resumo gerado e a função para gerar esse resumo. Por exemplo: o MD5 gera um resumo de 128 bits, o SHA-1 gera um resumo de 160 bits, o SHA-512 gera um resumo de 512 bits.
  • Colisões acontecem quando um algoritmo hash gera o mesmo resumo para arquivos diferentes (sim, isso acontece mas quanto melhor o algoritmo, mais difícil é de acontecer)
Pronto. Agora que esses dois pontos já estão explicados, podemos entender o que é a assinatura digital de documentos.

Vamos supor que fiz um documento em pdf e quero assiná-lo digitalmente.
  1. Primeiro eu aplicamos uma função hash para conseguir um resumo do meu documento
  2. Depois aplicamos uma algoritmo de criptografia (RSA, AES, DES, 3-DES) no modo cifragem usando minha chave privada no resultado da função de hash utilizada no passo 1. O resultado dessa operação de cifragem é a nossa assinatura digital (essa chave privada está dentro do certificado digital).
  3. Agora monto um arquivo contendo nosso arquivo original (usado no passo 1) mais o resultado da cifragem (gerado no passo 2).
Pronto. Temos um arquivo assinado e esse simples processo é chamado de assinatura digital.

Pontos importantes a serem observados:
  • A assinatura digital garante a autoria da mensagem pois é usada a chave privada para assinar
  • Caso estivéssemos assinando um documento txt, após gerar o documento assinado conseguiríamos ler o documento. Isso acontece pois a assinatura digital não realiza criptografia do conteúdo do documento. No final do arquivo, também veríamos dados ilegíveis que foram gerados nos passos 1 e 2.
  • Vamos supor que uma terceira pessoa altere meu documento (o que chamamos de falsificação). Para verificarmos se o conteúdo do arquivo está válido, realizaremos o processo de assinatura digital novamente: 
    • Primeiro pegamos a assinatura digital do arquivo.
    • Depois deciframos com a minha chave pública. Esse passo irá me retornar o HASH do documento original.
    • Por último realizamos o HASH do documento. Esse hash deverá ser igual ao resultado gerado no passo 2. Se o resultado for o mesmo, o arquivo está válido. Se der um resultado diferente, teremos a certeza que o conteúdo do arquivo foi modificado. E isso só acontece pois ao alterar o texto, a função hash gera um valor completamente diferente.
Estava procurando uma imagem para ilustrar esse passo a passo e encontrei esse blog que também está falando um pouco sobre assinatura digital (como conhecimento nunca é demais, vale a pena ler...)



Agora, antes de entrarmos na programação, vamos apenas entender sobre os certificados A1 e A3 que usaremos para assinar um documento digitalmente. Já viu cartório ? Aquela putaria que é pra reconhecer firma de documento e tudo mais ? A ideia de ambos é fazer o que o cartório faz mas de forma eletrônica. É realizar o processo descrito na imagem acima. Sabe a chave privada que é usada na imagem acima pra criptografar ? Essa chave fica guardada dentro do certificado digital.

O certificado A3 é um documento físico (um cartão na verdade) que possui dados referentes ao seu dono, bem como sua chave privada. Já o certificado A1, é um documento digital mas que também possui todos os dados que o A3 possui.




Na imagem acima temos um certificado digital de pessoa jurídica. O certificado de pessoa física é exatamente igual mas com o escrito e-CPF. Ambos contem informações sobre uma pessoa (e-CPF) ou sobre uma empresa (e-CNPJ) bem como a chave privada.

Continuando, vamos entender agora esse framework demoiselle.

Esse framework foi criado pelo SERPRO (Serviço Federal de Processamento de Dados) com o intuito de facilitar a utilização de assinatura eletrônica através da linguagem Java. A versão 1 que usei é muito boa pois se propõe a fazer isso e ponto. Já a versão 2... não entendi qual a ideia do pessoal do SERPRO ao envolver toda a plataforma EE 6 no meio de um simples processo de assinatura digital. Ao meu ver, a versão 1 foi disponibilizada como uma API e a versão 2 foi disponibilizada como framework (o que não me agrada muito). Mas vamos deixar isso de lado e partir para o que interessa...

Desde a versão 1 do demoiselle, as libs estão disponibilizadas no repositório central do maven. Então vamos fazer esse projeto já com maven.

O objetivo será gerar um programa para a plataforma Java SE que realize a assinatura digital de um documento PDF. Após isso, iremos transformar esse programa em um applet para ser usado através de sistemas web para os clientes consigam assinar documentos (vale lembrar que esse mês - setembro de 2015 - o Chrome removeu todo suporte a applets Java. Logo, as versões mais atuais desse navegador não executarão nosso applet). Vamos então ao desenvolvimento:


  • Criar projeto com maven e adicionar libs do demoiselle:
Uma dica: utilize o archetype maven-archetype-simple ou o maven-archetype-quickstart para gerar o projeto e adicione as dependencias do demoiselle no pom.xml deixando-o assim:

Arquivo pom.xml com dependências do demoiselle


  • Adicionar código para leitura dos certificados. Leitura de certificados A1 e A3:
Primeiro vamos diferenciar os dois certificados nesse passo. Os certificados A1 (cartões físicos), exigem uma senha para podermos acessar seus dados. Logo, essa senha tem que ser informada para o nosso programa em tempo de execução. O demoiselle já facilita nossa vida novamente com a classe PinCallbackHandler que irá apresentar uma caixa de texto exigindo a senha quando necessário.


Código fonte para leitura das informações do certificado digital

Callback para informar a senha do certificado A1 (cartão)

Nota importante: se você olhar o código fonte do demoiselle, ele faz uma busca por vários drivers para tentar fazer a leitura dos certificados A1. Caso não apareça essa caixa para introduzir a senha (PIN), verifique se o driver do dispositivo está instalado.

Nota do editor (sempre quis escrever isso): Sempre que eu vejo código na internet, é código porco. Não tem como copiar código da internet sem ter que refatorar tudo. Hoje entendo porque. Puta preguiça de fazer código pra não ganhar nada com isso. Ou seja, refatorem esse código safado que estou escrevendo. Mas já que comecei esse inferno de post, o jeito é terminar...

  • Assinar digitalmente um documento pdf:
  • Transformar em Applet:
  • Assinar o applet com nosso certificado para o browser não mostrar mensagem de risco:

OBS.: O texto ainda está em construção. Devo terminar ainda essa semana