AWS Inspector - Notificação CVE - EC2 e ECR
Published: 2024-07-17 11:16:30

Neste tutorial, vamos explicar como criar e configurar uma função Lambda na AWS que captura eventos do AWS Inspector via SNS, formata esses eventos em um email detalhado e os envia via AWS SES para um destinatário específico.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tqzo4ko2onm7ge87wwqj.png)

---

## **Passos:**


1. **Criar a Função Lambda:**
   Primeiro, você precisa criar uma função Lambda na AWS. A função Lambda será acionada pelos eventos gerados pelo AWS Inspector através do SNS.
   * Acesse o Console da AWS.
   * Vá para o serviço Lambda.
   * Clique em "Criar função".
   * Configure o nome, a runtime (Python 3.12 ou superior recomendado) e deixe as permissões de execução padrão inicialmente. (Depois adicione AmazonEC2ReadOnlyAccess, AmazonSESFullAccess, AmazonSNSReadOnlyAccess e AmazonEC2ContainerRegistryReadOnly)
   * Defina como 1 minuto o timeout da lambda.

2. **Configurar Gatilho do SNS:**
   * Após criar a função Lambda, adicione um gatilho SNS.
   * Selecione o tópico SNS que recebe os eventos do AWS Inspector.
   * Exemplo da CloudWatch Rule de detecção do Inspector que envia para o SNS:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pr9wtbxtxp9tyjh499rs.png)
---
```python
{
  "source": ["aws.inspector2"],
  "detail-type": ["Inspector2 Finding"],
  "detail": {
    "severity": ["HIGH", "MEDIUM", "CRITICAL"],
    "status": ["ACTIVE", "CLOSED", "SUPRESSED"]
  }
}
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swz2txvf831xqav2jgz7.png)



* Configure a função lambda para ser acionada por novas mensagens no tópico SNS.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8jxzu99ez7hhntuc3j8f.png)

**Variáveis de ambiente:**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zu5abrp520t8sm64ists.png)


---

## **Implementar o Código da Função Lambda:**

* Troque o nome da empresa do código, para a empresa que deseja configurar o alerta.

```python
import json
import boto3
import os

# Inicialize os clientes da AWS
ses_client = boto3.client('ses')
ec2_client = boto3.client('ec2')
ecr_client = boto3.client('ecr')

def send_email(subject, body):
    # Função para enviar o email usando SES
    response = ses_client.send_email(
        Source=os.environ['SOURCE_EMAIL'],
        Destination={
            'ToAddresses': [os.environ['TARGET_EMAIL']]
        },
        Message={
            'Subject': {
                'Data': subject,
                'Charset': 'UTF-8'
            },
            'Body': {
                'Html': {
                    'Data': body,
                    'Charset': 'UTF-8'
                }
            }
        }
    )
    print(f"Email enviado com sucesso: {response}")

def lambda_handler(event, context):
    for record in event['Records']:
        sns_message = json.loads(record['Sns']['Message'])
        detail = sns_message.get('detail', {})
        
        # Detalhes do evento
        title = detail.get('title', 'N/A')
        description = detail.get('description', 'N/A').replace('\n', '<br>')
        severity = detail.get('severity', 'N/A')
        status = detail.get('status', 'N/A')
        finding_arn = detail.get('findingArn', 'N/A')
        first_observed = detail.get('firstObservedAt', 'N/A')
        last_observed = detail.get('lastObservedAt', 'N/A')
        updated_at = detail.get('updatedAt', 'N/A')
        vulnerability_id = detail.get('packageVulnerabilityDetails', {}).get('vulnerabilityId', 'N/A')

        resources = detail.get('resources', [])
        
        for resource in resources:
            resource_type = resource.get('type', '')
            
            if resource_type == 'AWS_EC2_INSTANCE':
                # Detalhes da instância EC2
                instance_id = resource.get('id', 'N/A')
                instance_name = get_ec2_instance_name(instance_id)
                instance_profile = resource.get('details', {}).get('awsEc2Instance', {}).get('iamInstanceProfileArn', 'N/A')
                image_id = resource.get('details', {}).get('awsEc2Instance', {}).get('imageId', 'N/A')
                ipv4_addresses = ', '.join(resource.get('details', {}).get('awsEc2Instance', {}).get('ipV4Addresses', []))
                platform = resource.get('details', {}).get('awsEc2Instance', {}).get('platform', 'N/A')
                instance_type = resource.get('details', {}).get('awsEc2Instance', {}).get('type', 'N/A')

                # Construir corpo do email para EC2
                email_subject = f"Alerta de Segurança - EMPRESA XPTO - {instance_name} - {title}"
                email_body = build_ec2_email_body(instance_name, title, description, instance_id, instance_profile, image_id, ipv4_addresses, platform, instance_type, severity, status, finding_arn, first_observed, last_observed, updated_at, vulnerability_id)
                send_email(email_subject, email_body)
            
            elif resource_type == 'AWS_ECR_CONTAINER_IMAGE':
                # Detalhes da imagem no ECR
                repository_name = resource.get('details', {}).get('awsEcrContainerImage', {}).get('repositoryName', 'N/A')
                image_digest = resource.get('details', {}).get('awsEcrContainerImage', {}).get('imageDigest', 'N/A')
                image_tags = ', '.join(resource.get('details', {}).get('awsEcrContainerImage', {}).get('imageTags', []))
                pushed_at = resource.get('details', {}).get('awsEcrContainerImage', {}).get('pushedAt', 'N/A')
                architecture = resource.get('details', {}).get('awsEcrContainerImage', {}).get('architecture', 'N/A')
                platform = resource.get('details', {}).get('awsEcrContainerImage', {}).get('platform', 'N/A')

                # Construir corpo do email para ECR
                email_subject = f"Alerta de Segurança - EMPRESA XPTO - {repository_name} - {title}"
                email_body = build_ecr_email_body(repository_name, title, description, image_digest, image_tags, pushed_at, architecture, platform, severity, status, finding_arn, first_observed, last_observed, updated_at, vulnerability_id)
                send_email(email_subject, email_body)

def get_ec2_instance_name(instance_id):
    # Função para obter o nome da instância EC2 a partir do ID da instância
    instance_name = "N/A"
    if instance_id != "N/A":
        ec2_response = ec2_client.describe_instances(InstanceIds=[instance_id])
        tags = ec2_response['Reservations'][0]['Instances'][0].get('Tags', [])
        for tag in tags:
            if tag['Key'] == 'Name':
                instance_name = tag['Value']
                break
    return instance_name

def build_ec2_email_body(instance_name, title, description, instance_id, instance_profile, image_id, ipv4_addresses, platform, instance_type, severity, status, finding_arn, first_observed, last_observed, updated_at, vulnerability_id):
    # Função para construir o corpo do email para eventos de EC2
    email_body = f"""
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Alerta de Segurança - EMPRESA XPTO PCI-DSS</title>
    <style>
        body {{
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 20px;
            background-color: #f5f5f5;
        }}
        h2 {{
            background-color: #333;
            color: #fff;
            padding: 10px;
            border-radius: 5px 5px 0 0;
            margin-top: 0;
        }}
        p {{
            margin-bottom: 20px;
            color: #555;
            padding: 0 10px;
        }}
        table {{
            width: 100%;
            border-collapse: collapse;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin-top: 20px;
        }}
        th, td {{
            padding: 10px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }}
        th {{
            background-color: #f2f2f2;
            color: #333;
            font-weight: bold;
        }}
        tr:nth-child(even) {{
            background-color: #f9f9f9;
        }}
        td:first-child, th:first-child {{
            width: 30%;
            min-width: 120px;
            font-weight: bold;
        }}
    </style>
</head>
<body>
    <h2>Alerta de Segurança - EMPRESA XPTO PCI-DSS</h2>
    <p>Recebemos uma nova notificação de vulnerabilidade no AWS Inspector:</p>
    <table>
        <tr>
            <th colspan="2">Detalhes da Vulnerabilidade</th>
        </tr>
        <tr>
            <td><b>Título</b></td>
            <td>{title}</td>
        </tr>
        <tr>
            <td><b>Descrição</b></td>
            <td>{description}</td>
        </tr>
        <tr>
            <td><b>ID da Vulnerabilidade</b></td>
            <td>{vulnerability_id}</td>
        </tr>
        <tr>
            <td><b>Severidade</b></td>
            <td>{severity}</td>
        </tr>
        <tr>
            <td><b>Status</b></td>
            <td>{status}</td>
        </tr>
        <tr>
            <td><b>Encontrado em</b></td>
            <td>{first_observed}</td>
        </tr>
        <tr>
            <td><b>Última Observação</b></td>
            <td>{last_observed}</td>
        </tr>
        <tr>
            <td><b>Atualizado em</b></td>
            <td>{updated_at}</td>
        </tr>
        <tr>
            <th colspan="2">Detalhes da Instância EC2</th>
        </tr>
        <tr>
            <td><b>ID da Instância</b></td>
            <td>{instance_id}</td>
        </tr>
        <tr>
            <td><b>Nome da Instância</b></td>
            <td>{instance_name}</td>
        </tr>
        <tr>
            <td><b>Perfil IAM</b></td>
            <td>{instance_profile}</td>
        </tr>
        <tr>
            <td><b>ID da Imagem</b></td>
            <td>{image_id}</td>
        </tr>
        <tr>
            <td><b>Endereços IPv4</b></td>
            <td>{ipv4_addresses}</td>
        </tr>
        <tr>
            <td><b>Plataforma</b></td>
            <td>{platform}</td>
        </tr>
        <tr>
            <td><b>Tipo da Instância</b></td>
            <td>{instance_type}</td>
        </tr>
    </table>
    <p>Para mais informações, acesse o painel do AWS Inspector.</p>
</body>
</html>
"""
    return email_body

def build_ecr_email_body(repository_name, title, description, image_digest, image_tags, pushed_at, architecture, platform, severity, status, finding_arn, first_observed, last_observed, updated_at, vulnerability_id):
    # Função para construir o corpo do email para eventos de ECR
    email_body = f"""
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Alerta de Segurança - EMPRESA XPTO PCI-DSS</title>
    <style>
        body {{
            font-family: Arial, sans-serif;
            line-height: 1.6;
            margin: 20px;
            background-color: #f5f5f5;
        }}
        h2 {{
            background-color: #333;
            color: #fff;
            padding: 10px;
            border-radius: 5px 5px 0 0;
            margin-top: 0;
        }}
        p {{
            margin-bottom: 20px;
            color: #555;
            padding: 0 10px;
        }}
        table {{
            width: 100%;
            border-collapse: collapse;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin-top: 20px;
        }}
        th, td {{
            padding: 10px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }}
        th {{
            background-color: #f2f2f2;
            color: #333;
            font-weight: bold;
        }}
        tr:nth-child(even) {{
            background-color: #f9f9f9;
        }}
        td:first-child, th:first-child {{
            width: 30%;
            min-width: 120px;
            font-weight: bold;
        }}
    </style>
</head>
<body>
    <h2>Alerta de Segurança - EMPRESA XPTO PCI-DSS</h2>
    <p>Recebemos uma nova notificação de vulnerabilidade no AWS Inspector:</p>
    <table>
        <tr>
            <th colspan="2">Detalhes da Vulnerabilidade</th>
        </tr>
        <tr>
            <td><b>Título</b></td>
            <td>{title}</td>
        </tr>
        <tr>
            <td><b>Descrição</b></td>
            <td>{description}</td>
        </tr>
        <tr>
            <td><b>ID da Vulnerabilidade</b></td>
            <td>{vulnerability_id}</td>
        </tr>
        <tr>
            <td><b>Severidade</b></td>
            <td>{severity}</td>
        </tr>
        <tr>
            <td><b>Status</b></td>
            <td>{status}</td>
        </tr>
        <tr>
            <td><b>Encontrado em</b></td>
            <td>{first_observed}</td>
        </tr>
        <tr>
            <td><b>Última Observação</b></td>
            <td>{last_observed}</td>
        </tr>
        <tr>
            <td><b>Atualizado em</b></td>
            <td>{updated_at}</td>
        </tr>
        <tr>
            <th colspan="2">Detalhes da Imagem no ECR</th>
        </tr>
        <tr>
            <td><b>Nome do Repositório</b></td>
            <td>{repository_name}</td>
        </tr>
        <tr>
            <td><b>Digest da Imagem</b></td>
            <td>{image_digest}</td>
        </tr>
        <tr>
            <td><b>Tags da Imagem</b></td>
            <td>{image_tags}</td>
        </tr>
        <tr>
            <td><b>Arquitetura</b></td>
            <td>{architecture}</td>
        </tr>
        <tr>
            <td><b>Plataforma</b></td>
            <td>{platform}</td>
        </tr>
        <tr>
            <td><b>Enviado em</b></td>
            <td>{pushed_at}</td>
        </tr>
    </table>
    <p>Para mais informações, acesse o painel do AWS Inspector.</p>
</body>
</html>
"""
    return email_body
```



---

## **Teste de eventos:**

**Um teste para ser feito para EC2:**

```json
{
  "Records": [
    {
      "EventSource": "aws:sns",
      "EventVersion": "1.0",
      "EventSubscriptionArn": "arn:aws:sns:sa-east-1:530929948444:AWS-CVE-Inspector:d07cd6d8-2f8d-40c9-af6a-ecc4266e0e70",
      "Sns": {
        "Type": "Notification",
        "MessageId": "175a2902-7430-5515-bc29-7613ec172f9f",
        "TopicArn": "arn:aws:sns:sa-east-1:530929948444:AWS-CVE-Inspector",
        "Subject": null,
        "Message": "{\"version\":\"0\",\"id\":\"e7b5cb0b-b7b1-6390-fdcf-4ba7c5cf572d\",\"detail-type\":\"Inspector2 Finding\",\"source\":\"aws.inspector2\",\"account\":\"530929948444\",\"time\":\"2024-07-17T09:58:46Z\",\"region\":\"sa-east-1\",\"resources\":[\"i-09cc55700f9369d04\"],\"detail\":{\"awsAccountId\":\"530929948444\",\"description\":\"In the Linux kernel, the following vulnerability has been resolved: usb: udc: remove warning when queue disabled ep It is possible trigger below warning message from mass storage function, WARNING: CPU: 6 PID: 3839 at drivers/usb/gadget/udc/core.c:294 usb_ep_queue+0x7c/0x104 pc : usb_ep_queue+0x7c/0x104 lr : fsg_main_thread+0x494/0x1b3c Root cause is mass storage function try to queue request from main thread, but other thread may already disable ep when function disable. As there is no function failure in the driver, in order to avoid effort to fix warning, change WARN_ON_ONCE() in usb_ep_queue() to pr_debug().\",\"epss\":{\"score\":4.4E-4},\"exploitAvailable\":\"NO\",\"findingArn\":\"arn:aws:inspector2:sa-east-1:530929948444:finding/7c4806a9e2c4b7230d865d1c96d20b11\",\"firstObservedAt\":\"Tue Jul 16 21:45:59.629 UTC 2024\",\"fixAvailable\":\"YES\",\"lastObservedAt\":\"Tue Jul 16 21:45:59.629 UTC 2024\",\"packageVulnerabilityDetails\":{\"cvss\":[],\"referenceUrls\":[\"https://git.kernel.org/linus/2a587a035214fa1b5ef598aea0b81848c5b72e5e(6.9-rc2)\",\"https://ubuntu.com/security/notices/USN-6817-3\",\"https://git.kernel.org/stable/c/df5cbb908f1687e8ab97e222a16b7890d5501acf\",\"https://git.kernel.org/stable/c/99731076722eb7ed26b0c87c879da7bb71d24290\",\"https://git.kernel.org/stable/c/2b002c308e184feeaeb72987bca3f1b11e5f70b8\",\"https://git.kernel.org/stable/c/68d951880d0c52c7f13dcefb5501b69b8605ce8c\",\"https://ubuntu.com/security/notices/USN-6878-1\",\"https://git.kernel.org/stable/c/30511676eb54d480d014352bf784f02577a10252\",\"https://ubuntu.com/security/notices/USN-6816-1\",\"https://ubuntu.com/security/notices/USN-6817-2\",\"https://ubuntu.com/security/notices/USN-6817-1\",\"https://www.cve.org/CVERecord?id=CVE-2024-35822\",\"https://ubuntu.com/security/notices/USN-6896-1\",\"https://ubuntu.com/security/notices/USN-6898-1\",\"https://git.kernel.org/stable/c/3e944ddc17c042945d983e006df7860687a8849a\",\"https://git.kernel.org/stable/c/f74c5e0b54b02706d9a862ac6cddade30ac86bcf\",\"https://git.kernel.org/stable/c/2a587a035214fa1b5ef598aea0b81848c5b72e5e\",\"https://git.kernel.org/stable/c/36177c2595df12225b95ce74eb1ac77b43d5a58c\"],\"relatedVulnerabilities\":[\"USN-6816-1\",\"USN-6817-1\",\"USN-6817-2\",\"USN-6817-3\",\"USN-6896-1\",\"USN-6898-1\",\"USN-6878-1\"],\"source\":\"UBUNTU_CVE\",\"sourceUrl\":\"https://people.canonical.com/~ubuntu-security/cve/2024/CVE-2024-35822.html\",\"vendorCreatedAt\":\"Fri May 17 14:15:00.000 UTC 2024\",\"vendorSeverity\":\"medium\",\"vulnerabilityId\":\"CVE-2024-35822\",\"vulnerablePackages\":[{\"arch\":\"X86_64\",\"epoch\":0,\"fixedInVersion\":\"0:5.15.0-116.126\",\"name\":\"linux-libc-dev\",\"packageManager\":\"OS\",\"release\":\"113.123\",\"remediation\":\"apt-get update && apt-get upgrade\",\"version\":\"5.15.0\"}]},\"remediation\":{\"recommendation\":{\"text\":\"None Provided\"}},\"resources\":[{\"details\":{\"awsEc2Instance\":{\"iamInstanceProfileArn\":\"arn:aws:iam::530929948444:instance-profile/ScoutSuite\",\"imageId\":\"ami-0228d19e5bf7dc391\",\"ipV4Addresses\":[\"172.30.0.243\"],\"ipV6Addresses\":[],\"keyName\":\"b23_lnx_sec\",\"launchedAt\":\"Tue Oct 03 03:48:54.000 UTC 2023\",\"platform\":\"UBUNTU_22_04\",\"subnetId\":\"subnet-0cf6115b2cf95ddf8\",\"type\":\"c6a.xlarge\",\"vpcId\":\"vpc-00a09194848c6e5d6\"}},\"id\":\"i-09cc55700f9369d04\",\"partition\":\"aws\",\"region\":\"sa-east-1\",\"tags\":{\"BackupEC2\":\"true\",\"Name\":\"SRV-LNX-SEC\"},\"type\":\"AWS_EC2_INSTANCE\"}],\"severity\":\"MEDIUM\",\"status\":\"CLOSED\",\"title\":\"CVE-2024-35822 - linux-libc-dev\",\"type\":\"PACKAGE_VULNERABILITY\",\"updatedAt\":\"Wed Jul 17 09:58:46.559 UTC 2024\"}}",
        "Timestamp": "2024-07-17T09:59:03.737Z",
        "SignatureVersion": "1",
        "Signature": "nVpeMS7rnD1WUTmp04BwMC64Dp1Db9WagxLI+Lzlray1YTnpEtgezAoguYJY4DnPrTsouX67vq7plVEnWj5oxeTDR+GFlSCGDlzM/pQf5AO8haAuWuFWatTYudcwdma9cNnSMzmVyQ8Kqn4tJOudvPaIneuL20uxstvdLYVBb/9TznCBY2N+YBwv4BLGZEcqnY35Vf6TeDcSZInSk90z8f/9tXUdFtgHo7WuMzWAX6Eoen70XE3e1SLwE6gSTSa+mSFzCfD8Tj2n+SXQB9wE/ZTLR7UBEFmdjkvmJ2WgE810JUKFRzFFH7cWLp3gyRcXhXH5G1bTsFmc1R4Jo/ZAaQ==",
        "SigningCertUrl": "https://sns.sa-east-1.amazonaws.com/SimpleNotificationService-60eadc530605d63b8e62a523676ef735.pem",
        "UnsubscribeUrl": "https://sns.sa-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:sa-east-1:530929948444:AWS-CVE-Inspector:d07cd6d8-2f8d-40c9-af6a-ecc4266e0e70",
        "MessageAttributes": {}
      }
    }
  ]
}
```

**Um teste para ser feito para ECR:**

```json
{
  "Records": [
    {
      "Sns": {
        "Message": "{\"detail\":{\"title\":\"High Vulnerability in ECR Image\",\"description\":\"A high severity vulnerability was detected in the container image.\",\"severity\":\"HIGH\",\"status\":\"ACTIVE\",\"findingArn\":\"arn:aws:inspector:us-east-1:123456789012:finding/finding-id\",\"firstObservedAt\":\"2024-07-16T10:00:00Z\",\"lastObservedAt\":\"2024-07-16T10:00:00Z\",\"updatedAt\":\"2024-07-16T10:00:00Z\",\"packageVulnerabilityDetails\":{\"vulnerabilityId\":\"CVE-2024-1234\"},\"resources\":[{\"type\":\"AWS_ECR_CONTAINER_IMAGE\",\"id\":\"arn:aws:ecr:us-east-1:123456789012:repository/my-repository\",\"details\":{\"awsEcrContainerImage\":{\"repositoryName\":\"my-repository\",\"imageDigest\":\"sha256:example1234\",\"imageTags\":[\"latest\"],\"pushedAt\":\"2024-07-15T10:00:00Z\",\"architecture\":\"amd64\",\"platform\":\"linux\"}}}]}}"
      }
    }
  ]
}
```



---

## Notificações:

**Exemplo de email fake EC2 enviado para a caixa de email**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/928qh6vasd8a9exoz7n4.png)


**Exemplo de email fake ECR enviado para a caixa de email**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7zqfoyh7fh2gh9bn3u5k.png)


---

##**Explicação do Código:**

* A função *lambda_handler*  é o ponto de entrada da Lambda, que recebe eventos do SNS.
* Os detalhes da vulnerabilidade são extraídos da mensagem JSON recebida.
* Detalhes específicos da instância EC2 ou ECR são recuperados usando o cliente EC2 ou ECR.
* Um email é construído em HTML para fornecer informações detalhadas sobre a vulnerabilidade e a instância.
* O email é enviado usando o cliente SES da AWS.