Implementando CSP con Nonces Dinámicos usando AWS CloudFormation, Lambda y CloudFront
Published: 2024-03-04 12:55:02


En este artículo, exploraremos cómo reforzar la seguridad de nuestras aplicaciones web mediante la implementación de una política de seguridad de contenido (CSP) utilizando nonces (números utilizados una sola vez) dinámicos. Utilizaremos AWS CloudFormation para desplegar nuestra infraestructura, AWS Lambda para generar nonces dinámicos y Amazon CloudFront para servir nuestra aplicación con la CSP aplicada.

## ¿Qué es CSP y por qué es importante?

Content Security Policy (CSP) es una medida de seguridad adicional que ayuda a detectar y mitigar ciertos tipos de ataques, como Cross Site Scripting (XSS) y data injection. A través de CSP, un sitio web puede especificar qué recursos están permitidos cargar, evitando así la ejecución de recursos maliciosos.

Uno de los mecanismos que ofrece CSP para asegurar scripts es el uso de nonces. Un nonce es un valor aleatorio que el servidor genera para cada solicitud. Este valor se añade como atributo a los tags `<script>` en el HTML y se especifica en la política CSP, asegurando que solo los scripts con el nonce correcto se ejecuten.

## Paso 1: Configurando AWS CloudFormation

Comencemos por definir nuestra infraestructura como código usando AWS CloudFormation. Esto incluye nuestra función AWS Lambda, la configuración de AWS CloudFront y los permisos necesarios.

Aquí hay un ejemplo básico de una plantilla de CloudFormation para crear una función Lambda:

```yaml
Resources:
  NonceLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs14.x
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            const nonce = crypto.randomBytes(16).toString('base64');
            return {
              statusCode: 200,
              headers: { 'Content-Type': 'text/plain' },
              body: `Nonce: ${nonce}`,
            };
          };
      Role: !GetAtt LambdaExecutionRole.Arn

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: 'logs:*'
                Resource: 'arn:aws:logs:*:*:*'
```

Este fragmento define una función Lambda simple que genera un nonce aleatorio y lo devuelve. Asegúrate de incluir el módulo `crypto` necesario para generar el nonce.

## Paso 2: Integración con Amazon CloudFront

Para integrar nuestra función Lambda con Amazon CloudFront, utilizaremos Lambda@Edge. Esto nos permite ejecutar la función en respuesta a eventos de CloudFront, como solicitudes de contenido.

Necesitamos modificar nuestra plantilla de CloudFormation para incluir una asociación entre nuestra función Lambda y un comportamiento de CloudFront. Esto se puede hacer en la sección de distribución de CloudFront de la plantilla.

```yaml
Distribution:
  Type: AWS::CloudFront::Distribution
  Properties:
    DistributionConfig:
      DefaultCacheBehavior:
        TargetOriginId: "myOrigin"
        ViewerProtocolPolicy: redirect-to-https
        LambdaFunctionAssociations:
          - EventType: viewer-response
            LambdaFunctionARN: !GetAtt NonceLambdaFunction.Version
```

Este fragmento asocia nuestra función Lambda con el evento `viewer-response`, lo que significa que se ejecutará cada vez que CloudFront responda a una solicitud.

## Paso 3: Configurando la Política CSP

Ahora, necesitamos modificar nuestra función Lambda para que no solo genere el nonce, sino que también lo incluya en las cabeceras CSP de las respuestas HTTP. Además, debemos asegurarnos de que nuestra aplicación web incluya este nonce en todos los tags `<script>`.

```javascript
exports.handler = async (event) => {
  const nonce = crypto.randomBytes(16).toString('base64');
  const cspPolicy = `default-src 'self'; script-src 'nonce-${nonce}' 'strict-dynamic';`;



  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'text/html',
      'Content-Security-Policy': cspPolicy
    },
    body: `Tu contenido HTML aquí`,
  };
};
```

En tu aplicación web, asegúrate de incluir el nonce en tus tags de script de la siguiente manera:

```html
<script nonce="${nonce}">
  // Tu código JavaScript aquí
</script>
```

Recuerda que el valor de `${nonce}` debe ser reemplazado por el nonce generado por tu función Lambda en cada respuesta.

## Conclusión

Al implementar CSP con nonces dinámicos, podemos mejorar significativamente la seguridad de nuestras aplicaciones web. Utilizando AWS CloudFormation, Lambda y CloudFront, podemos automatizar y escalar esta práctica de seguridad a lo largo de nuestra infraestructura. Este enfoque no solo nos ayuda a proteger contra ataques como XSS, sino que también asegura que solo los scripts que hemos aprobado se ejecuten en el navegador del usuario.

---

Espero que este artículo te haya sido útil y te anime a implementar medidas de seguridad adicionales en tus aplicaciones web. ¡La seguridad nunca debe ser una ocurrencia tardía!