Introdução à Segurança de Software
A segurança de software é um aspecto crítico do desenvolvimento moderno. Com o aumento de ataques cibernéticos e regulamentações como LGPD e GDPR, garantir que suas aplicações sejam seguras não é mais opcional – é uma necessidade de negócios.
Estatísticas Alarmantes
| Dado | Porcentagem |
|---|---|
| Ataques direcionados a apps web | 40{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} de todos os ataques |
| Cust médio de violação de dados | R$ 6.4 milhões |
| Tempo médio para detectar breach | 207 dias |
| apps com vulnerabilidades críticas | 47{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} |
| OWASP Top 10 presente em | 94{6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442} das apps |
OWASP Top 10: As Maiores Vulnerabilidades
O OWASP Top 10 é o guia definitivo das vulnerabilidades mais críticas em aplicações web. Vamos explorar cada uma.
A01 – Broken Access Control (Controle de Acesso Quebrado)
Descrição: Usuários podem executar ações além de suas permissões permitidas.
Exemplos:
# VULNERÁVEL - IDOR (Insecure Direct Object Reference)
@app.route('/pedidos/')
def get_pedido(id):
# Não verifica se o pedido pertence ao usuário logado
return Pedido.query.get(id)
# SEGURO
@app.route('/pedidos/')
@login_required
def get_pedido(id):
pedido = Pedido.query.filter_by(
id=id,
usuario_id=current_user.id
).first_or_404()
return pedido
Mitigação:
- Implementar autorização em cada camada
- Negar por padrão
- Usar IDs aleatórios (UUID)
- Log de acessos
A02 – Cryptographic Failures (Falhas Criptográficas)
Descrição: Exposição de dados sensíveis devido a criptografia inadequada.
Exemplos:
# VULNERÁVEL
senha = "senha123" # Sem hash
dados = dados.encode("utf-8") # Sem criptografia
# SEGURO
from cryptography.fernet import Fernet
# Gerar chave (armazenar em segurança!)
key = Fernet.generate_key()
cipher = Fernet(key)
senha_hash = bcrypt.hashpw("senha123".encode(), bcrypt.gensalt())
dados_criptografados = cipher.encrypt(dados)
Mitigação:
- Usar criptografia forte (AES-256, bcrypt, Argon2)
- Gerenciar chaves com Key Vault
- TLS para dados em trânsito
- Nunca hardcodar secrets
A03 – Injection (Injeção)
Descrição: Injeção de código malicioso através de inputs não sanitizados.
Exemplos:
-- SQL Injection Vulnerável
cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")
-- SQL Injection Seguro
cursor.execute("SELECT * FROM users WHERE email = {6727d158e4474b0847515bd23a8ee4bebd5f1aac7a18bc968e51d8985dccb442}s", (email,))
# Command Injection Vulnerável
os.system(f"ping {host}")
# Command Injection Seguro
import subprocess
subprocess.run(["ping", host]) # Lista, não string!
// XSS Vulnerável
document.getElementById('comment').innerHTML = userInput;
// XSS Seguro
document.getElementById('comment').textContent = userInput;
// ou
element.textContent = sanitizeHTML(userInput);
Mitigação:
- Sanitizar e validar inputs
- Usar ORM ou queries parametrizadas
- Escapar outputs
- Content Security Policy (CSP)
A04 – Insecure Design (Design Inseguro)
Descrição: Arquitetura e modelagem de sistema com falhas de segurança inerentes.
Mitigação:
- Threat modeling na fase de design
- Segregar recursos por criticidade
- Limitar tentativas de login (rate limiting)
- Princípio de menor privilégio
A05 – Security Misconfiguration (Configuração de Segurança)
Exemplos:
# Docker vulnerável
docker run -p 80:80 -v /:/root image:latest
# Docker seguro
docker run
--read-only
--no-new-privileges
-p 8080:8080
--cap-drop ALL
image:latest
# Flask vulnerável
app = Flask(__name__)
app.debug = True # Reveals code in errors!
# Flask seguro
app = Flask(__name__)
app.config['DEBUG'] = False
app.config['PROPAGATE_EXCEPTIONS'] = False
Mitigação:
- Hardening de servidores
- Revisão de configurações
- Automação de patching
- Arquitetura minimalista
A06 – Vulnerable and Outdated Components (Componentes Vulneráveis)
Mitigação:
# Verificar dependências vulneráveis
pip install safety
safety check
# npm audit
npm audit
# OWASP Dependency-Check
dependency-check --project App --scan ./lib
# GitHub Actions - Verificar vulnerabilidades em PR- name: Run Snyk Security Test
uses: snyk/actions/python@master
with:
args: --severity-threshold=high
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
A07 – Identification and Authentication Failures
# Vulnerável - Sem rate limiting
@app.route('/login', methods=['POST'])
def login():
user = User.query.filter_by(email=email).first()
if bcrypt.checkpw(password, user.password_hash):
login_user(user)
return redirect('/dashboard')
# Seguro - Com rate limiting
from flask_limiter import Limiter
limiter = Limiter(app)
@app.route('/login', methods=['POST'])
@limiter.limit("5 per minute")
def login():
# ... resto do código
Mitigação:
- MFA (Autenticação Multifator)
- Rate limiting em autenticação
- Senhas complexas (passphrase > senha)
- Sessões com timeout
A08 – Software and Data Integrity Failures
# GitHub Actions - Verificar integridade de dependências- name: Verify checksums
run: |
echo "$CHECKSUM" > expected_checksum.txt
sha256sum -c expected_checksum.txt
env:
CHECKSUM: ${{ secrets.CHECKSUM }}
Mitigação:
- Verificar integridade de dependências
- Assinar artefatos
- CI/CD com aprovações
- Não confiar em dados não verificados
A09 – Security Logging and Monitoring Failures
import logging
from flask import request
logger = logging.getLogger(__name__)
@app.before_request
def log_request():
logger.info({
'ip': request.remote_addr,
'method': request.method,
'path': request.path,
'user_agent': request.headers.get('User-Agent')
})
@app.route('/login', methods=['POST'])
def login():
if failed_login(user):
logger.warning({
'event': 'failed_login',
'email': request.form.get('email'),
'ip': request.remote_addr,
'attempts': get_attempts(request.remote_addr)
})
# Alertar se muitas tentativas
Mitigação:
- Logging de todos os eventos de segurança
- Monitoramento 24/7
- Alertas para anomalias
- Retenção de logs adequada
A10 – Server-Side Request Forgery (SSRF)
# Vulnerável
@app.route('/fetch_url')
def fetch_url():
url = request.args.get('url')
response = requests.get(url) # Pode acessar internamente!
return response.text
# Seguro
from urllib.parse import urlparse
ALLOWED_HOSTS = ['api.exemplo.com', 'cdn.exemplo.com']
@app.route('/fetch_url')
def fetch_url():
url = request.args.get('url')
parsed = urlparse(url)
if parsed.hostname not in ALLOWED_HOSTS:
abort(403)
# Block private IPs
if parsed.hostname in ['localhost', '127.0.0.1', '0.0.0.0']:
abort(403)
return requests.get(url).text
Ferramentas de Teste de Segurança
SAST – Static Application Security Testing
| Ferramenta | Linguagem | Tipo | Custo |
|---|---|---|---|
| SonarQube | Multi | Self-hosted | Grátis/Enterprise |
| Snyk Code | Multi | Cloud | Grátis/Pro |
| Semgrep | Multi | CLI | Grátis |
| Checkmarx | Multi | Enterprise | Comercial |
| Fortify | Multi | Enterprise | Comercial |
DAST – Dynamic Application Security Testing
| Ferramenta | Tipo | Custo |
|---|---|---|
| OWASP ZAP | Open Source | Grátis |
| Burp Suite | Freemium | $399+/ano |
| Acunetix | Commercial | Sob consulta |
| Netsparker | Commercial | Sob consulta |
SCA – Software Composition Analysis
| Ferramenta | Foco | Custo |
|---|---|---|
| Snyk | Dependencies | Grátis/Pro |
| OWASP Dep-Check | Dependencies | Grátis |
| WhiteSource | Enterprise | Comercial |
| FOSSA | License compliance | Grátis/Pro |
IAST – Interactive Application Security Testing
| Ferramenta | Tipo |
|---|---|
| Contrast Security | Commercial |
| Hdiv | Commercial |
| Seeker (Synopsys) | Commercial |
Implementando Testes de Segurança no CI/CD
GitHub Actions – Pipeline de Segurança
name: Security Pipeline
on: [push, pull_request]
jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >
p/owasp-top-ten
p/nodejs-scan
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk
uses: snyk/actions/python@master
with:
args: --severity-threshold=high
dast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start application
run: docker-compose up -d
- name: OWASP ZAP Scan
uses: zaproxy/action-baseline@v0.9.0
with:
target: 'https://localhost:8443'
rules_rules_name: 'api-scan'
Penetration Testing
Metodologia OWASP
1. Information Gathering
- Footprinting
- Enumeration
- Threat Modeling
- Identify assets
- Analyze threats
- Vulnerability Analysis
- Automated scanning
- Manual testing
- Exploitation
- Proof of concept
- Impact assessment
- Reporting
- Findings
- Recommendations
- Remediation
Tipos de Pentest
| Tipo | Conhecimento | Escopo | Custo |
|---|---|---|---|
| Black Box | Zero | Sem informação | $$$ |
| Gray Box | Parcial | Credenciais limitadas | $$$$ |
| White Box | Total | Código e documentação | $$$$$ |
Ferramentas de Pentest
# Reconhecimento
nmap -sV -sC target.com
subfinder -d target.com
amass enum -passive -d target.com
# Scanning
nikto -h https://target.com
sqlmap -u "https://target.com/api?id=1"
XSStrike -u "https://target.com/search?q=test"
# Exploitation
metasploit framework
burp suite professional
Conclusão
Segurança de software é responsabilidade de todos. Implementar testes de segurança de forma integrada ao ciclo de desenvolvimento é essencial para reduzir riscos e proteger dados sensíveis.
Resumo:
- OWASP Top 10 deve ser training obrigatório
- SAST/DAST/SCA integrados ao CI/CD
- Pentests periódicos são essenciais
- Nunca confie em inputs de usuários
- Criptografia forte é não negociável
FAQ
P: Com que frequência devo fazer pentests?
R: Mínimo annually, idealmente a cada 6 meses ou após grandes mudanças.
P: SAST substitui DAST?
R: Não. SAST analisa código, DAST testa aplicação em execução. São complementares.
P: Como começar com segurança em devs?
R: Treinamento OWASP Top 10, implementar SAST no CI/CD, secure code review.
P: Bug bounty substitui pentest?
R: Não. São complementares. Bug bounty encontra issues em produção, pentest é controlado.
