Categorias
PHP

Segurança no PHP II

Requisito 4: Sem erros para o usuário

Falaremos aqui de outro ponto importantíssimo na questão de segurança que é freqüentemente ignorado pelos desenvolvedores: as mensagens de erro.

As mensagens de erro foram feitas para que o desenvolvedor possa trabalhar de forma mais prática e descobrir o que ele está fazendo de errado. Observem, entretando, que, quando uma aplicação atinge maturidade suficiente para "entrar em produção", torna-se imperativo que o usuário não visualize mensagens de erro.

A razão disso é muito simples: as mensagens de erro freqüentemente trazem informações sensíveis. Observe como exemplo uma típica mensagem de falha de conexão com a base de dados:

Warning: mysql_connect() [function.mysql-connect]:
Access denied for user 'foo'@'localhost' (using password: YES)
in /usr/local/apache/htdocs/script.php on line 2

Note, através das partes destacadas, que esta mensagem me informa:

  1. O tipo de RDBMS: mysql
  2. O usuário de conexão com a base: foo
  3. Que este usuário está tentando uma conexão de dentro do servidor: localhost
  4. O caminho absoluto da raiz web: /usr/local/apache/htdocs
  5. O nome do script: script.php

É por isso que, quando colocamos uma aplicação em produção, ocultamos as mensagens de erro e as gravamos diretamente em um arquivo de log. Isto é muito simples de implementar:

Exemplo:

display_errors = Off
log_errors = On
error_log = /log/php_errors.log

Requisito #5: Esconda do servidor web o que ele não precisa acessar

Quantos de nós não usamos em nossas aplicações um arquivo, tipicamente chamado de config.php ou setup.php, onde guardamos, por exemplo, usuário e senha da base de dados?

Não há nada de errado nisso, mas cuidado: se este arquivo não gera saída de informação em HTML, por que deixá-lo acessível via web?

Para esclarecermos o problema, vamos definir 3 coisas:

  1. minha raiz web é: /usr/local/apache/htdocs
  2. meu arquivo de configuração fica localizado em /usr/local/htdocs/config/config.php
  3. este é um código típico que usa este arquivo:

require_once("/urs/local/htdocs/config/config.php");
/ bla bla bla /

Observe que o erro neste caso é confundir interpretador PHP e servidor web. O Apache (ou IIS, Xitami etc) não precisa saber onde está este arquivo. Isto é responsabilidade do interpretador.

Outro problema é que se arquivo fica desnecessariamente exposto, afinal de contas basta eu abrir um navegador e digitar:

http://www.meusite.com.br/config/config.php

Não faz sentido. Por mais que você possa argumentar que não há forma de ler o código-fonte deste arquivo, ainda assim, isto não muda o fato de que ele está desnecessariamente exposto.

A solução é simples: movemos o arquivo para fora da raiz web:

/usr/local/config/config.php

E depois apenas acertamos as permissões e corrigimos nosso código:

require_once("/urs/local/config/config.php");
/ bla bla bla /

A partir de agora nosso arquivo de configuração só pode ser lido por quem precisa dele: o interpretador PHP.

Requisito #6: Use criptografia

Dados sigilosos são chamados assim por um motivo. Quando tratamos especificamente de senhas é impressionante a quantidade de aplicações web que gravam senhas em texto puro na base de dados.

Ora, se a senha possui a importância que tem e quem a escolhe é o usuário, por que alguém mais precisa ler essa senha?

Se a senha possui este peso em nossa aplicação, não podemos nos dar o luxo de fazer com que ela trafegue pela aplicação totalmente exposta.

PHP implementa criptografia de várias formas, mas eu sugiro - para quem puder usar, pois exige instalação e configuração extra - a utilização da função mcrypt.

Os hashes MD5 e SHA-1 são opções válidas, mas o problema é a sua fragilidade: para o MD5 existe até dicionário de dados, enquanto o SHA-1 foi recentemente "quebrado" por um pesquisador chinês.

Conclusão

A implementação de regras básicas de segurança depende apena da boa vontade do desenvolvedor. Você deve ter percebido como a maior parte das soluções aqui apresentadas significam simples mudanças de hábito.

É mais do que tempo de nós, desenvolvedores PHP, deixarmos de lado nossos antigos vícios e começarmos a implementar boas práticas de programação.

Ganha o profissional, ganha a sua aplicação, ganha o seu cliente, ganha o mercado. Só quem perde nessa situação é quem tenta se aproveitar de nossa aplicação.

Referências e links sugeridos

[PHP Security Consortium] - http://phpsec.org/

Er Galvão Abbott trabalha há mais de dez anos com programação de websites e sistemas corporativos com interface web. Autodidata, teve seu primeiro contato com a linguagem HTML em 1995, quando a internet estreava no Brasil. Atualmente, além de lecionar em diversos cursos, tem se dedicado ao desenvolvimento de sistemas baseados na web, tendo nas linguagens PHP, Perl e JavaScript suas principais paixões.

Parte I

Categorias
Linux

Uma lição de history

Enquanto o autocompletar de comandos é um dos aspectos mais usados e adminirados do Bash, uma característica igualmente poderosa normalmente é ignorada. O armazenador de histórico, comumente usado para navegar para trás e para frente pela lista de comandos já executados, oferece muito mais possibilidades que  se pode imaginar. Enquanto é bem simples navegar pela lista, algumas vezes o comando desejado pode estar tão atrás no histórico que acaba sendo inviável. O comando history pode imprimir tudo o que está armazenada na tela. O uso mais óbvio para isso é redirecionar a saída do comando para o grep a fim de encontrar uma parte do comando a lembrar.

history | grep "command"

Se o comando ainda estiver no armazenador ele será mostrado em seguida com a posição que ocupa. O comando pode ser reexecutado através do seu número prefixado com o ponto de exclamação para marcar a posição. Por exemplo, !1016 executaria o comando no ponto 1016 do histórico do Bash. Outro truque é seguir o ponto de exclamação com uma parte do comando executado. O histórico será procurado e quando uma correpondência ocorrer, ela será executada.

!cd executaria o último comando cd que está no buffer. Infelizmente, os comandos não se adicionam ao histórico do buffer, então sua execução recursiva não é possível. Outra maneira de acessar o histórico de comandos é através da função de busca acessa ao pressionar Ctrl-R no terminal. Após pressionar a seqüência você será apresentado a um terminal de busca. Ao digitar o termo de buscar o primeiro comando que corresponder ao critério será exibido e ao pressionar Enter o comando será executado. O cursos esquerda ou direita insere o comando para o terminal, enquanto acima e abaixo lhe direcionam para o comando anterior e posterior, como usual.

Mais em Truques de linha de comando.

Categorias
Linux

Chaves seguras

Dependemos da encriptação para manter nossos dados seguros, mas isto significa ter várias chaves e senhas que devemos nos preocupar. Uma chave GPG tem uma senha para protegê-lo, mas e as chaves do seu sistema de arquivos ou chaves de autenticação SSH? Manter cópias em dispositivos USB parecem uma boa idéia até que você perde o dispositivo e todas as suas chaves se tornam de domínio público. Até mesmo a chave GPG não fica seguro já que é óbvio que ela significa e a senha pode ser quebrada com ataque de dicionário.

Um arquivo encriptado dos seus dados mais sensíveis tem inúmeras vantagens: tudo fica protegido com uma senha (adicionando uma segunda camada de encriptação no caso de uma chave GPG) e disfarça o conteúdo do arquivo. Alguém que encontre o seu dispositivo USB encontraria dados sem conseguir identificar o significado do seu conteúdo. O Ccrypt (http://ccrypt.sourceforge.net) é uma boa opção para fazer isso, pois possui uma encriptação forte e pode ser usado para encriptar fluxos tar, como em

tar -c file1 file2... | ccencrypt >stuff

e extrair com

ccdecrypt <stuff | tar x

Se você realmente quer ocultar seus dados, use o Steghide (http://steghide.sourceforge.net) para esconder os dados com outro arquivos, como uma foto ou arquivo de música

If you really want to hide your data, use Steghide (http://steghide.sourceforge.net) to hide the data within another file, such as a photo or music file

steghide embed --embedfile stuff --coverfile img_1416.jpg

e extrair com

steghide extract --stegofile img_1416.jpg

Mais em Truques de linha de comando.

Categorias
PHP

Enviando mensagens com o PHPMailer

O PHPMailer é um componente de envio de e-mail para servidores que exigem autenticação ou para um desenvolvedor que deseje configurações mais avançadas para a rotina de e-mail pelo php que o a função mail() não possua. É importante percebermos que um servidor que exige autenticação o faz por razões de segurança, para que o mesmo não caia nas listas negras caracterizado como um servidor de Spams.

A seguir, um exemplo de código para envio de e-mail pelo PHPMailer (para páginas de Contato ou Fale Conosco, por exemplo).

Obs: O ideal é que você baixe o PHPMailer e coloque no seu próprio servidor, deixando com que o seu domínio sempre tenha independência e rapidez no envio de mensagens através das suas páginas.

Categorias
PostGreSQL

Substituir conteúdo win1252 para utf-8

Não devo ser o primeiro a precisar exportar dados de um banco PostGreSQL instalado em Windows com codificação win1252 para um banco com codificação em utf-8 (no meu caso, em servidor Linux).

Não basta transformar o arquivo de importação para utf-8, pois os caracteres do win1252 (aspas duplas à esquerda, aspas duplas à direita, aspa simples e travessão) estarão lá, com um valor esquisito no seu banco. A minha solução foi importar assim mesmo e depois realizar um update usando uma função para corrigir.

Os exemplos de código a seguir são para: 1 - transformar para caracteres HTML; 2 - transformar para os caracteres simples.

HTML:

Simples:

Não se preocupe com os quadrados que aparecem. Se você copiar para um bom editor de texto, verá que possuem valores diferentes.

Categorias
Linux

Matando os zumbis

Se você passa algum tempo olhando para a sua lista de processos, cedo ou tarde vai se deparar com um processo chamado 'defunto' (defunct). Antes de explicar o que é um processo defunto e como removê-lo, segue um resumo de como consultar a tabela de processos usando o comando ps.

Digitar ps ux listará todos os processos atribuídos ao usuário atual e é possível especificar outro nome de usuário com ps U username. Um dos usos mais comuns para ps é de listagem de todos os processos que estão sendo executados no sistema através de ps aux. Quebrando o comando por partes, o a lista todos os processos ao invés de somente os de um único usuário, o u é o nível de detalhes retornados por cada processo e x lista os processos executados pelo daemon não executados por um terminal.

Um processo defunto é um processo iniciado por outro processo (o pai), mas que foi finalizado antes que o processo pai tenha sido completado. Isso pode acontecer se o processo pai ficou pendurado ou quebrado.

Os processos defuntos são também conhecidos por zumbis e listados com status 'Z' na saída do ps. Eles não são tão destrutivos quanto os mortos-vivos, já que eles não consomem quase recurso do sistema, mas em um sistema que está sempre ativo, como um servidor, eles podem se tornar distrativos. O segredo para matar um processo defunto é primeiro matar o pai, que estará listado na saída do ps adicionado de -l para grandes retornos. Os processos pais podem ser identificados através da coluna PPID ao invés da coluna PID, a coluna com o ID do processo. Esses são identificadores anexados a cada processo executado no seu sistema. Eles podem ser mortos usando outro comando no shell, kill -9, seguido do PPID. Obviamente, isto irá parar a tarefa pai, então se certifique primeiro de que a tarefa não é essencial. Uma vez que a tarefa pai tenha sido morto, o processo init do sistema deverá enviar o sinal correto aos processos defuntos, que devem terminar automaticamente.

Mais em Truques de linha de comando.

Categorias
Linux

Melhor que navegador

Se você precisa freqüentemente recuperar páginas da internet e achá-lo com um navegador é como usar uma marreta para quebrar um ovo, então o wget é para você. A página de informação descreve soberbamente a utilidade para download não-interativo de arquivos da internet; mas o que eles querem dizer é que às vezes ele funciona melhor do que um navegador. Você pode usar o wget num código para fazer download de páginas ou arquivos e ele é perfeito para sincronizar aquivos locais da web. Você não precisa nem utilizá-lo a partir de um script - ele funciona muito bem quando executado diretamente do terminal (http://wget.sunsite.dk).

O mais simples uso do wget é para baixar um arquivo pela URL:

wget http://localhost/somefile.tar.gz

Isto deve mostrar uma barra de download em formato texto. Infelizmente, se o site usar o protocolo HTTP, wget não suportará coringas, então, você não pode usar *.gz para fazer download múltiplo de arquivos (mas pode usar se o site é acessado por FTP). wget é bastante usado para espelhar um site inteiro. Por exemplo:

wget --mirror -p --html-extension --convert-links http://localhost

Wget atravessa todo o site e baixa o conteúdo no diretório atual. O argumento mirror habilita opções adequadas para espelhar um site - em particular, recursão por atravessar a árvore completo do site. htmlextension é usada para sites que usam também scripts CGI para gerar HTML, ou arquivos ASP que precisam ser renomeados depois de baixados. Se wget reconhecer o conteúdo, ele apenas acrescenta a extensão HTML.

Terminada a transferência, wget varre todos os arquivos locais para trocar qualquer referência remota para que o site possa ser visto desconectado.

Mais em Truques de linha de comando

Categorias
Linux

Evitando múltiplos terminais – Trabalhando com telas

Terminais virtuais são como crianças: ter um, dois ou até três trazem alegria à sua vida, mas mais do que isso põem tensão nos seus recursos. Quando trabalhando remotamente, algumas pessoas se vêem sem a possibilidade de abrir múltiplos terminais, então simplesmente abrem várias conexões SSH na mesma máquina. Isto não é apenas um desperdício de tráfego, mas também um sinal de que você é um iniciante - o que você não é, certo? Veteranos sabem que há uma maneira muito melhor para abrir múltiplos terminais e isso vem na forma do programa de telas GNU. Para começar, abra um terminal, digite screen e tecle Enter. Seus terminal será substituído por um console vazio e você pode pensar que nada aconteceu, mas na verdade aconteceu - como você verá.

Digite qualquer comando que quiser, ex: uptime, e tecle Enter. Agora pressione Ctrl+a depois c e você poderá ver outro terminal em branco. Não se preocupe, seu antigo terminal ainda está lá e ainda ativo; este é um novo. Digite outro comando, ex: ls.

Agora pressione Ctrl+a depois 0 (zero) - você verá seu terminal original novamente. Como você pode ver, Ctrl+a é a combinação que sinaliza que um comando está para vir - Ctrl+a depois c cria um novo terminal e Ctrl+c depois um número o leva ao respectivo terminal. Você pode usar Ctrl+a depois Ctrl+a para trocar para a janela selecionada anteriormente, Ctrl+a depois Ctrl+n para trocar para a próxima janela ou Ctrl+a depois Ctrl+p para trocar para a janela anterior. Para fechar janelas apenas digite exit.

Quando sua última janela fechar você também sairá do screen e será impresso na tela 'screen is terminating' para lhe lembrar. Como alternativa - e isto é o melhor coisa sobre tela - você pode pressionar Ctrl+a depois d para desanexar sua sessão de tela. Depois, de outro computador mais tarde, utilizar screen -r para recuperar de onde deixou com todos os programas e saídas intactos - mágico!

Mais em Truques de linha de comando

Categorias
Linux

SSH pelo proxy

Túneis criptografados são uma maneira útil para estabelecer uma conexão segura entre seu computador local e uma máquina remota ou servidor. Se você usar VNC, a máquina cliente remota, provavelmente você está usando um túnel; uma técnica sensível pe utilizar SSH, que é mais comumente empregada para logins remotos.

Um dos melhores usos de túneis SSH é o acesso ao Webmin, a ferramenta de configuração remota que é executada num servidor web. Você pode mudar quase tudo em seus sistema usando o Webmin, então não é inteligente deixá-lo aberto à internet. Mas se você desabilitá-la, você perde a possibilidade de configurar sua máquina. Você pode dar um jeito nisso através de túneis SSH pela porta que o Webmin usa para sua máquina local, como abaixo:

ssh -L 8090:localhost:10000 remotehost

Apenas aponte o servidor web em https://localhost:8090 para conectar ao servidor Webmin remoto. Você pode também encaminhar um serviço proxy usando SSH. Se você estivesse em uma localização onde não é possível acessar o Google ou o eBay, por exemplo, você pode criar um túnel para o servidor proxy e navegar de lá. Muitas distribuições incluem um servidor proxy, como o Squid. É preciso que seja instalado e ativo na máquina remota primeiro. Squid utiliza a porta 3128, então o comando para o túnel com o Squid seria algo como:

ssh -L 8090:localhost:3128 remotehost

Então é apenas uma questão de configurar seu navegador para usar localhost:8090 como o servidor proxy, e todas as subsequentes requisições serão passadas através do túnel SSH. Usar um servidor proxy desta maneira possibilita que você conecte a outras máquinas no proxy da rede local, como 192.168.1.1 o que também inclui serviços como configuração de servidores roteadores.

Mais em Truques de linha de comando

Categorias
Linux

Nice, nice, baby

Muitos usuários Linux conhecem o comando nice, mas poucos realmente sabem como usá-lo. Nice é um dos comandos que soa bem mas que você nunca lembra uma razão para usá-lo. Apesar disso, ele pode ser incrivelmente útil. Nice pode alterar a prioridade de execução de um processo, dando-o um maior ou menor percentual do processador. Normalmente ele é manuseado pelo agendador de tarefas do Linux. O agendador garantirá que processos com uma maior prioridade (como aqueles que envolvem entradas do usuário) terão seu compartilhamento dos recursos. Isto assegura que mesmo quando seu sistema está usando 100% da CPU você continua apto a movimentar as janelas e clicar com o mouse.

No entando, o agendador nem sempre trabalha sem problemas; certas tarefas podem sobrecarregar seu computador. Este pode ser um desobediente comando find que foi disparado por um script de limpeza da distribuição; ou a codificação de um grupo de arquivos de vídeo que levam seu computador a uma parada.

Comumente você caçaria estes processos com um comando top antes de matá-los. Nice apresenta uma alterativa mais sutil e útil. Ele reduz a prioridade das tarefas afetadas de maneira que o seu sistema continue funcional enquanto continua a executar os processos afetados. Executar um comando com uma prioridade diferente é tão simples quanto:

nice --10 updatedb

Este comando executa o updatedb com prioridade reduzia a -10. Se você executar um top, verá o valor nice abaixo da column identificada como 'NI'.

Caso queira reduzir a prioridade de um programa em execução, utilize o comando renice com o ID do processo:

renice -10 -p 1708217082: old priority 0, new priority -10

Este comando também reduz a prioridade do processo em 10 e, dependendo do valor nice dos outros processos, diminuirá o total de tempo de CPU que será compartilhado com outras tarefas.