Pruebas de Seguridad
Las pruebas de seguridad deben ser automatizadas e integradas en tu flujo de trabajo de desarrollo. Encuentra vulnerabilidades antes que los atacantes.
Pruebas de Seguridad de Aplicaciones Estáticas (SAST)
# Plugin de seguridad de ESLint
npm install --save-dev eslint-plugin-security
# .eslintrc.js
module.exports = {
plugins: ['security'],
extends: ['plugin:security/recommended'],
rules: {
'security/detect-object-injection': 'error',
'security/detect-non-literal-regexp': 'error',
'security/detect-unsafe-regex': 'error',
'security/detect-buffer-noassert': 'error',
'security/detect-child-process': 'warn',
'security/detect-disable-mustache-escape': 'error',
'security/detect-eval-with-expression': 'error',
'security/detect-no-csrf-before-method-override': 'error',
'security/detect-possible-timing-attacks': 'error',
},
};
Semgrep
# Instalar Semgrep
pip install semgrep
# Ejecutar reglas de seguridad
semgrep --config auto .
# Ejecutar conjuntos de reglas específicos
semgrep --config p/security-audit .
semgrep --config p/javascript .
# Reglas personalizadas
# semgrep.yml
rules:
- id: hardcoded-password
pattern: password = "..."
message: "Contraseña hardcodeada detectada"
severity: ERROR
languages: [javascript, typescript]
Pruebas de Seguridad de Aplicaciones Dinámicas (DAST)
# OWASP ZAP Docker
docker run -t owasp/zap2docker-stable zap-baseline.py -t https://tu-app.com
# Generar reporte HTML
docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-stable \
zap-baseline.py -t https://tu-app.com -r report.html
Escaneo de Dependencias
# Workflow de GitHub Actions
name: Escaneo de Seguridad
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Ejecutar npm audit
run: npm audit --audit-level=high
- name: Ejecutar Snyk para verificar vulnerabilidades
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Ejecutar escáner de vulnerabilidades Trivy
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
severity: 'HIGH,CRITICAL'
Pruebas de Cabeceras de Seguridad
// Probar cabeceras de seguridad con Playwright
import { test, expect } from '@playwright/test';
test('las cabeceras de seguridad están configuradas correctamente', async ({ page }) => {
const response = await page.goto('https://tu-app.com');
const headers = response.headers();
expect(headers['strict-transport-security']).toContain('max-age=');
expect(headers['x-frame-options']).toBe('DENY');
expect(headers['x-content-type-options']).toBe('nosniff');
expect(headers['content-security-policy']).toBeDefined();
expect(headers['referrer-policy']).toBeDefined();
});
test('sin datos sensibles en respuesta', async ({ page }) => {
const response = await page.goto('https://tu-app.com/api/user');
const body = await response.json();
// Asegurar que password nunca se retorna
expect(body.password).toBeUndefined();
expect(body.passwordHash).toBeUndefined();
});
Automatización de Pruebas de Penetración
// Pruebas de seguridad personalizadas
describe('Pruebas de Seguridad', () => {
test('protección contra inyección SQL', async () => {
const maliciousInputs = [
"'; DROP TABLE users; --",
"' OR '1'='1",
"1; SELECT * FROM users",
];
for (const input of maliciousInputs) {
const response = await fetch('/api/search', {
method: 'POST',
body: JSON.stringify({ query: input }),
});
// No debe retornar error indicando ejecución SQL
expect(response.status).not.toBe(500);
const data = await response.json();
expect(data.error).not.toContain('SQL');
}
});
test('protección XSS', async () => {
const xssPayloads = [
'<script>alert(1)</script>',
'<img src=x onerror=alert(1)>',
'javascript:alert(1)',
];
for (const payload of xssPayloads) {
const response = await fetch('/api/comment', {
method: 'POST',
body: JSON.stringify({ text: payload }),
});
const data = await response.json();
// Payload debe ser sanitizado o rechazado
expect(data.text).not.toContain('