- All SKILL.md files now <500 lines (avg reduction 69%) - Detailed content extracted to references/ subdirectories - Frontmatter standardised: only name + description (Anthropic standard) - New skills: brand-guidelines, spec-coauthor, report-templates, skill-creator - Design skills: anti-slop guidelines, premium-proposals reference - Removed non-standard frontmatter fields (triggers, version, author, category) Plugins affected: infraestrutura, marketing, dev-tools, crm-ops, gestao, core-tools, negocio, perfex-dev, wordpress, design-media Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
276 lines
6.1 KiB
Markdown
276 lines
6.1 KiB
Markdown
# /security-audit - OWASP Top 10 Checklist Detalhada
|
|
|
|
Verificações e exemplos de código para cada categoria OWASP Top 10.
|
|
|
|
## A01 - Broken Access Control
|
|
|
|
**Verificações:**
|
|
```php
|
|
// ❌ VULNERÁVEL
|
|
if ($_GET['user_id']) {
|
|
$user = getUserById($_GET['user_id']); // Sem verificação ownership
|
|
showUserData($user);
|
|
}
|
|
|
|
// ✅ SEGURO
|
|
if ($_GET['user_id']) {
|
|
$user = getUserById($_GET['user_id']);
|
|
if ($user->id !== $currentUser->id && !$currentUser->isAdmin()) {
|
|
die('Unauthorized');
|
|
}
|
|
showUserData($user);
|
|
}
|
|
```
|
|
|
|
**Testes:**
|
|
- [ ] Tentar aceder recurso de outro user (`/user/123` → `/user/124`)
|
|
- [ ] Testar IDOR (Insecure Direct Object Reference)
|
|
- [ ] Verificar se RBAC implementado correctamente
|
|
- [ ] Path traversal (`../../../etc/passwd`)
|
|
- [ ] Forced browsing (aceder `/admin` sem autenticação)
|
|
|
|
---
|
|
|
|
## A02 - Cryptographic Failures
|
|
|
|
**Verificações:**
|
|
```php
|
|
// ❌ VULNERÁVEL
|
|
$password = md5($_POST['password']); // MD5 é inseguro
|
|
|
|
// ✅ SEGURO
|
|
$password = password_hash($_POST['password'], PASSWORD_BCRYPT);
|
|
```
|
|
|
|
**Checklist:**
|
|
- [ ] Passwords com bcrypt/argon2 (não MD5/SHA1)
|
|
- [ ] Dados sensíveis encriptados em BD
|
|
- [ ] HTTPS em produção (não HTTP)
|
|
- [ ] Cookies com flags `Secure` e `HttpOnly`
|
|
- [ ] Sem PII em logs
|
|
|
|
**Testes:**
|
|
```bash
|
|
# Verificar HTTPS
|
|
curl -I https://site.com | grep -i "strict-transport-security"
|
|
|
|
# Verificar cookies
|
|
curl -I https://site.com | grep -i "set-cookie"
|
|
# Deve ter: Secure; HttpOnly; SameSite=Strict
|
|
```
|
|
|
|
---
|
|
|
|
## A03 - Injection (SQL, Command, LDAP)
|
|
|
|
**SQL Injection:**
|
|
```php
|
|
// ❌ VULNERÁVEL
|
|
$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];
|
|
|
|
// ✅ SEGURO (Prepared Statements)
|
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
|
$stmt->execute([$_GET['id']]);
|
|
```
|
|
|
|
**Testes SQL:**
|
|
```sql
|
|
-- Payloads comuns
|
|
' OR '1'='1
|
|
'; DROP TABLE users; --
|
|
' UNION SELECT NULL, NULL, NULL--
|
|
```
|
|
|
|
**Command Injection:**
|
|
```php
|
|
// ❌ VULNERÁVEL
|
|
system("ping " . $_GET['host']);
|
|
|
|
// ✅ SEGURO
|
|
$host = escapeshellarg($_GET['host']);
|
|
system("ping $host");
|
|
```
|
|
|
|
**Checklist:**
|
|
- [ ] Prepared statements em todas as queries
|
|
- [ ] Input sanitizado antes de shell commands
|
|
- [ ] NoSQL injection prevenido
|
|
- [ ] LDAP injection prevenido
|
|
- [ ] Template injection prevenido (Twig, Smarty)
|
|
|
|
---
|
|
|
|
## A04 - Insecure Design
|
|
|
|
**Checklist:**
|
|
- [ ] Rate limiting implementado (login, API)
|
|
- [ ] CAPTCHA em formulários públicos
|
|
- [ ] MFA disponível para contas admin
|
|
- [ ] Session timeout configurado
|
|
- [ ] Password policy forte (min 8 chars, uppercase, etc.)
|
|
|
|
**Testes:**
|
|
```bash
|
|
# Testar rate limiting
|
|
for i in {1..100}; do
|
|
curl -X POST https://site.com/login \
|
|
-d "email=test@test.com&password=wrong" &
|
|
done
|
|
# Deve bloquear após N tentativas
|
|
```
|
|
|
|
---
|
|
|
|
## A05 - Security Misconfiguration
|
|
|
|
**Checklist Servidor:**
|
|
```bash
|
|
# Verificar versões expostas
|
|
curl -I https://site.com | grep -i "server:"
|
|
# Não deve revelar Apache/2.4.41 ou PHP/8.1.2
|
|
|
|
# Verificar directory listing
|
|
curl https://site.com/uploads/
|
|
|
|
# Verificar ficheiros sensíveis expostos
|
|
curl https://site.com/.env
|
|
curl https://site.com/.git/config
|
|
curl https://site.com/phpinfo.php
|
|
# Todos devem dar 403/404
|
|
```
|
|
|
|
**Headers de Segurança:**
|
|
```nginx
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
|
add_header Content-Security-Policy "default-src 'self' https:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" always;
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
server_tokens off;
|
|
```
|
|
|
|
---
|
|
|
|
## A06 - Vulnerable and Outdated Components
|
|
|
|
**Verificações:**
|
|
```bash
|
|
# PHP - Composer
|
|
composer audit
|
|
|
|
# Node.js
|
|
npm audit
|
|
|
|
# WordPress
|
|
wp core version
|
|
wp plugin list --format=json | jq '.[] | select(.update=="available")'
|
|
```
|
|
|
|
**Checklist:**
|
|
- [ ] Dependências actualizadas (últimos 3 meses)
|
|
- [ ] Sem bibliotecas com vulnerabilidades conhecidas
|
|
- [ ] PHP/Node/Python versão suportada
|
|
- [ ] WordPress core e plugins actualizados
|
|
|
|
---
|
|
|
|
## A07 - Identification and Authentication Failures
|
|
|
|
**Verificações:**
|
|
```php
|
|
// ❌ VULNERÁVEL - Session Fixation
|
|
session_start();
|
|
|
|
// ✅ SEGURO
|
|
session_start();
|
|
session_regenerate_id(true); // Regenerar após login
|
|
```
|
|
|
|
**Checklist:**
|
|
- [ ] Session regenerate após login
|
|
- [ ] Logout invalida sessão no servidor
|
|
- [ ] Session timeout (15-30 min)
|
|
- [ ] Password reset com token expirável
|
|
- [ ] Account lockout após N tentativas falhadas
|
|
- [ ] Sem user enum (login não revela se user existe)
|
|
|
|
**Testes:**
|
|
```bash
|
|
# Testar user enumeration
|
|
curl -X POST https://site.com/login \
|
|
-d "email=naoexiste@test.com&password=wrong"
|
|
# Não deve dizer "user não existe"
|
|
```
|
|
|
|
---
|
|
|
|
## A08 - Software and Data Integrity Failures
|
|
|
|
**Verificações:**
|
|
```php
|
|
// ❌ VULNERÁVEL
|
|
$data = unserialize($_GET['data']);
|
|
|
|
// ✅ SEGURO
|
|
$data = json_decode($_GET['data'], true);
|
|
```
|
|
|
|
**SRI Example:**
|
|
```html
|
|
<script src="https://cdn.example.com/lib.js"
|
|
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/ux..."
|
|
crossorigin="anonymous"></script>
|
|
```
|
|
|
|
---
|
|
|
|
## A09 - Security Logging and Monitoring Failures
|
|
|
|
**Checklist:**
|
|
- [ ] Login attempts logged (success/fail)
|
|
- [ ] Access to sensitive data logged
|
|
- [ ] Logs não contêm passwords ou PII
|
|
- [ ] Alertas configurados para actividade suspeita
|
|
- [ ] Retenção de logs (mínimo 90 dias)
|
|
|
|
**Análise de Logs:**
|
|
```bash
|
|
# Tentativas de SQL injection
|
|
grep -i "union.*select" /var/log/nginx/access.log
|
|
|
|
# Tentativas de path traversal
|
|
grep -E "\.\./|\.\.%2F" /var/log/nginx/access.log
|
|
|
|
# Scans de vulnerabilidades
|
|
grep -E "nikto|nmap|sqlmap" /var/log/nginx/access.log
|
|
|
|
# Tentativas de login falhadas
|
|
grep "Failed password" /var/log/secure
|
|
```
|
|
|
|
---
|
|
|
|
## A10 - Server-Side Request Forgery (SSRF)
|
|
|
|
**Verificações:**
|
|
```php
|
|
// ❌ VULNERÁVEL
|
|
$url = $_GET['url'];
|
|
file_get_contents($url); // Pode aceder rede interna
|
|
|
|
// ✅ SEGURO
|
|
$url = $_GET['url'];
|
|
$parsed = parse_url($url);
|
|
if ($parsed['host'] !== 'allowed-domain.com') {
|
|
die('Invalid URL');
|
|
}
|
|
// Whitelist de domínios permitidos
|
|
```
|
|
|
|
**Testes:**
|
|
```bash
|
|
curl "https://site.com/fetch?url=http://localhost/admin"
|
|
curl "https://site.com/fetch?url=http://192.168.1.1"
|
|
```
|