Páginas

segunda-feira, 31 de dezembro de 2012

Proteja seu Sistema Contra: Quebra de Senha por Força Bruta



Esse artigo inicia uma série de artigos que mostrarão como podemos tornar nossos sistemas mais seguros contra ataques.

Hoje em dia é fácil obter conhecimento sobre como se tornar um hacker e atacar sites. Existe muito material na internet que ensina como atacar, quais as ferramentas a serem usadas etc. Como desenvolvedores não podemos simplesmente achar que nossos sistemas web nunca sofrerão ataques. Devemos estar preparados para repelir as principais técnicas utilizadas pelos hackers. Uma dessas técnicas é a quebra de senha por força bruta. Nesse tipo de ataque o hacker utiliza uma ferramenta que irá fazer várias combinações de caracteres até achar a senha correta. Essas combinações não são necessariamente aleatórias, mas usualmente são provenientes de uma lista de combinações pré-estabelecidas. Por exemplo, essa lista poderia conter as seguintes senhas:


'123456' (Essa é clássica!)
'adm'
'adm123'
'root'

Existem listas imensas contendo as senha mais utilizadas já disponíveis na internet para pronto uso pelos hackers. Como se precaver contra esse tipo de ataque?

Uma maneira é usando Captcha. Captcha é um mecanismo que inibe o acesso automatizado a determinada função que exija autenticação. Um exemplo clássico é a página de login dos sites que desenvolvemos. Um hacker pode entrar na página de login de um sistema e visualizar o código fonte. Vamos ver um exemplo de código:

<form action=”autenticar.php” method=”post”>
Usuário: <input type=”text” name=”usuario”/><br/>
Senha: <input type=”text” name=”senha”/><br/>
<input type=”submit” value=”Logar”/>
</form>

Visualizando o código fonte da página o hacker pode obter as informações necessárias para o seu ataque, são elas: a url do script que receberá a tentativa de login e os nomes dos campos. Esses parâmetros podem ser configurados em sua ferramenta de força bruta viabilizando assim sucessivos ataques.

O uso de captcha faz com que o script receptor não aceite acessos automatizados vindo de ferramentas, mas somente acessos legítimos de humanos. Pode-se conseguir isso por fazer uma pergunta aleatória na página de login que somente um humano pode responder e então verificar se a resposta dada foi a correta. Usualmente exibe-se ao usuário um conjunto aleatório de caracteres em uma imagem e então se pergunta a ele quais caracteres são estes.

Implementação: 
Quando a página de login é solicitada, crie uma sequencia de caracteres aleatórios, guarde essa sequencia na sessão, faça uma imagem contendo esses caracteres e exiba na página de login. Então no script que recebe a tentativa de login verifique se a sequencia de caracteres informado pelo usuário é igual a que está guardada na sessão.

Veja uma implementação em PHP:

Arquivo captcha.php

<?php
session_start();
header("Content-type: image/jpeg"); 
function captcha($largura, $altura, $tamanho_fonte, $quantidade_letras) {
    $imagem = imagecreate($largura, $altura);
    // COLOQUE ESTE ARQUIVO:  Comic_Sans_MS_Bold.ttf NA PASTA DESTE SCRIPT. PODE SER OUTRA FONTE
    $fonte = "Comic_Sans_MS_Bold.ttf"; 
    $preto = imagecolorallocate($imagem, 0, 0, 0);
    $branco = imagecolorallocate($imagem, 255, 255, 255);   
    $palavra = substr(str_shuffle("AaBbCcDdEeFfGgHhIiJjKkLlMmNnPpQqRrSsTtUuVvYyXxWwZz23456789"), 0, ($quantidade_letras));
   //COLOCA CAPCHA GERADO NA CESSÃO, DEPOIS SÓ CHAMAR $_SESSION["palavra"] PARA OBTER O CAPTCHA
    $_SESSION["palavra"] = $palavra;
    for ($i = 1; $i <= $quantidade_letras; $i++) {
        imagettftext($imagem, $tamanho_fonte, rand(-25, 25), ($tamanho_fonte * $i), ($tamanho_fonte + 10), $branco, $fonte, substr($palavra, ($i - 1), 1)); 
    }
    imagejpeg($imagem); 
    imagedestroy($imagem);
}

//ALTERE ESSES PARAMETROS DE ACORDO COM SEU GOSTO
$largura = 180;
$altura = 60;
$tamanho_fonte = 30;
$quantidade_letras = 5;

//GERA O CAPTCHA
captcha($largura, $altura, $tamanho_fonte, $quantidade_letras);
?>

Então altere seu formulário de login para:

<form action=”autenticar.php” method=”post”>
Usuário: <input type=”text” name=”usuario”/><br/>
Senha: <input type=”text” name=”senha”/><br/>
Digite os caracteres abaixo: <br/>
<img scr=”captcha.php”/><br/>
<input type=”text” name=”captcha”/><br/>
<input type=”submit” value=”Logar”/>
</form>

Exemplos de captchas gerados com <img src=”captcha.php” />:





Então na página autenticar.php basta verificar se o valor informado pelo usuário no campo captcha é igual ao captcha guardado na sessão. Isso praticamente inviabiliza tentativas automatizadas de login por ferramentas de hackers. No próximo artigo dessa série abordarei o ataque XSS e como podemos nos defender dele.

Atenciosamente,
Gustavo Marques

quinta-feira, 27 de dezembro de 2012

Colocando widget do twitter no seu sistema web





Colocar uma timeline qualquer do twitter no seu sistema web é bem simples. Existem algumas bibliotecas tanto em Java quanto em PHP. Porém uma ainda mais simples é a Twimg, disponível para implantação via  javascript. Se sua intenção é exibir uma timeline, ela é perfeita. Permite configurações nas cores, tamanho e muitas outras opções.

Vamos ao código:

<!-- Importe a biblioteca-->

<script src="http://widgets.twimg.com/j/2/widget.js"></script>


<!-- Instancie o objeto passando como parâmetro as opções, mude-as de acordo com seu gosto-->

<script>
new TWTR.Widget({
  version: 2,
  type: 'profile',
  rpp: 4,
  interval: 6000,
  width: 'auto',
  height: 300,
  theme: {
    shell: {
      background: '#9FB6FC',
      color: '#ffffff'
    },
    tweets: {
      background: '#fff2ff',
      color: '#545454',
      links: '#0781eb'
    }
  },
  features: {
    scrollbar: false,
    loop: false,
    live: true,
    hashtags: true,
    timestamp: true,
    avatars: false,
    behavior: 'all'
  }
}).render().setUser('programadorprof').start();
</script>

Perceba que na ultima linha 'render().setUser('programadorprof').start();' você passa como parâmetro o nome do usuário do twitter cuja timeline deseja exibir.

O resultado do código acima fica assim:




Atenciosamente,
Gustavo Marques

domingo, 23 de dezembro de 2012

Front Controller e Command com PHP

No post anterior introduzi os padrões Front Controller e Command. Expliquei seus benefícios e dei exemplos de como implementar em java. Nesse post apresentarei a versão em PHP (PHP versão 5 ou superior).

Leia o post original para entender os conceitos do artigo.

Vamos lá:

Estrutura de diretórios

./commands/
./commands/DeletarProduto.php
./commands/AlterarProduto.php
./Controller.php

DeletarProduto.php

<?php
class DeletarProduto{
    public function execute() {
         //DELETA O PRODUTO
    }     
}
?>

AlterarProduto.php

<?php
class AlterarProduto{
    public function execute() {
         //ALTERA O PRODUTO
    }     
}
?>

E agora o Controller.php:

<?php
//carrega o command
require_once "commands/".$_REQUEST['command'].".php";
$reflectionClass = new ReflectionClass($_REQUEST['command']);
$command = $reflectionClass->newInstance();
$command->execute();
?>

Para acessar o command basta usar a url: Controller.php?command=AlterarProduto ou Controller.php?command=DeletarProduto.

O Fato do PHP ter tipagem dinâmica facilita muito as coisas, tornando o código bem menos verboso em comparação com o java.

Atenciosamente,
Gustavo Marques

Ganhe Reusabilidade com Front Controller e Padronização com Command




No post anterior introduzimos os padrões de projetos. Neste post explicaremos dois deles: Front Controller e Command.

O padrão Front Controller é a base de muitos frameworks que conhecemos. Trata-se de uma maneira de centralizar os acessos em um único ponto e então, a partir deste,  rotear para uma ação (ou comando). Isso tem algumas vantagens. Em todas as aplicações existem funcionalidades que devem ser executadas em todos os acessos. Por exemplo verificar se o usuário está logado, verificar permissões e registrar log de acesso. São funções que devem ser executadas não importa qual a funcionalidade acessada. 

Vamos imaginar um cenário sem o front controller com command para entendermos a necessidade de sua implantação em nossos sistemas:

Certa aplicação em java possui 2 Servlets. Um para atualizar um produto e outro para deletar um produto. Em ambas as ações o usuário precisa estar logado, também é preciso registrar um log de acesso.

O primeiro Servlet foi escrito assim:

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AlterarProduto extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //PROCEDE COM A ALTERAÇÃO DO PRODUTO
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

E o segundo foi escrito assim:

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DeletarProduto extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //PROCEDE COM A EXCLUSÃO DO PRODUTO
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}


Há uma duplicação de código referente a verificação do usuário logado e o registro de log. E se precisarmos mudar algum código referentes a essas funcionalidades? teríamos que mudar todos os servlets. E se precisarmos adicionar mais alguma funcionalidade comum a todos os servlets? novamente teremos que alterar todos. Esse é um dos problemas que o front controller resolve.

Vamos ver como poderia ficar o nosso controller:

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Controller extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //ENCAMINHA PARA  AÇÃO (OU COMANDO) ESPECIALIZADO
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

Nesse modelo, as requisições 'alterar produto' e 'excluir produto' serão feitas ao mesmo servlet: Controller. Então o Controller depois de executar as funcionalidades comum as duas requisições irá encaminhar a solicitação a uma classe especializada. É aí que entra o padrão command. Quem não se lembra das famosas Actions do struts? Isso é o padrão command. Vamos implementar:

Crie uma interface Command

public inerface Command{
   public void execute(HttpServletRequest request, HttpServletResponse response);
}

Agora crie um pacote chamado 'commands' que irá conter seus commands.

Em seguida, vamos criar nossas implementações de Command:

package commands;
//imports
public class AlterarProduto implements Command{
   public String execute(HttpServletRequest request, HttpServletResponse response){
      //ALTERA O PRODUTO      
   }
}

package commands;
//imports
public class DeletarProduto implements Command{
   public String execute(HttpServletRequest request, HttpServletResponse response){
      //DELETA O PRODUTO      
   }
}

Agora vamos alterar o nosso Controller para reconhecer esses commands. Ele deve ser acessado pela seguinte url: Controller?command=AlterarProduto ou Controller?command=DeletarProduto. O parametro command é o nome da classe dos commands que implementamos. Se for necessário incluir um terceiro command 'CadastrarProduto' basta passar o nome nesse parametro e criar a classe que implementa Command no pacote commands.

Segue o controller

package servlets;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Controller extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //VERIFICA SE O USUARIO ESTÁ LOGADO
        //REGISTRA LOG DE ACESSO

        //EXECUTA O COMANDO ESPECIFICADO NA URL
        Command comando = (Command)Class.forName("commands."+request.getParameter("command")).newInstance();
        comando.execute();        
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
   
    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

Percebam que na instanciação do command e passo o nome da classe informada pela url. Aqui podemos visualizar o motivo do padrão command facilitar a padronização. Visto que todos os commands implementam a interface Command podemos usar o polimorfismo e instanciar várias implementações diferentes. Isso permite que nossa aplicação cresça sem a necessidade de alterar o nosso controller ou o nosso web.xml por adicionar novos servlets.

O foco deste artigo foi explicar e demonstrar os padrões front controller e command. Naturalente existem maneiras mais bem elaboradas para implementar, usando por exemplo DI e annotations. Porém desta maneira os conceitos são apresentados sem perder o foco.

Num próximo artigo apresentarei os padrões front controller e command implementados em PHP.

Atenciosamente,
Gustavo Marques

quinta-feira, 20 de dezembro de 2012

Gerando relatórios em PDF com PHP

É interessante que algumas das consultas que nossas aplicações fazem ao banco de dados pudessem ser exportadas em PDF para o usuário poder baixar a partir de seu navegador. Como implementar isso em PHP? Podemos utilizar a Classe FPDF.

Instalação:
Baixe a Classe FPDF. http://www.fpdf.org/

Quando extrair o conteúdo do arquivo baixado, coloque em seu projeto apenas o arquivo fpdf.php e a pasta font. Pronto! Sua aplicação já está preparada para criar relatórios em PDF.

Utilização:
Para utilizar a biblioteca é muito simples. Primeiro busque no banco de dados os registros que deseja exportar na forma de um array (poderá ser um array bidimencional ou um array de objetos) e depois utilize os métodos providos pela classe fpdf para gerar se PDF.

Vamos ao código:


<?php
require_once 'dominio/Pessoa.php';// nesse caso será um array de objetos Pessoa
require_once 'dao/PessoaDAO.php';
require_once 'fpdf.php';

//OBTENDO DADOS DO BANCO
$dao = new PessoaDAO();
$data = $dao->listarPessoas();

//CRIA A PÁGINA EM PDF
$pdf = new FPDF();
$pdf->AddPage('P', 'A4');

//CABEÇALHO DO RELATÓRIO
//Coloque aqui uma imagem como logo no seu relatório
//Se não precisar de imagem, apague essa linha
$pdf->Image('images/logo.png', -20);
$pdf->SetFont('Arial', 'B', 15);
$pdf->Cell(80);
$pdf->Cell(30, 10, 'Pessoas', 0, 0, 'C');//'Pessoas' centralizado no meio da página
$pdf->Ln(20);

//CABEÇALHO DA TABELA
$pdf->SetFont('Arial', 'B', 11);
$pdf->Cell(90, 7, 'Nome', 1);
$pdf->Cell(90, 7, 'Email', 1);
$pdf->Ln();

//POPULANDO A TABELA
$pdf->SetFont('Arial', '', 11);
foreach ($data as $row) {
    $pdf->Cell(90, 6, $row->getNome(), 1);
    $pdf->Cell(90, 6, $row->getEmail(), 1);
    $pdf->Ln();
}

//FORÇA O DOWNLOAD PELO BROWSER
$pdf->Output('pessoas.pdf', 'D');
?>


Veja abaixo um exemplo de como fica o PDF gerado:





Atenciosamente,
Gustavo Marques

quarta-feira, 28 de novembro de 2012

Porque vale a pena estudar e utilizar padrões de projeto?



        Sente-se desanimado em meio a tantas siglas e palavras desconhecidas? Talvez ache que programador tem que colocar logo a mão na massa (ou no teclado) e sair programando. Porque então dedicar tempo para estudar padrões de projeto?
   
        Vale muito a pena estudar padrões de projeto. Todos nós nos beneficiamos dos padrões em diversas áreas da vida. Pense por exemplo no corpo humano: o que aconteceria se cada indivíduo tivesse seus órgãos internos em um local diferente do corpo? Quanto trabalho daria ao cirurgião localizar primeiro onde se encontra tal órgão, entender suas particularidades para então começar uma cirurgia? Felizmente nossos corpos seguem um padrão, duas pernas, dois olhos, coração localizado no peito etc. E isso facilita sua 'manutenção'. Essa metáfora pode ser aplicada ao desenvolvimento de software. O uso de padrões de desenvolvimento trás uma série de benefícios.

      Ainda não se convenceu com a metáfora acima de que é benéfico o uso de padrões? Então vamos utilizar outra metáfora: Imagine se alguém lhe pedisse para construir um automóvel do zero. Mesmo de posse das peças certas, é provável que leve vários anos para conseguir. E uma vez terminado, o produto final talvez não colabore para uma manutenção por terceiros. Agora se você visitasse primeiro uma linha de produção de uma montadora de automóveis, veria como cada peça é encaixada, qual o lugar de cada uma no conjunto etc. Ou seja, alguém já gastou um bom tempo entendendo funcionamento correto de um automóvel, onde cada peça deve ficar, como encaixá-las, e tornou esse conhecimento disponível para a montadora construir automóveis da maneira certa, segura e ágil. Isso se aplica ao desenvolvimento de software. Muitos já construíram software da maneira errada e aprenderam lições disso. Outros construíram software da maneira correta e observaram os benefícios resultantes. Esse conjunto de experiências proporcionam um excelente conhecimento disponível. Podemos dizer que utilizar padrões de projeto é se beneficiar da experiência adquirida por outros.

        Se convenceu de que vale a pena estudar e utilizar padrões de projeto?

       Em próximos posts falarei de alguns padrões de projeto que devem estar em todos os projetos: DAO, MVC, Factory. Também explicarei outros que irão trazer ainda mais benefícios, como o Command, Front Controller e DI (Injeção de Dependências).



       Gustavo Marques.

sábado, 17 de novembro de 2012

Tratando vários campos checkbox de mesmo nome com PHP

Em nossos formulários podemos ter uma lista de itens a serem selecionados pelo usuario. Esses campos podem ter o mesmo nome e devem ser recebidos na forma de array no script receptor. Isso é interessante pois se forem muitos itens ou de tamanho desconhecido (geralmente quando vem do banco) fica inviável ler campo a campo no PHP.
Veja como implementar:

Primeiramente o form:

<form action="gravar.php" method="post">
   <input type="checkbox" name="itens[]" value="1" /> Item 1<br/>
   <input type="checkbox" name="itens[]" value="2" /> Item 2<br/>
   <input type="checkbox" name="itens[]" value="3" /> Item 3<br/>
   <input type="submit" value="Enviar" /> 
</form>

Perceba que o nome deve ser terminado com '[]', para instruir o PHP de que se trata de um array.
O script:

<?php
$itens= $_REQUEST['itens'];

if (!empty($itens)) {                
      $qtd = count($itens);
       for ($i = 0; $i < $qtd; $i++) {
            echo $itens[$i];//imprime o item corrente
       }
 }

?>

Com esse código você pode ter uma lista de 1000 checkbox que não faz diferença, não precisará ler um a um.


Gustavo Marques.

Veja também

Related Posts Plugin for WordPress, Blogger...