Por Carlos Bezerra

O desafio de se desenvolver um software seguro, em tempo ágil, pode ser vencido com o uso adequado de processos e ferramentas de segurança, que associadas às metodologias ágeis, resultarão em práticas de desenvolvimento seguro para times ágeis. Neste artigo, mostraremos algumas dessas práticas, que mesmo baseadas em outras já existentes no mercado, serão relacionadas ao desenvolvimento ágil.

A segurança no desenvolvimento de software vem se tornando uma demanda cada vez mais evidente no mercado. Com tal propósito, diversas práticas continuam sendo criadas. Para citar apenas algumas, temos, por exemplo, o conjunto de práticas da Microsoft (MSDL), os Seven Touchpoints for Software Security e as normas do Common Criteria. Outro processo de desenvolvimento seguro, e também com bastante êxito no mercado, é o OWASP SAMM um modelo mais maduro para o desenvolvimento de software seguro, que hoje está na versão 2.0., sendo o substituto do CLASP, também do projeto OWASP.

Com prazos cada vez mais apertados para projetos de softwares, as metodologias ágeis vêm sendo amplamente utilizadas na área. Contudo, quais são as práticas de segurança que mais se adequa a tais metodologias? Definir essas práticas é essencial, pois além da escolha pelo método ágil, o cliente precisa requisitar, e priorizar, a segurança; para que, assim, ela possa ser incluída como requisito no projeto, já que isso nem sempre acontece.

O treinamento sobre a importância da segurança deve preparar, educar e capacitar as partes interessadas no projeto. O plano para o treinamento de segurança deve abordar tópicos como: políticas de privacidade, conceitos básicos, grandes ataques, estratégias de defesa e modelagem de ameaças. Obviamente, treinamentos direcionados ao cotidiano de trabalho da equipe devem ser priorizados; como por exemplo, sua consonância com as tecnologias utilizadas na solução a ser desenvolvida (Web, Mobile, Cloud). Além disso, é importante que todos os participantes envolvidos no processo realizem treinamentos direcionados às suas necessidades específicas.

É recomendável, também, que novos membros do time realizem os treinamentos, mesmo os mais básicos, se possível, antes mesmo de entrar em um projeto já em andamento, de modo que tais treinamentos possam fazer parte do onboarding deles. E mesmo para os membros mais antigos, é indicado que os treinamentos sejam disponibilizados periodicamente, tanto para que todos possam realizá-los, quanto para fins de reciclagem técnica ou reforço de aprendizagem. Também é possível incluir essa prática durante as iterações do projeto, quando for necessário abordar temas específicos ou mesmo para atualizar membros do time. Porém, essa é uma abordagem mais custosa, e que pode afetar o desenvolvimento do projeto.

Contratar especialistas para promover os treinamentos dentro do ambiente do projeto pode ser a melhor forma de os realizar, dada à experiência e à prática dos mesmos, tanto em relação à segurança, quanto em relação à sua didática, caso sejam familiarizados com a oferta de treinamento. A vivência de profissionais que se especializam na área permite-lhes ter conhecimento sobre os temas mais importantes para determinadas equipes. Além disso, eles podem trazer conteúdos mais atuais sobre os assuntos abordados no projeto. Claro que, como frisamos acima, essa abordagem é mais dispendiosa, não apenas financeiramente, como também em relação ao ‘tempo’. Realizar esses treinamentos para um time, ou parte dele, requer planejamento e gasto de recursos financeiros. Além de consumir ‘tempo’ considerável: elemento este essencial, porém muitas vezes escasso em equipes de desenvolvimento ágil.

Como alternativa, podem ser utilizadas plataformas de treinamento que abordem o tema de segurança, sob diferentes pontos de vista; ou pode ser incentivada a realização de treinamentos externos, os quais podem ser feitos pelos membros do time, tanto de forma individual quanto conjunta. Treinamentos online, tanto podem ser menos custosos financeiramente, quanto mais fáceis de serem adequados ao tempo disponível, dada sua flexibilidade em relação a horários, bem como ao fato de estarem disponíveis de forma individualizada. Contudo, é extremamente importante prestar atenção à qualidade do material escolhido, evitando, assim, gastos cujo resultado seja insatisfatório.

Naturalmente, prover treinamento deve acrescer o custo de desenvolvimento, logo, manter a equipe treinada implica em valor repassado ao cliente, no preço final do produto. Porém, isto ajuda a preparar todos os envolvidos para lidar efetivamente com os requisitos de segurança. Além disso, a efetividade das práticas seguintes dependerá, substancialmente, do nível de treinamento da equipe.

É necessário garantir que requisitos de segurança sejam discutidos pelo time de desenvolvimento, junto ao cliente. De modo que possam, juntos, mitigar problemas relacionados a falhas causadas pela falta de elucidação dos mesmos. Assim, definir os requisitos de segurança tem como objetivo principal a identificação de funcionalidades relacionadas à segurança, para que as mesmas sejam descritas de forma clara dentro de um projeto de desenvolvimento seguro de software. É válido ressaltar, que além dos requisitos de segurança, não se pode esquecer dos requisitos da solução, os quais devem expor características de segurança, como parte de sua definição; sendo ambos importantes, e portanto devendo ser, necessariamente, considerados com a devida atenção.

Photo by Matteo Vistocco on Unsplash

Da mesma forma que o time ajuda o cliente a entender e definir os requisitos do projeto, o mesmo deve ser feito com os requisitos de segurança. Caso exista o papel de Security Master ou Security Champion no time, este terá a responsabilidade de prover suporte ao time durante o levantamento desses requisitos. Porém, nem sempre é possível dispor desse papel no time de desenvolvimento; nesses casos, outro membro do time deve assumir tal função. Por norma, naturalmente, o responsável deve ser um profissional com experiência em segurança; e, caso isso não seja possível, ele deve ter, ao menos, apoio e orientação de alguém que tenha experiência em segurança, mesmo que este último não faça parte do time.

Estes requisitos devem ser atualizados e revistos a cada ciclo, de modo que possam refletir sobre as alterações que ocorrem, naturalmente, ao longo das etapas dos projetos ágeis; e assim, possam considerar as mudanças nos cenários de ameaça. Uma prática que também pode ajudar na definição de requisitos de segurança, são as Evil User Stories, onde são descritos possíveis cenários de ameaças de segurança ao sistema, demonstrando como o mesmo pode ser afetado por atacantes. Entretanto, essa prática só tem efetividade se houver, à disposição da equipe, profissionais com perfil de segurança para descrever os cenários, bem como suas possíveis mitigações.

Já que a implementação de requisitos de segurança acrescenta tempo e custo ao projeto, ela deve ser acordada com o cliente. De modo que, caso o mesmo, apesar de ciente da importância do desenvolvimento seguro, opte pela restrição desses requisitos, ele possa, ainda assim, considerar dentro de seus prazos, objetivos e custos, os riscos assumidos pela não execução dessa tarefa de forma adequada.

Diversos times de desenvolvimento aplicam práticas de implementação como forma de manter a qualidade do código, sendo Clean Code, uma das mais difundidas. De modo semelhante, essas regras podem ser definidas para segurança. Com o intuito de evitar os erros mais comuns durante a implementação, times de desenvolvimento devem estabelecer o conjunto de regras de desenvolvimento, com foco em boas práticas ligadas à segurança de software. Essas regras devem especificar alguns pontos importantes, como o tratamento de entradas dos usuários ou o uso impróprio de funções obsoletas. É importante ter em mente que, para cumprir com o propósito de ser seguro, deve-se escrever um código resiliente e manutenível em relação à segurança. Ou seja, um código que seja possível de ser mantido, e que seja flexível, e por isso mesmo facilmente adaptável, resistindo assim às inseguranças do cenário de vulnerabilidades e ataques cada vez mais intensos e recorrentes. Para isso, a otimização das regras de implementação de segurança, para o desenvolvimento seguro e ágil, deve ser considerada.

Para iniciar essa etapa, é preciso definir quais regras os programadores devem seguir para escrever um código seguro. Muitas dessas regras podem ser listadas por meio de treinamentos e pesquisas. Além disso, muitas dessas regras podem ser extraídas dos guias oficiais das linguagens de programação, que visam a orientação ao desenvolvimento seguro das mesmas. Outras práticas também podem ajudar a definir esses padrões, como, por exemplo, a definição e o uso de padrões de criptografia conforme apontado no MSDL, citado ao início desse artigo.

Utilizar práticas de revisão de código, já utilizadas por outros times de desenvolvimento, com o intuito de validar o uso das regras de implementação segura definidas, é também uma estratégia positiva. Desse modo, os revisores devem observar se as regras definidas estão sendo seguidas e, se possível, atentar para outros problemas de segurança que possam existir no código. Isso irá contribuir para a inclusão, com o passar do tempo, de novas regras ao processo; como também para o ganho de experiência por parte dos desenvolvedores.

Outro método que pode ser utilizado para validar a implementação segura, são os testes automatizados, uma prática já bastante implantada em diversos projetos de software. O intuito dessa prática é implementar funções de verificação que comprovem a corretude dos requisitos implementados. Aproveitar a implementação desses testes e incluir validação de funcionalidades relacionadas à segurança pode aumentar a confiabilidade do software. Deste ponto de vista, caso haja verificações de segurança, pode-se estar mais seguro de que o código desenvolvido não será desvirtuado em mudanças futuras. E, caso isso ocorra, os testes, se bem implementados, devem falhar; deixando claro para o desenvolvedor que mudanças indesejadas aconteceram.

Garantir que o código fonte do projeto seja analisado, em busca de falhas de segurança, é essencial para validar a segurança do software implementado. Essa prática consiste, basicamente, em duas metodologias de verificação: Static Code Analysis (SAST) e Dynamic Code Analysis (DAST). A primeira analisa o código puro, a partir de regras de verificação predefinidas, em busca de trechos de código que apresentem problemas de segurança apontados pelas regras adotadas. A Segunda analisa a solução, em tempo de execução, juntamente com todo o código das bibliotecas da linguagem, e de terceiros, incorporados durante a implementação. A partir dos resultados apresentados por essas abordagens, é possível aferir a conformidade do código com os padrões de segurança definidos nos requisitos do projeto.

Photo by Andy Beales on Unsplash

Para todas as abordagens acima relatadas, existem ferramentas de verificação, que, sendo configuradas corretamente, são confiáveis. O time de desenvolvimento deve utilizar essas ferramentas, de acordo com as suas necessidades, a depender da linguagem e dos processos utilizados. Os resultados devem ser analisados e, se necessário, devem ser adicionadas tarefas ao backlog para corrigir os problemas encontrados.

Este tipo de análise, por meio de ferramentas, vai evitar que erros já conhecidos de linguagens, más práticas de segurança e outros cenários comuns, sejam evitados. O uso desta prática não implica no código estar, necessariamente, livre de vulnerabilidades. Estas ferramentas apenas buscam por padrões já conhecidos. A grande vantagem delas é, ainda na etapa de implementação, levantar e corrigir os erros mais comuns, permitindo que testes especializados estejam focados em problemas mais complexos, ou seja, nos erros que não seriam capturados por essas ferramentas.

A configuração da(s) ferramenta(s) de verificação de código deve ser realizada nas primeiras iterações do projeto, lembrando de, sempre que se fizer necessário, validar e atualizar a mesma. Uma vez configurada, o time deve encontrar o melhor momento para executá-la. Testes realizados por ferramentas podem ser executados em todas as iterações de desenvolvimento. Além disso, times que trabalham com CI/CD podem adicionar a execução dessas ferramentas dentro de seus respectivos pipelines. Dessa forma, a cada integração do software à base de código principal, uma rodada de verificação será realizada. Essas ferramentas também podem ser executadas pontualmente, para validar a correção de determinados bugs ou avaliar trechos de código mais críticos.

Naturalmente, por mais que os desenvolvedores busquem implementar o software com as melhores práticas de segurança, vulnerabilidades vão continuar a ser incorporadas no software involuntariamente. Para sanar esse problema, é essencial submeter o software a testes realizados por especialistas em segurança, visando, assim, garantir a segurança do mesmo. A experiência dos especialistas, somada ao mindset de atacante, permite que estes encontrem falhas ignoradas, ou inseridas tardiamente no processo de desenvolvimento. Além disso, por se tratar de uma análise especializada, estes profissionais podem apontar os métodos mais indicados para correção, os riscos associados, a facilidade de exploração, o impacto no negócio, entre outros aspectos que não seriam possíveis de ser extraídos por ferramentas ou pela equipe de desenvolvimento.

Testes especializados incluem, mas não estão limitados a: Penetration Testing, Red Team Testing, Risk Based Testing e Vulnerabilities Assessments. A aplicação de testes especializados, normalmente, requer a presença de um ou mais especialistas em segurança. Logo, para aplicar essa abordagem é necessária a contratação de uma empresa especializada, ou de profissionais autônomos também especializados. Em cenários mais críticos, o próprio projeto pode contar com um time desses profissionais para realizar esta função. De todo modo, o método mais apropriado para testar o software deve ser acordado com os especialistas, a fim de que a tarefa seja realizada da forma mais eficiente possível, seguindo as características específicas de cada projeto.

O momento ideal para aplicar esse tipo de teste seria coincidente com o lançamento de cada versão da aplicação. Contudo, nem sempre essa configuração ideal é possível, devido a inúmeras adversidades e restrições. Uma abordagem possível é realizar esses testes antes de cada Major Release, ou seja, entregas que alteram muitos aspectos do software e incluem diversas novas funcionalidades. É responsabilidade de todos os envolvidos, a definição de uma agenda para a realização desses testes, de modo que o software seja testado da forma mais adequada possível. Também é importante estar alerta aos riscos assumidos caso não seja possível realizar testes em todas as versões do software.

Claro que estas não são todas as práticas existentes, nem as mesmas garantem a resolução de todos os problemas relativos à segurança de um projeto de software, já que existem inúmeros outros aspectos a serem levados em consideração. Como também, nenhuma dessas práticas é obrigatória. Além disso, o projeto não estará necessariamente inseguro, caso todas, ou algumas delas, não sejam seguidas. Porém, considerar e adaptar estas práticas no processo de desenvolvimento certamente contribui para uma melhoria na segurança dos softwares desenvolvidos. Afinal, se é preciso ser ágil, e como sabemos, a pressa é inimiga da segurança, é crucial a atenção à mitigação das vulnerabilidades em práticas de desenvolvimento seguro para times ágeis.

___________________

O conteúdo deste texto foi produzido com base em um Trabalho de Conclusão de Curso [1] e um artigo no QUATIC 2020 [2], ambos do autor:

[1] BEZERRA, C. M. M.. Políticas para desenvolvimento de software seguro em time ágeis. 2019. Trabalho de Conclusão de Curso (Graduação em Ciência da Computação) — Universidade Federal Rural de Pernambuco. Disponível em [https://repository.ufrpe.br/handle/123456789/1848]

[2] Bezerra C.M.M., Sampaio S.C.B., Marinho M.L.M. (2020) Secure Agile Software Development: Policies and Practices for Agile Teams. In: Shepperd M., Brito e Abreu F., Rodrigues da Silva A., Pérez-Castillo R. (eds) Quality of Information and Communications Technology. QUATIC 2020. Communications in Computer and Information Science, vol 1266. Springer, Cham. https://doi.org/10.1007/978-3-030-58793-2_28