PHP Seguranca

De Wiki REDDES


Tabla de contenidos

Introdução

Com novos projetos de software surgindo dentro da BIREME, cada vez mais é necessário garantir e reforçar a segurança das aplicações construídas, para que informações confidenciais e infra-estrutura dos clientes não seja comprometida.

Objetivo

O principal objetivo desta página é estabelecer um conjunto de boas práticas para codificação de um software seguro, reduzindo ao máximo as vulnerabilidades.

Validação de dados de entrada

Toda informação entrada em uma aplicação, que em geral pode ser via GET, POST ou COOKIE, deve ser confrontada a uma validação. O programador deve saber quais são os tipos e padrões de dados aceitos por cada entrada de dados existente no código.

Se um parâmetro via GET é recebido e espera-se que esse valor seja um número inteiro, é necessária uma validação para garantir que a aplicação vai realmente receber um valor inteiro. Um modo eficiente de validar o dado de entrata é confrontá-lo a uma expressão regular com auxílio da função preg_match.

Inteiros

<?php
  $id = 0; // Valor default
  if( preg_match('/^[0-9]+$/', $_REQUEST['id'] ){
	  $id = $_REQUEST['id'];
  }
?>

Número com separadores

<?php
  $money = 0; // Valor default
  if( preg_match('/^[0-9]{1,3}((\.[0-9]{3,3})+(\,[0-9]*)?)?$/', $_REQUEST['money'] ){
	  $money = $_REQUEST['money'];
  }
?>

E-Mail

<?php
  $email = false; // Valor default
  if( preg_match('/^[a-z_][a-z0-9_\.]+@[a-z0-9]+(\.[a-z0-9_]+)+$/i', $_REQUEST['email'] ){
	  $email = $_REQUEST['email'];
  }
?>

Caminhos de arquivos

Para casos em que uma entrada é passada para qualquer uma destas funções:

  1. readfile
  2. fopen
  3. file
  4. include
  5. require

Sugere-se esta validação:

<?php
  $caminho = ""; // Valor default
  if( preg_match('/^[a-z_\-]+(\/[a-z0-9_\- ][a-z0-9_\-\. ]*)+\.[a-z0-9_\-]+$/i', $_REQUEST['caminho'] ){
	  $caminho = $_REQUEST['caminho'];
  }
?>

Tratamento dos dados de entrada

Alguns tipos de dados entrados devem ser tratado antes do armazemento, para que nenhum script ou código malicioso sejam permitidos nesta operação.

Expressões de busca

É necessário prever e restringir o que pode ser buscado. O exemplo abaixo trata expressões de busca para que somente somente números, letras, letras com acentos, hífens e aspas duplas sejam entrados:

<?php
  $expression = $_REQUEST['expression'];
  $expression = strtoupper($expression);
  preg_match_all('/"?[À-ÖØ-öø-ÿ\w\-]+"?/', $expression, $expression);
  $expression = join(' ',$expression[0]);
?>

Atenção: Para que a função acima funcione adequadamente, o programador deve garantir que a expressão regular pertença ao mesmo conjunto de caracteres que o texto a ser comparado.

Textos puro

Se é esperado uma entrada textual, que é devolvida ao navegador do usuário, é necessário que as tags HTML que sejam anuladas para evitar injeção de scripts. Sugestão:

<?php
  $text = htmlentities($_POST['text'], ENT_QUOTES, 'UTF-8');
?>

Textos HTML

Em alguns casos é preciso permitir que dados textuais entrados contenham algumas tags HTML. Neste caso é necessário definir de forma explícita quais são as tags que são permitidas para esta entrada. Exemplo:

<?php
$valid_tags = array('div','span','br','u','b');
$textarea = $_REQUEST['textarea'];
preg_match_all('/<\/?([a-zA-Z]+)[^>]*>/', $textarea,$matches);

if(isset($matches[1])){
  $matches = array_unique($matches[1]);
  foreach( $matches as $m ){
    $m = strtolower($m);
    if( !in_array($m, $valid_tags) )
      $textarea = preg_replace('/<(\/?'.$m.')[^>]*>/', '<b>[$1]</b>', $textarea);
  }
}
?>

Checando veracidade dos dados

Há passo adicional que pode ser seguido imaginando que o processo de validação e tratamento do dado de entrada seja insulficiente, que é checar se o valor passado por entrada é verdade ou não.

Inclusão de Arquivos

Sempre evitar variavéis quando acessar arquivos do servidor:

// $lib_dir é uma váriavel opcional de configuração
include($lib_dir . "functions.inc");

Mas quando necessário, utilizar uma função que verifique os arquivos que serão incluidos nos scripts php:

/**
 * @desc Function utility for testing the file name
 * @param $name String the name of file
 * @param $ext String the extension of file
 * @param $exp opt String The regular expression for validate the file name
 * return String the complete name of file (name.ext)
 */
function test_inc($name,$ext,$exp=0)
{
   if ($exp != 0) {
       if(! eregi($exp,$name) ) {
           exit(".. 404 - Not Found");
       }
   }
   $file = $name . "." . $ext;
   if (!file_exists($file ) ) {
       exit("404 - Not Found");
   }
  return $file;
}
?>

Para cada arquivo PHP a ser incluído, deve-se chamar esta função:

include (test_inc($php_script . "xml2tree","php"));
include (test_inc($php_script . "ep_lib","php"));
include (test_inc($php_script . "class.XSLTransformer","php"));

Vazamento de Informações

Variáveis

Algumas variáveis são incializadas com informações importantes, como nome de usuário, caminhos, entre outros valores. É interessante desalocar estas variáveis assim que deixarem de ser usadas, para que caso algum script malicioso seja importando, não tenha acesso aos dados indevidos.

<?php
  $user = $_POST['user'];
  $pass = $_POST['password'];
  
  $valid_user = is_user_valid( $user, $password);
  
  unset($user);
  unset($pass);
?>

Variáveis Globais

A maior causa de quebra de segurança em código PHP é o parâmetro register_globals, ela era utilizada nas versões antigas de PHP como "on" mas foi alterada para "off" nas versões mais atuais. Verifique sempre através do phpinfo() se no servidor onde esta sendo executado sua aplicação o valor deste parâmetro esta como "off".

Mensagens de Erro

Tenha certeza que o parâmetro displary_errors no php.ini esta como "0". Caso contrario, qualquer erro encontrado no seu código, tal como um erro de conexão com o banco de dados ou vaviáveis não inicializadas serão mostradas no browser e um usuário malicioso pode usar esta informação para explorar o código. Alternativamente é possivel adicionar no ínicio do código:

error_reporting(0);
ini_set('display_errors', '0');

Leituras Recomendadas sobre Segurança

  1. http://wiki.reddes.bvsalud.org/index.php?title=PHP_Seguranca&oldid=663
  2. http://shiflett.org/articles/cross-site-request-forgeries
  3. http://www.slideshare.net/ergalvao
  4. http://shiflett.org/articles/cross-site-request-forgeries
  5. http://www.talkphp.com/vbarticles.php?do=article&articleid=59&title=csrf-post-token-protection
  6. http://ha.ckers.org/xss.html
  7. http://jehiah.cz/archive/xss-stealing-cookies-101
  8. http://code.google.com/p/doctype/wiki/ArticlesXSS

Exemplos de aplicações que usam Token (quando logado)

  1. http://delicious.com/
  2. http://www.linkedin.com/
  3. http://www.orkut.com/

Arquivos Relacionados

  1. Top 10 OWASP com PHP - Compreendendo e tratando as 10 vulnerabilidades mais críticas em aplicações web segundo o OWASP. Por Er Galvão Abbott [1]
Herramientas personales