1 of 77

1

Java seguro na prática:

Shift Left,

Zero Trust e

Trusted Software Supply Chain

no Azure Red Hat OpenShift

Link

rafabene@gmail.com

2 of 77

rafabene@gmail.com

apiVersion: redhat/v2

kind: Principal Software Engineer

metadata:

name: Rafael Benevides

namespace: Red Hat Inc.

annotations:

contributor: Opensource

labels:

developer: Java, Go

hobby: 4x4, drones, motos

spec:

replicas: 1

containers:

image: benevides/rafael:latest

Rafael Benevides

@rafabenedev

3 of 77

4 of 77

5 of 77

1 - Introdução

6 of 77

“Não importa se você é júnior ou sênior, se trabalha em fintech ou e-commerce: a segurança do código Java impacta negócios de bilhões.”

Quem lembra deste caso?

Impacto:

  • vazamento de dados,
  • paralisações,
  • patch correndo contra o tempo.

7 of 77

Imagina o que pode acontecer se …

Alguém explorar uma vulnerabilidade e tiver acesso a modificar (ou até mesmo ler dados sensíveis de milhares de clientes)

8 of 77

O papel do desenvolvedor - DevOps antigamente…

9 of 77

O papel do desenvolvedor hoje: Segurança não é só infra

10 of 77

Shift Left: Antecipando os problemas

11 of 77

Nossa jornada hoje

Shift

left

Código

inseguro

Zero

trust

ARO

12 of 77

2 - “Desenvolvimento seguro em Java: práticas de Shift Left”

13 of 77

Bancos sofrem ataques todos os dias e de todos os tipos

Top vulnerabilidades em bancos:

  1. Injeções (SQL/LDAP/Command)
  2. XSS
  3. Autenticação/autorização quebradas
  4. Exposição de PII
  5. Configurações inseguras (Actuator, permissões)
  6. Dependências vulneráveis (supply chain)
  7. Falta de rate limiting (brute force em login/PIX)
  8. Segredos expostos em código/properties

14 of 77

Injeções (SQL/LDAP/Command)

  • Injeções são quando dados fornecidos pelo usuário são interpretados como comando e não apenas como informação.�
  • Alvos: Banco de dados, sistema operacional, templates, XML/LDAP, navegadores.�
  • Consequência: Acesso não autorizado, alteração de dados, até execução remota de código.

15 of 77

SQL Injection

Parece batido, mas uma simples concatenação de Strings e você está exposto!

String sql = "SELECT * FROM contas WHERE cpf='" + cpf + "'";

Solução:

@Query("SELECT c FROM Conta c WHERE c.cpf = :cpf")

Conta findByCpf(@Param("cpf") String cpf);

16 of 77

XSS - Cross-site scripting

Você vê algum problema nisso?��@WebServlet("/search")

public class SearchServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp)

throws IOException {

String q = req.getParameter("q");

resp.setContentType("text/html;charset=UTF-8");

resp.getWriter().println("<html><body>Você procurou por: " + q + "</body></html>");

}

}

17 of 77

XSS - Cross-site scripting

Ou nisto?��document.getElementById("out").innerHTML = userInput;

18 of 77

XSS - Cross-site scripting

Problema: Se o que o usuário enviou contiver HTML/JS, ele será inserido no DOM e executado no navegador de quem acessar a página.

19 of 77

XSS - Cross-site scripting

Manipulando uma página "real" o atacante consegue dados sensíveis do usuário.��

20 of 77

XSS - Cross-site scripting

21 of 77

XSS - Cross-site scripting

Solução:

// faz escaping de caracteres perigosos (<, >, ", etc.)

import org.apache.commons.text.StringEscapeUtils;

String safeQ = StringEscapeUtils.escapeHtml4(q);

OU document.getElementById("out").textContent = userInput; // trata como texto

22 of 77

CSRF - Cross Site Request Forgery

Problema: O navegador da vítima enviar uma requisição válida (com cookies/sessão ativos) para outro sistema em que ela já está autenticada.

Exemplo: Você está logado no seu internet banking, visita uma página maliciosa, ela dispara um POST /transferir em segundo plano e o servidor recebe como se fosse você.

23 of 77

CSRF - Cross Site Request Forgery

24 of 77

CSRF - Cross Site Request Forgery

Solução:

@EnableWebSecurity

public class SecurityConfig {

@Bean

SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

http.csrf().and() // habilita proteção

.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());

return http.build();

}

}

25 of 77

CSRF - Cross Site Request Forgery

Solução:

<input type="hidden" name="_csrf" value="abc123">

26 of 77

CSRF - Cross Site Request Forgery

27 of 77

Exposição de PII (Personal Identification Information)

Problema: Dados como CPF sendo expostos em logs, métricas, etc (Pode gerar problemas com LGPD)

Solução: Mascarar dados sensíveis.

28 of 77

Actuator expondo dados sensíveis via heap dump

Problema: /actuator/heapdump permite o download da heap.

Solução:

management.endpoint.heapdump.enabled=false

29 of 77

Segredos em código/properties

Problema: senha do DB ou token de API no application.properties

(db.password=123456)

Solução: Usar o Azure Keyvault

https://learn.microsoft.com/pt-br/azure/developer/java/spring-framework/configure-spring-boot-starter-java-app-with-azure-key-vault

30 of 77

Usando Azure Key Vault

# Endereço do seu Key Vault

spring.cloud.azure.keyvault.secret.property-sources[0].endpoint=https://meu-vault.vault.azure.net/

spring.cloud.azure.keyvault.secret.property-source-enabled=true

# Credenciais de autenticação (App Registration no Azure AD)

spring.cloud.azure.keyvault.secret.property-sources[0].credential.client-id=11111111-2222-3333-4444-555555555555

spring.cloud.azure.keyvault.secret.property-sources[0].credential.client-secret=SEU_CLIENT_SECRET

spring.cloud.azure.keyvault.secret.property-sources[0].profile.tenant-id=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

# ===============================

# Exemplo de uso dos segredos

# (esses nomes vêm dos segredos no Key Vault)

# ===============================

spring.datasource.url=${secretDbUrl}

spring.datasource.username=${secretDbUser}

spring.datasource.password=${secretDbPassword}

31 of 77

Agora, só problemas de autenticação

ou de autorização

32 of 77

Problemas de Autenticação e Autorização

Problema 1: Senha armazenada em texto puro

Solução:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12); // custo ajustável

String hash = encoder.encode(password);

userRepository.save(new User(email, hash));

33 of 77

Problemas de Autenticação e Autorização

Problema 2: Brute force attack

Solução:

1 - Usar captchas

2 - Bloquear o usuário após X tentativas

34 of 77

Problemas de Autenticação e Autorização

Problema 3: Manter a mesma session id antes/após login. - Atacante pode usar o id de uma sessão conhecida.

35 of 77

Problemas de Autenticação e Autorização

Problema 3: ��Fornecendo uma

sessão compro-

metida

36 of 77

Problemas de Autenticação e Autorização

Solução:

No Spring Security: habilitar sessionFixation().migrateSession()

37 of 77

Problemas de Autenticação e Autorização

Problema 4: Guardar JWT em localStorage -> acessível por XSS.

Solução: Armazenar access token em cookie HttpOnly + Secure + SameSite, usar refresh token rotativo.

ResponseCookie cookie = ResponseCookie.from("access_token", token)

.httpOnly(true).secure(true).path("/").sameSite("Strict")

.maxAge(Duration.ofMinutes(15)).build();

response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());

38 of 77

Problemas de Autenticação e Autorização

Problema 5: IDOR - Id of Object Reference

https://site.com/minha-conta/fatura?id=123

(Qualquer um pode acessar a fatura 123)

Solução:

  • Verificar se o objeto realmente pertence ao usuário logado.
  • Não confiar apenas em IDs enviados pelo cliente.
  • Usar identificadores difíceis de prever (UUIDs, tokens).

39 of 77

Problemas de Autenticação e Autorização

Problema 6: Validação só no Frontend

frontend esconde botão “apagar”,

backend permite DELETE /users/{id} sem checagem.

Solução:

Usar Spring Security method-level checks:

@PreAuthorize("#id == principal.id or hasRole('ADMIN')")

@DeleteMapping("/users/{id}")

public void deleteUser(@PathVariable Long id) { ... }

40 of 77

Problemas de Autenticação e Autorização

Problema 7: Aceitar role JWT vindo do cliente sem validar assinatura.

Solução: Assinar tokens (JWT) com chave forte e validar token no servidor

@PreAuthorize("hasAuthority('SCOPE_admin')")

41 of 77

Problemas de Autenticação e Autorização

Problema 8: Apenas apagar cookie no cliente sem invalidar token server-side (refresh tokens continuam válidos).

Solução: Manter lista de refresh tokens server-side

public void logout(String refreshToken) { . . .

refreshTokenRepository.revoke(refreshTokenId);

// limpar cookie do cliente

}

42 of 77

3 - “Zero Trust: nunca confie, sempre valide”

43 of 77

3.1 - Zero Trust no Filesystem

44 of 77

Zero Trust no Filesystem

Tratar todo o FS como não confiável por padrão, liberando só o mínimo necessário e validando tudo.�

  • imutável por padrão: raiz read-only; nada de escrever em / (só tmpfs/controlado).
  • mínimo de escrita:tmpfs ou volumes com políticas rígidas.
  • mínimo de privilégios: sem root, sem suid, sem exec onde não precisa
  • verificável: imagem assinada/escaneada;
  • isolável: SELinux;

45 of 77

Zero Trust no Filesystem

Sugestão para isto: Usar o Red Hat UBI (Universal Base Image)

  • Livre e redistribuível, sem necessidade de subscrição
  • Atualizações de segurança e bugfixes direto da Red Hat
  • Compatibilidade binária com RHEL e OpenShift
  • Vários sabores (ubi, minimal, micro, openjdk, etc.)
  • Pode ser usada com ou sem Red Hat Subscription
  • Preparada para rodar em OpenShift (non-root, labels, SCC)
  • Ciclo de vida longo (alinhado ao RHEL)
  • Conformidade com requisitos de segurança (FIPS, SELinux, etc.)

46 of 77

Zero Trust no Filesystem

FROM registry.access.redhat.com/ubi9/openjdk-21:1.20

# copia o jar ou fat jar

COPY target/myapp-1.0-runner.jar /deployments/app.jar

# apenas defina a execução

CMD ["java", "-jar", "/deployments/app.jar"]

47 of 77

3.2 - Zero Trust na Rede

48 of 77

Zero Trust a nível de rede - 1

Problema:

  • Todo pod em Kubernetes pode falar com qualquer outro por padrão

  • Aumenta risco de movimento lateral em caso de invasão

  • Sem restrição, uma app comprometida acessa banco ou serviços internos sem controle

49 of 77

Zero Trust a nível de rede - 1

Solução: Definir NetworkPolicies para limitar comunicação

Exemplo: só permitir que api acesse db na porta 5432

kind: NetworkPolicy

spec:

podSelector: {}

ingress: [] # bloqueia tudo por padrão

kind: NetworkPolicy

spec:

podSelector:

matchLabels: { app: db }

ingress:

- from:

- podSelector: { app: api }

ports:

- protocol: TCP

port: 5432

50 of 77

Zero Trust a nível de rede - 2

Problema:

  • Tráfego entre microservices via HTTP/TCP é em texto puro

  • Qualquer pod que “finja” ser outro pode se conectar

  • Sem autenticação mútua, difícil garantir identidade

51 of 77

Zero Trust a nível de rede - 2

Solução: Usar Service Mesh (Istio, OpenShift Service Mesh) e ativar mTLS: criptografia e autenticação mútua automática

apiVersion: security.istio.io/v1beta1

kind: PeerAuthentication

spec:

mtls:

mode: STRICT

52 of 77

Zero Trust a nível de rede - 3

Problema:

  • Qualquer pod pode abrir conexões externas (internet, APIs, etc.)

  • Risco: malware dentro do cluster enviar dados para fora

53 of 77

A maioria das comunicações são internas ou de entrada

54 of 77

Mas a saída DEVE ser bloqueada

55 of 77

Zero Trust a nível de rede - 3

Solução: Definir EgressRules em Service Mesh ou políticas de rede

Exemplo: permitir saída apenas para APIs confiáveis (ex.: pagamentos)

apiVersion: networking.istio.io/v1beta1

kind: ServiceEntry

spec:

hosts: ["api.pagamentos.com"]

ports:

- number: 443

name: https

protocol: TLS

56 of 77

3.3 - Zero Trust no Banco de Dados

57 of 77

58 of 77

Zero Trust a nível de banco de dados -1

Problema:

  • Usuários genéricos ou compartilhados (ex.: appuser para todos)

  • Permissões excessivas (GRANT ALL PRIVILEGES)

Solução:

  • Privilégios mínimos por schema/tabela (least privilege)

59 of 77

Zero Trust a nível de banco de dados -2

Problema:

  • Conexões sem criptografia (plain TCP)

Solução:

  • TLS obrigatório

60 of 77

Zero Trust a nível de banco de dados -3

Problema:

  • Credenciais hardcoded em código/configuração

Solução:

  • Secrets em Vault/K8s Secrets com rotação automática

61 of 77

Zero Trust a nível de banco de dados - 4

Problema:

  • Banco acessível de qualquer rede/pod

Solução:

  • Microsegmentação de rede (NetworkPolicy/firewall)

62 of 77

Zero Trust a nível de banco de dados - 4

Problema:

  • Falta de auditoria em queries sensíveis

Solução:

  • Auditoria e logs de queries + limites (timeouts, RLS)

63 of 77

5 - Segurança reforçada com ARO

“O código já é seguro. Agora precisamos garantir que ele rode em uma plataforma igualmente segura.”

64 of 77

Responsabilidade compartilhada reforçada

Datacenters certificados (ISO 27001, SOC 2, GDPR, etc.)

Patching contínuo, atualização automática de CVEs, hardening validado

Controle granular com RBAC, NetworkPolicy e SCC

65 of 77

Cluster com hardening corporativo Red Hat

O ARO utiliza imagens Red Hat Enterprise Linux CoreOS (RHCOS), com:

  • CIS (Center for Internet Security) Benchmarks aplicados ;
  • Atualizações automáticas de CVE via canais Red Hat;
  • SELinux em modo enforcing — coisa que muitos clusters vanilla desativam;
  • Somente containers assinados e verificados (via Red Hat Container Catalog / Quay.io).

Isso entrega uma base zero trust já embutida na camada do host e do sistema operacional.

66 of 77

Isolamento de rede e compliance com Azure Security Center

  • Private Link / VNET Integration: o cluster pode ser isolado totalmente da internet
  • Azure Security Center + Defender for Containers: Monitoramento nativo de vulnerabilidades, compliance e detecção de anomalias.�
  • Egress lockdown: controle de saída via NSG (Network Security Group) e Azure Firewall, evitando exfiltração de dados.�

Isso atende normas como LGPD, PCI-DSS e ISO 27001 sem precisar configurar tudo manualmente.

67 of 77

Gestão de identidade e acesso integrada

  • Integração com Microsoft Entra ID (Antigo Azure AD)
  • RBAC do OpenShift herdando grupos do Entra ID.
  • Pod Security Admission e SCCs controlando o que cada workload pode fazer.�

Com isso, você aplica o Princípio do Menor Privilégio de ponta a ponta — desde o login até o pod.

68 of 77

Supply Chain e imagens seguras

ARO permite:

  • Uso de ImageStreams que apontam para registries verificados (Quay, Red Hat, Azure Container Registry);
  • Assinar e validar imagens com cosign e OpenShift Signatures;
  • Rodar pipelines Tekton com política "Trusted Software Supply Chain", exigindo builds reprodutíveis e assinaturas.�

Isso reduz o risco de supply chain attacks — uma das maiores preocupações atuais (vide SolarWinds, Log4Shell, etc).

69 of 77

Observabilidade e auditoria nativas

  • Audit logs completos no Azure Monitor e OpenShift.�
  • Monitoramento e tracing integrados (Prometheus, Loki, OTEL).�
  • Alertas automáticos para CVEs, upgrades e mudanças de política.�

Com isso, o cliente tem rastreabilidade e capacidade de resposta rápida a incidentes.

70 of 77

6 - Demonstração usando uma aplicação Spring Boot

71 of 77

7 - Encerramento

“Segurança não é projeto, é prática diária.”

72 of 77

Como aplicar Shift Left no dia a dia

  • Testes desde o início: Escreva testes unitários junto com o código
  • Automatize cedo: Pipelines CI/CD com lint, build e testes rápidos
  • Feedback contínuo: Use code reviews, pair programming e PRs pequenos
  • Segurança antecipada: Adote SAST/DAST e análise de dependências logo no desenvolvimento
  • Infra como código: Valide configurações de ambiente/local em dev antes de subir para prod
  • Observabilidade já no dev: Métricas, logs estruturados e tracing desde os primeiros commits

73 of 77

Como aplicar Zero Trust no dia a dia

  • Nunca confie, sempre verifique: Autenticação multifator (MFA) em todos os acessos
  • Princípio do menor privilégio: Conceda somente a permissão mínima necessária
  • Microsegmentação: Isole redes, serviços e workloads (ex: Kubernetes NetworkPolicy)
  • Validação contínua: Monitore sessões ativas e revalide credenciais periodicamente
  • Observabilidade total: Colete logs, métricas e traces para detectar comportamento anômalo
  • Proteção de dados: Criptografe em repouso e em trânsito, valide acesso antes de liberar

74 of 77

Como aplicar Supply Chain no dia a dia

  • Controle de dependências: Use repositórios confiáveis, mantenha SBOM (Software Bill of Materials) atualizado
  • Assinatura e verificação: Assine imagens, pacotes e artefatos; valide antes de usar (ex: Sigstore, Cosign)
  • Builds reprodutíveis: Garanta pipelines determinísticos para evitar código injetado
  • Análise de vulnerabilidades: Escaneie dependências e imagens regularmente
  • Infra como código segura: Valide templates e manifests (ex: Terraform, Helm, Kubernetes) antes do deploy
  • Monitoramento contínuo: Acompanhe alertas de CVEs e atualize componentes críticos rapidamente

75 of 77

Por fim…

"Em um mundo que não para de se mover, estar seguro em Java significa estar pronto para o futuro.”

76 of 77

77 of 77

Dúvidas? Ideias?

Vamos conversar!