Desenvolvimento seguro?

28 de julho de 2017
Compartilhe

No cenário atual de segurança da informação, percebemos que devemos estar preparados contra os possíveis ataques. Nesse contexto, um grande aliado contra as ameaças na integração de segurança no ciclo de desenvolvimento é a metodologia OWASP Software Security Assurance Process, também descrita pela sigla OSSAP (https://www.owasp.org/index.php/OWASP_Software_Security_Assurance_Process).Neste artigo, iremos falar um pouco sobre desenvolvimento seguro e como podemos mitigar algumas ameaças já no processo de desenvolvimento.Por onde começar?Para saber do que precisamos nos proteger e como devemos nos proteger, precisamos entender quais são as vulnerabilidades mais encontradas em aplicações web. Para tanto, utilizamos como base o guia Open Web Application Security Project, mais conhecido como OWASP (https://www.owasp.org/index.php/Main_Page). Por ele temos a lista das vulnerabilidades mais comuns que são exploradas nas aplicações web.Abaixo estão listadas as 10 principais vulnerabilidades atuais citadas pela OWASP:

Em alguns dos nossos exemplos, vamos mostrar funções que utilizamos na construção do site https://desafiocyber.beyellow.com.br, desenvolvido em PHP. O objetivo dessa página era o cadastro dos candidatos para que participem do nosso processo seletivo através de um mini-CTF (Capture The Flag), com desafios relacionados à segurança da informação, reforçando a necessidade de um desenvolvimento seguro da nossa aplicação, pois prevíamos que sua proposta poderia torná-la alvo de usuários maliciosos.Conexão com MysqlNo primeiro passo, tomamos algumas medidas para mitigar os riscos de ataques de SQL Injection. Utilizamos a biblioteca PDO para as interações com banco de dados Mysql.A função prepare() do PDO já faz o escape dos caracteres da variável recebida e trata-os no momento da interação com o banco de dados. Partindo da premissa de que não confiamos nas requisições feitas pelo cliente, decidimos validar a variável antes de adicioná-la à função prepare.Exemplo de código:$email=filter_var($email, FILTER_VALIDATE_EMAIL);if ($stmt = $pdo->prepare(“SELECT id,nick FROM users WHERE email = :email LIMIT 1”)) {$stmt->bindValue(‘:email’,$email);list($user_id, $nick) = $stmt->fetch( PDO::FETCH_NUM );}Validando as variáveis e utilizando o PDO da maneira correta, conseguimos mitigar problemas como o SQL injection.Autenticação e validaçãoPara uma autenticação segura é fundamental que toda comunicação entre cliente e servidor esteja criptografada. Para isto, além do certificado digital SSL/TLS, utilizamos HTTP Strict Transport Security (HSTS), que é um parâmetro de segurança que força a utilização do canal seguro, impedindo a comunicação sem criptografia.A baixo estão alguns parâmetros de segurança que definimos no cabeçalho HTTP em um arquivo de configuração na pasta conf-enabled do apache.Header set X-Content-Type-Options: “nosniff”Header always set x-xss-protection “1; mode=block”Header always set x-frame-options “SAMEORIGIN”Header always set Strict-Transport-Security “max-age=63072000; includeSubdomains;”A primeira função que definimos para a aplicação foi o cadastramento de usuários. Isto ocorria da seguinte forma: solicitávamos algumas informações básicas dos usuários e uma senha, que seria utilizada para que fizessem o login posteriormente. Como uma forma de segurança adicional, utilizamos um script em JavaScript para enviar a hash da senha que o usuário preencheu no formulário, passando a hash pelo canal seguro HTTPS. Desta forma, mesmo se um atacante comprometesse o canal, seria mais difícil comprometer a senha do usuário, já que a política de senhas também estava forte.Após receber os dados via post, pegamos a hash da senha que o usuário enviou e utilizamos para criar outra hash. Com um salt randômico, utilizamos SHA-512. Para gerar o salt também recorremos ao SHA-512 com 16 caracteres randômicos. Depois disso, pegamos a hash do salt e concatenamos com a hash da senha, formando outra hash que é enviada ao banco de dados. Quanto mais segurança, melhor – ainda mais quando seu público é constituído por pessoas que são da área de segurança.$salt = hash(‘sha512’, uniqid(openssl_random_pseudo_bytes(16), TRUE));$senha = hash(‘sha512’, $_POST[‘rec-p’] . $salt);Após cadastrar tudo no banco de dados, um link é enviado por e-mail para que o usuário ative o cadastro, diminuindo a quantidade de possíveis usuários falsos na aplicação.$salt = hash(‘sha512’, uniqid(openssl_random_pseudo_bytes(16), TRUE));$sha=hash(‘sha512’, $email);$hash = hash(‘sha512’, $sha . $salt );$stmt = $pdo->prepare(“INSERT INTO users_active (cpf,hash) VALUES (:cpf,:hash) “);$stmt->execute(array(‘:cpf’ => $cpf,’:hash’ => $hash));$link=’https://’.$_SERVER[‘SERVER_NAME’].”/process_active.php?KEY1=$sha&KEY2=$salt”;Por que não usar o $_SERVER[‘HTTP_HOST’] ? Porque ele é vulnerável. Isto porque esse comando pode dar abertura para que um atacante manipule a requisição e altere o HOST no cabeçalho. Lembrando que muitas aplicações o utilizam para importar scripts, gerar links e redefinir senhas.O próximo passo após a ativação do usuário é a autenticação na aplicação. Criamos um formulário simples pedindo e-mail e senha. Para evitar ataques de força bruta, utilizamos o reCaptcha (https://www.google.com/recaptcha).Abaixo está um trecho de como recebemos o e-mail e a senha do usuário e como validamos o reCaptcha:require_once “recaptchalib.php”;$secret = ” YWNob3UgcXVlIGNvbG9jYXJpYSBtaW5oYSBjaGF2ZSBhcXVpPyBycw”;$response = null;$reCaptcha = new ReCaptcha($secret); if (isset($_POST[‘email’],$_POST[”rec-p”],$_POST[“g-recaptcha-response”])){$response = $reCaptcha->verifyResponse($_SERVER[“REMOTE_ADDR”],$_POST[“g-recaptcha-response”]);if ($response != null && $response->success){$email=filter_var($_POST[‘email’], FILTER_SANITIZE_EMAIL);$password = trim(preg_replace(“/[^a-z0-9]/”, “”,$_POST[‘rec-p’]));}}Como podemos ver, não há muito segredo. O maior diferencial foi na hora de tratar a hash que recebemos, que só aceita números e letras minúsculas, eliminando outra possibilidade de caractere.Para criar uma sessão segura utilizamos o seguinte código:function sec_session_start() {$session_name = ‘SEC_PHPSESSID’;$secure = true;$httpOnly = true;$domain=$_SERVER[‘SERVER_NAME’];ini_set(‘session.use_only_cookies’, 1)session_set_cookie_params(time+1500,’/’,$domain,$secure,$httpOnly);session_name($session_name);session_start();session_regenerate_id(true);}Configurando os parâmetros de segurança no cookie que será gerado, definimos o atributo secure como true, para que ele só seja transferido se estiver no canal seguro (HTTPS). Já o HttpOnly pode ser utilizado para que o cookie não se torne “acessível” por meio de scripts, tornando mais difícil o roubo de sessão através de Cross-site scripting (XSS). Definimos o domain recorrendo ao SERVER_NAME que definimos no apache, de modo que o cookie somente fique disponível para o domain.Agora vamos à parte do XSS, sobre o qual falamos há pouco. Para mitigar o risco contra o roubo de sessão por meio de XSS, tratamos as variáveis que enviavam dados ao banco de dados para que nele não entre nenhuma tag HTML. Se por algum motivo ocorrer a entrada de tags no banco de dados, tratamos na hora de consultar os dados e mostrar a variável na aplicação, utilizando a função htmlspecialchars ($variavel, ENT_QUOTES).if ($botao->rowCount() == 0){echo ‘<button data-toggle=”modal” data-target=”#’.htmlentities(preg_replace(“/[^0-9]+/”, “”, $id),ENT_QUOTES).'” class=”btn btn-default”>’.htmlentities($name,ENT_QUOTES).'</button>’;}else{echo ‘<button data-toggle=”modal” data-target=”#” class=”btn btn-success”>’ .htmlentities($name,ENT_QUOTES).'</button>’;}}Controle de acessoA autenticação é de suma importância para verificar se o usuário está logado na aplicação, antes que ele retorne dados de uma página autenticada. Por exemplo:if (usuario_logado() == true) {echo “Usuário logado”;//continua código pela pagina autenticada.}else{header(‘Location: index.php);} Nunca, em hipótese alguma, faça como no exemplo abaixo: if (usuario_logado() == false) {header(‘Location: index.php);}echo “Usuário logado”;//continua código pela pagina autenticada.No exemplo acima, o código só é redirecionado depois que a página é carregada por completo, apresentando o conteúdo sem necessariamente ter uma sessão ativa e autenticada. Isto torna o controle de acesso falho.Proteção adicionalMesmo com algumas proteções contra as ameaças, no desenvolvimento é de suma importância ter outras formas de proteção – como, por exemplo, o WAF (Web Application Firewall). Em nossa aplicação utilizamos o ModSecurity (https://modsecurity.org/) e o Fail2ban (https://www.fail2ban.org/). O Modsecurity foi acionado para barrar as tentativas de exploração das vulnerabilidades mais conhecidas. Já o Fail2ban, para bloquear possíveis DoS (Denial Of Service) ou tentativas de conexão em nosso SSH, que obviamente não estava rodando na porta default, pois desabilitamos o usuário root e criamos contas de acesso imprevisíveis. Além disso, implementamos um segundo fator de autenticação com o Google Authenticator. Há ainda outras técnicas para esconder o SSH que poderiam ter sido implementadas, como o Port Knocking.Outra função muito importante foi a configuração do arquivo htaccess do apache, para que retorne o status code 200 nas requisições, evitando riscos com a enumeração de páginas e arquivos da aplicação. Desabilitamos também o Directory browsing pelo htaccess e barramos eventuais tentativas de acessar o arquivo htacess pela aplicação.<IfModule mod_rewrite.c>RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule .* index.php [L]ErrorDocument 401 /index.phpErrorDocument 403 /index.phpErrorDocument 404 /index.phpErrorDocument 500 /index.php</IfModule><Files .htaccess>Require all denied</Files>Options -Indexes –MultiViewsO motivo de redirecionar esses erros para a página index foi justamente evitar a enumeração por status code. Em nosso header incluímos um http_response_code(200), que na maioria dos casos retornaria como 200.Conclusão A maioria das aplicações hoje está vulnerável por falta de um desenvolvimento seguro. Percebemos que sites bem conceituados no mercado ainda sofrem com falhas da lista das 10 principais vulnerabilidades citadas pela OWASP. Existem hoje no mercado várias formas de realizar a revisão estática no código, em busca de brechas que podem colocar a aplicação em risco.Uma das formas de analisar estaticamente é por meio da ferramenta Checkmarx (https://www.checkmarx.com/). Outra forma, sem custos, é recorrer ao guia de code review da OWASP (https://www.owasp.org/index.php/OWASP_Code_Review_Project).Se alguma dúvida surgir ou caso o leitor tenha sugestões de melhorias, sinta-se livre para comentar.Referênciashttps://www.w3schools.com/php/filter_validate_email.asphttps://www.owasp.org/index.php/Main_Pagehttp://php.net/manual/en/function.setcookie.phphttp://www.wikihow.com/Create-a-Secure-Login-Script-in-PHP-and-MySQLhttps://developers.google.com/recaptcha/old/docs/phphttps://gist.github.com/mbijon/1098477http://php.net/manual/en/function.htmlentities.phphttps://www.owasp.org/index.php/Secure_SDLC_Cheat_Sheethttps://www.digitalocean.com/community/tutorials/how-to-set-up-multi-factor-authentication-for-ssh-on-ubuntu-16-04https://www.digitalocean.com/community/tutorials/how-to-use-port-knocking-to-hide-your-ssh-daemon-from-attackers-on-ubuntuLuiz Milagres é professor de Cibersegurança da FIAP. Com mais de 10 anos de experiência em Tecnologia e Cibersegurança, sendo aproximadamente 8 anos dedicados a Segurança da Informação, com mais de 60 projetos entregues nas maiores Empresas do Brasil e do Mundo. Especialista em projetos de Testes de Invasão, avaliação de segurança em tecnologia da informação, estratégias de implantação para gestão de vulnerabilidades, gestão e resposta a incidentes, inteligência cibernética e gerenciamento de ameaças. É gerente da prática de Cybersecurity na EY no Brasil.Willian Lopes é Consultor de segurança da informação na EY com aproximadamente 4 anos de experiência em desenvolvimento de sistemas e a 2 anos atuando focado em desenvolvimento seguro. Experiência em administração, configuração e gerenciamento de Sistemas Operacionais Microsoft Desktop e Server. Realização de scripts para monitoração, automação de tarefas, correções paliativas e troubleshooting de problemas relacionados a infraestrutura. Possui experiência em desenvolvimento de aplicações WEB (front e back-end), com conhecimentos em lógica de programação em linguagens como: Python, PHP, JAVA e C++.

Nosso site armazena cookies para coletar informações e melhorar sua experiência. Gerencie seus cookies ou consulte nossa política.

Prosseguir