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

Veja também

Related Posts Plugin for WordPress, Blogger...