sexta-feira, 21 de dezembro de 2012

[Programação] [Web] Segurança em PHP

Olá pessoal, resolvi escrever esse big post para abordar brevemente sobre segurança de dados e informações em arquivos php. Muitos programadores não se atentam aos detalhes de segurança, principalmente por php ser uma linguagem web, muito fácil e objetiva. Lembre-se não se limite só ao que conhece. Vamos falar sobre vários aspectos inseguros existentes e como eles podem ser revolvidos facilmente ( rimou? hahaha ).

CROSS SITE SCRIPT
Se dados são importantes, lembre-se não os passe por métodos GET. Por exemplo, no caso de envio do link style.html pela url http://example.com/index.php?link=style.html o usuário poderia facilmente manipular a página a ser aberta. Quando existe a necessidade de enviar informações por GET que sejam necessárias em um formulário, como por exemplo, a string $nome, verifique abaixo:

$nome = mysql_escape_string($_GET["nome"]);

A função mysql_escape_string serve tanto para GET quando para POST e retorna uma string validada, não permitindo uma SQL Injection, por exemplo.

TRATAMENTO DE DADOS
Sempre que possível, trate seus dados com base em seu formato, por exemplo, para dados inteiros, converta-os utilizando métodos em php, veja abaixo:

$codigo = int($_POST["id"]);

Independente do dado recebido, será convertido para inteiro. Como entrada "string12teste" será retornado somente "12".

SQL INJECTION
Nunca passe informações direto do formulário sem validá-las. Caso contrário expressões de SQL poderão ser passadas pelos formulários para manipular sua SQL já montada. Use tratamentos descritos acima.


HTML INJECTION 
Sim, existe e muitos ignoram. Mas a prevenção contra HTML Injection permite que as páginas se mantenham como são sem alterar sua forma. Para isso sempre que não desejar mostrar e manipular a html para o usuário utilize a função strip_tags().


TIPO DE DADO
Sempre verifique ou dê um tipo ao seu dado em variável. Em php variáveis são dinâmicas, podem assumir qualquer forma ou valor por isso armazenamento e verificação do seu tipo é importante. Por exemplo, a variável $codigo recebe valor 1, entretanto podemos definir o tipo desse valor 1, abaixo exemplos:


$codigo = $_GET["id"];
$codigo = $_POST["id"];
$codigo = $_SESSION["id"];
$codigo = $_COOKIE["id"];

Assim o $codigo não poderá ser recebido diretamente como 1. Evitando erros comuns ou propositais de usuários.

SEMPRE VALIDE DADOS SEGUROS POR TIPO
Em uma página onde a variável $autenticar retorna um valor booleano, ela pode ser manipulada caso não possua um tipo. Observe:

Sem declaração de tipo.


if ($autenticar) {
     echo “Usuário autenticado, prosseguir...”;
} else {
     echo “O usuário não está autenticado!”;
}

O usuário poderia fazer uma injeção na URL ?autenticar=true e manipular a entrada como se o usuário tivesse realizado login. Interessante ressaltar que sites como Apostilando.com possuem esse erro, sendo possível fazer download das apostilas manipulando a URL sem fazer login.

Para concertar esse erro, poderia ser declarado um tipo para variável.
if ($_SESSION["autenticar"]) {
      echo “Usuário autenticado, prosseguir...”;
} else {
     echo “O usuário não está autenticado!”;
}

Agora $_SESSION["autenticar"] nunca seria confundido com uma variável $autenticar que pode ser recebida como injeção $_GET.

ERRO COM INCLUDE
Muito cuidado ao utilizar o include, mesmo que a página incluída são seja encontrada, a página atual continua em execução, veremos a seguir.

Inclui uma autenticação, e verifica se obteve ou não sucesso.
include_once “login.php”;

if (!isLoggedIn()) {
     die(“Problemas de autenticação!”);
} else {
     echo “Informações sigilosas do usuário”;
}

No código acima, se a página login não fosse encontrada, continuaria a execução e o php mostraria erro na página exibindo informações importante como o nome da função isLoggedIn(). Para resolver esse problema, basta utilizar require_once ao invés de include_once, pois assim, a página só será executada se a requerida for encontrada.


NÃO EXIBA OS ERROS
Informações importantes podem ser exibidas em erros de MySQL. Evite que a mensagem não seja exibida, e grave-as em um arquivo log. Esse processo pode ser feito alterando as seguintes informações nas configurações do php:


display_errors: 0
log_errors: 1
error_log: /caminho/para/arquivo.log

SEMPRE VALIDE PÁGINAS RESTRITAS
Páginas restritas como de acesso/login/funções, necessitam de validação para não serem acessadas diretamente. Páginas de acesso restrito podem ser validadas com a SESSION aberta, páginas com informações restritas diretamente podem ser validadas com a URL.


RESTRIÇÃO HTML
Em formulários com campo textbox, necessitam ser validados, para que não contenham links, códigos html, ou scripts maliciosos para serem executados. Para isso utilize a função htmlspecialchars() ela irá tratar o código recebido para string texto.

ARQUIVOS VIA UPLOAD
É muito importante verificar o tipo a ser salvo, para que não sejam enviados arquivos proibidos ou potencialmente perigosos para o servidor de dados. Por isso sempre verifique o mime-type do arquivo.

LISTAGENS DE ARQUIVOS E PASTAS
Desabilite a possibilidade de indexes no arquivo .htaccess, isso evita que todos arquivos sejam exibidos. Caso seja preciso listar arquivos ou pastas específicos crie um função php para isso. Para desabilitar indexes, escreva:

Options -Indexes

PREVENÇÃO CONTRA HTML/JAVASCRIPT
Atualmente é comum em navegadores mais modernos a capacidade de alterar o corpo html da página, com isso, funções javascript de validação ou ainda limite de caracteres podem ser desabilitadas facilmente. Para resolver esse problema SEMPRE valide a string no php. Abaixo um exemplo:

Input que recebe o nome com máximo 10 caracteres.
<input type="text" name="nome" id="nome" maxlength="10" />

Se o usuário desabilitar no código o maxlength, haverá problemas, e ocorrerá erros, isso pode ser validado novamente em php, observe:

// Recebe o nome
$nome = mysql_escape_string($_POST["nome"]);

// Valida o nome


if (strlen($nome) > 10)
{ die("Erro na string!"); }

Cuidado com campos tipo hidden, encripte sempre que possível.


PREVENÇÃO EM JAVASCRIPT
Mesmo que o script possa ser manipulado e seja necessária a validação em php como visto anteriomente. Sempre faça scripts em javascript que valide informações na própria página, para evitar que o usuário fique enviando informações e voltando caso ocorra erros.

PREVENÇÃO EM SENHAS
Utilize sempre processos de criptografia de dados ao ler/armazenar senhas em banco de dados.

Bom pessoal, é isso! Aqui nessa postagem alguns dos vários métodos existem, espero que tenham gostado, e aproveitem o máximo do conteúdo aqui descrito, e lembre-se não se limite só ao que conhece ( acho que eu já disse isso LOL )

quarta-feira, 19 de dezembro de 2012

[Programação] Métodos de Classificação - Insertion Sort


Olá pessoal, para compensar dias sem postar hoje iremos abordar sobre os principais métodos de classificação existentes para algoritmos esses métodos tornarão possível classificar objetos salvos na memória, sendo desde arrays até listas mais complexas. O objetivo desses métodos é facilitar a localização entre esses dados não havendo necessidades de montá-los novamente na memória, gastando assim menos armazenamento na memória ao executar diversas tarefas de trabalho com os dados.

O principio dos métodos se baseia na existência de um conjunto de dados e a partir de um valor enviado pelo usuário, utilizados os métodos nesse conjunto de dados, acessando a informação se ela existir. Existem vários métodos de classificação. Vamos abortar o principio e a execução de cada um. Para esse post começaremos com Insertion Sort

Insertion Sort - O método Insertion Sort percorre todo o vetor recebido da esquerda para direita, e à medida que avança deixa os elementos mais a esquerda ordenados. Veremos abaixo o código em funcionamento:

// Função de Insertion Sort que recebe o conjunto de dados
// Em nosso exemplo recebemos um vetor de inteiros
public int[] InsertionSort (int[] vetor)
{
     int j;
     int temp;


     for (int i = 1; i < vetor.Count; i++)
     {
          j = i;

          // Enquanto o J for maior que zero, e o valor anterior for menor que o valor atual
          while ((j > 0) && (vetor[j - 1] > vetor[j]))
          {
               // Será realizada a troca do anterior com o atual
               // Define o temporário como o valor atual
               temp = vetor[j];
               // Define o valor atual como o valor anterior
               vetor[j] = vetor[j - 1];
               // Define o valor anterior como o valor temporário
               vetor[j - 1] = temp;
               j--;
          }
     }

     return vetor;
}