Streamlining container image security with Grype and Wazuh

| by | Wazuh 4.8.0
Post icon

Grype is a lightweight, open source tool for scanning container images and filesystems for vulnerabilities. It examines container image layers and dependencies to identify known vulnerabilities in the software packages installed within the image. By inspecting each layer and its contents, Grype helps you proactively uncover potential security risks before deploying the container image into a production environment.

Wazuh is a free and open source enterprise security platform that provides several capabilities and features to help organizations secure their cloud, on-premises, and container environments. This includes centralized logging, real-time monitoring, incident response automation, and others. 

By integrating Grype with Wazuh, you can gain a comprehensive view of your container security posture and take proactive measures to address identified threats. This process can be integrated into your CI/CD pipeline or DevOps workflow. In this blog post, we explore how to leverage the capabilities of Grype and Wazuh to implement effective container image vulnerability scanning.

Infrastructure

To demonstrate the integration of Grype and Wazuh for container image vulnerability scanning, we use the following infrastructure:

  • A pre-built, ready-to-use Wazuh OVA 4.8.0 which includes the Wazuh central components (Wazuh server, Wazuh indexer, and Wazuh dashboard). Follow this guide to download and set up the Wazuh virtual machine.
  • An Ubuntu 22.04 endpoint with Wazuh agent 4.8.0 installed and enrolled to the Wazuh server. We install Grype version 0.78.0 on this endpoint. 

Configuration

In this section, we set up Docker Engine and deploy container images on the monitored Ubuntu 22.04 endpoint. Next, we install Grype, create a custom bash script, and then use the Wazuh Command module to reference the script. The script scans the endpoint to detect existing container images and runs a vulnerability scan with Grype. Finally, we create and configure custom Wazuh decoders and rules on the Wazuh server to process and monitor the logs generated from the Grype scan.

Ubuntu

Perform the following steps on the Ubuntu endpoint to set up Docker Engine, deploy container images, and install Grype. 

Install Docker Engine and pull container images

Follow the steps below to install Docker Engine and deploy container images on the Ubuntu endpoint.

Note: You need root user privileges to execute all the commands described below.

1. Update the list of available packages and their versions, and install the cURL package:

# apt update && apt install curl -y

2. Run the following commands to download and run the Docker installation script:

# curl -sSL https://get.docker.com/ | sh

3. The Docker service starts automatically on Debian-based distributions. On RPM-based distributions, start the Docker service with the following command:

# systemctl start docker

4. Create and switch into a project directory /container_env for the container environment using the following command:

# mkdir /container_env && cd $_

5. Create a configuration file docker-compose.yml  in the container_env directory:

# touch docker-compose.yml

6. Copy and paste the configuration below into the docker-compose.yml file. This configuration file defines a development environment for a Node.js application that interacts with a MongoDB database and a Redis cache:

services:
  nodejs:
    image: node:latest
    container_name: nodejs_container
    restart: always
    ports:
    - 3000:3000
    volumes:
    - ./app:/app
    working_dir: /app
    environment:
    - NODE_ENV=production

  mongo:
    image: mongo:latest
    container_name: mongo_container
    restart: always

  redis:
    image: redis:latest
    container_name: redis_container
    restart: always

Note: You can configure the services further, however in this example, the focus is on pulling the base images (node:latest, mongo:latest, and redis:latest). These are the container images that will be scanned for vulnerabilities.

7. Run the command below to pull the container images using Docker Compose:

# docker compose pull

8. Verify that the container images are present:

# docker image ls
REPOSITORY   TAG   	IMAGE ID   	CREATED   	SIZE
redis    	latest	1a83fd5edeed   6 days ago	117MB
node     	latest	3d4b037e6712   13 days ago   1.11GB
mongo    	latest	ff65a94ec485   4 weeks ago   795MB

Install Grype

1. Run the following command to download and execute the Grype installation script:

# curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sudo sh -s -- -b /usr/local/bin

2. Verify that Grype has been installed:

# grype --version
grype 0.78.0

3. Run the following command to update the Grype vulnerability database:

# grype db update

Create a custom bash script and configure the Wazuh Command module

Follow the steps below to create a bash script and configure the Wazuh Command module on the Ubuntu endpoint. The script scans the endpoint to detect existing container images and runs a vulnerability scan with Grype. The Wazuh Command module is configured to monitor the output of the script and treat it as log content. 

1. Create a custom script directory /var/ossec/custom-script/ and create a new file grype_scan.sh using the following command:

# mkdir /var/ossec/custom-script/ && touch /var/ossec/custom-script/grype_scan.sh

2. Copy and paste the code below into the /var/ossec/custom-script/grype_scan.sh file:

#!/bin/bash
# Copyright (C) 2015-2023, Wazuh Inc.

# Directory to save the custom output template
TEMPLATE_DIR="/tmp"
TEMPLATE_FILE="$TEMPLATE_DIR/custom.tmpl"

# Create the custom output template (unchanged)
cat <<EOL > "$TEMPLATE_FILE"
"Package","Version Installed","Vulnerability ID","Severity"
{{- range .Matches}}
"{{.Artifact.Name}}","{{.Artifact.Version}}","{{.Vulnerability.ID}}","{{.Vulnerability.Severity}}"
{{- end }}
EOL

# Retrieve list of container images
images=$(docker images --format "{{.Repository}}:{{.Tag}}")

# Loop through each container image and run Grype scan
for image in $images; do
  # Run Grype scan on the current image using the custom output template
  grype_output=$(grype $image -o template -t $TEMPLATE_FILE)

  # Process Grype output for the current image
  while IFS= read -r line; do
    	# Prepend image name with quotes and comma
    	formatted_line=Grype:"\"$image\","$line
    	# Print the formatted line with quoted image name
    	echo "$formatted_line"
  done <<< "$grype_output"
done

# Clean up the custom output template
rm -f "$TEMPLATE_FILE"

This script sets up a custom output template for Grype. Then, it retrieves a list of container images and executes a Grype scan on each container image. Subsequently, it formats the output by adding “Grype:” at the start of each line. Finally, it cleans up the temporary output template file.

3. Add the executable permission for all classes to the /var/ossec/custom-script/grype_scan.sh file:

# chmod +x /var/ossec/custom-script/grype_scan.sh

4. Change the ownership of the /var/ossec/custom-script/grype_scan.sh file and the directory where it is located:

# chown root:wazuh /var/ossec/custom-script/ -R

5. Edit the Wazuh agent /var/ossec/etc/ossec.conf file and add the following Command module configuration within the <ossec_config> block:

<!-- Grype container vulnerability scanner script -->
<wodle name="command">
  <disabled>no</disabled>
  <command>/var/ossec/custom-script/grype_scan.sh</command>
  <interval>5d</interval>
  <ignore_output>no</ignore_output>
  <run_on_start>yes</run_on_start>
  <timeout>0</timeout>
</wodle>

Where:

  • disabled specifies that the Grype command is set to active.
  • command specifies the location of the grype_scan.sh script to be executed.
  • interval specifies the time interval for the execution of the configured script. In this blog post, the set value executes the grype_scan.sh every 5 days. Set this value to your preferred time interval.
  • ignore_output determines whether the output of the command execution should be ignored. Setting it to no means that the output will be processed and logged by Wazuh.
  • run_on_start specifies that the command module configuration for the grype_scan.sh script runs immediately when the Wazuh service starts.
  • timeout sets the timeout option to 0. This means the grype_scan.sh process will execute without any imposed time restrictions to halt it.

6. Restart the Wazuh agent to apply the above changes:

# systemctl restart wazuh-agent

Wazuh server

Perform the steps below on the Wazuh server. We create and configure custom Wazuh decoders and rules on the Wazuh server to process and monitor the logs generated from the Grype scan.

Note: You need root user privileges to execute all the commands described below.

1. Create a file grype_decoders.xml in the /var/ossec/etc/decoders/ directory.

# touch /var/ossec/etc/decoders/grype_decoders.xml

2. Add the following Wazuh decoder to the /var/ossec/etc/decoders/grype_decoders.xml file to parse the Grype logs received from the Wazuh agent:

<decoder name="grype-decoder">
  <prematch>^Grype:</prematch>
</decoder>
<decoder name="grype-decoder-fields">
  <parent>grype-decoder</parent>
  <regex offset="after_parent">"(\.+)","(\.+)","(\.+)","(\.+)","(\.+)"</regex>
  <order>image, package, version, vulnerability_id, severity</order>
</decoder>

3. Create a file grype_rules.xml in the /var/ossec/etc/rules/ directory:

# touch /var/ossec/etc/rules/grype_rules.xml

4. Add the following Wazuh rules to the /var/ossec/etc/rules/grype_rules.xml file to detect the Grype scan results:

<group name="grype">
  <!-- Parent Rule for Grype alerts -->
  <rule id="100101" level="0">
    <decoded_as>grype-decoder</decoded_as>
    <description>Grype alert detected.</description>
  </rule>

  <!-- This rule detects a critical severity vulnerability in a container image -->
  <rule id="100102" level="14">
    <if_sid>100101</if_sid>
    <field name="severity">Critical</field>
    <description>Grype alert [Critical]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description>
  </rule>

  <!-- This rule detects a high severity vulnerability in a container image -->
  <rule id="100103" level="12">
    <if_sid>100101</if_sid>
    <field name="severity">High</field>
    <description>Grype alert [High]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description>
  </rule>

  <!-- This rule detects a medium severity vulnerability in a container image -->
  <rule id="100104" level="7">
    <if_sid>100101</if_sid>
    <field name="severity">Medium</field>
    <description>Grype alert [Medium]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description>
  </rule>

  <!-- This rule detects a low severity vulnerability in a container image -->
  <rule id="100105" level="4">
    <if_sid>100101</if_sid>
    <field name="severity">Low</field>
    <description>Grype alert [Low]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description>
  </rule>

  <!-- This rule detects a negligible severity vulnerability in a container image -->
  <rule id="100106" level="1">
    <if_sid>100101</if_sid>
    <field name="severity">Negligible</field>
    <description>Grype alert [Negligible]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description>
  </rule>

  <!-- This rule detects an unknown severity vulnerability in a container image -->
  <rule id="100107" level="7">
    <if_sid>100101</if_sid>
    <field name="severity">Unknown</field>
    <description>Grype alert [Unknown]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description>
  </rule>
</group>

Where:

  • Rule ID 100101 detects the output of the Grype vulnerability scan. This rule will not generate alerts on the Wazuh dashboard, because, by default, alerts with levels below 3 do not appear on the Wazuh dashboard.
  • Rule ID 100102 detects the critical severity vulnerabilities from the Grype scan.
  • Rule ID 100103 detects the high severity vulnerabilities from the Grype scan.
  • Rule ID 100104 detects the medium severity vulnerabilities from the Grype scan.
  • Rule ID 100105 detects the low severity vulnerabilities from the Grype scan.
  • Rule ID 100106 detects the negligible severity vulnerabilities from the Grype scan. This rule will not generate alerts on the Wazuh dashboard, because, by default, alerts with levels below 3 do not appear on the Wazuh dashboard. You can modify the rule level at your discretion.
  • Rule ID 100107 detects the unknown severity vulnerabilities from the Grype scan.

5. Restart the Wazuh manager to apply the above changes:

# systemctl restart wazuh-manager

Visualizing vulnerability alerts on the Wazuh dashboard

Perform the following steps to view the alerts on the Wazuh dashboard.

1. Navigate to Explore > Discover.

2. Type rule.groups:grype in the filter bar and hit the Enter button on your keyboard. 

3. Under Available fields, add the following fields as columns by hovering on each field and clicking the + icon beside it: agent.name, data.image, data.severity, data.vulnerability_id, data.package, and data.version.  

Grype Available fields

Note: If you do not see the fields under Available fields, refresh the fields list from the Index Patterns page. To do this, navigate to Dashboard Management > Index Patterns. Select wazuh-alerts-* from the list then click the refresh icon ⟳.

We filter further to identify and visualize alerts for each vulnerability severity.

Critical vulnerability alerts

Perform the following steps to view the critical severity vulnerability alerts on the Wazuh dashboard.

1. Navigate to Explore > Discover.

2. Type rule.groups:grype and rule.id:100102 in the filter bar and click Update

3. Under Available fields, add the following fields as columns by hovering on each field agent.name, data.image, data.severity, data.vulnerability_id, data.package, and data.version and clicking the + icon beside it.

4. Save the query as Grype [Critical vulnerabilities].

Grype critical vulnerabilities

High vulnerability alerts

Perform the following steps to view the high severity vulnerability alerts on the Wazuh dashboard.

1. Navigate to Explore > Discover.

2. Type rule.groups:grype and rule.id:100103 in the filter bar and click Update

3. Under Available fields, add the following fields as columns by hovering on each field agent.name, data.image, data.severity, data.vulnerability_id, data.package, and data.version and clicking the + icon beside it.  

4. Save the query as Grype [High vulnerabilities]. Ensure you select the Save as new search option.

High vulnerability alerts

Medium vulnerability alerts

Perform the following steps to view the medium severity vulnerability alerts on the Wazuh dashboard.

1. Navigate to Explore > Discover.

2. Type rule.groups:grype and rule.id:100104 in the filter bar and click Update

3. Under Available fields, add the following fields as columns by hovering on each field agent.name, data.image, data.severity, data.vulnerability_id, data.package, and data.version and clicking the + icon beside it.  

4. Save the query as Grype [Medium vulnerabilities]. Ensure you select the Save as new search option.

Medium vulnerability alerts

Low vulnerability alerts

Perform the following steps to view the low severity vulnerability alerts on the Wazuh dashboard.

1. Navigate to Explore > Discover.

2. Type rule.groups:grype and rule.id:100105 in the filter bar and click Update

3. Under Available fields, add the following fields as columns by hovering on each field agent.name, data.image, data.severity, data.vulnerability_id, data.package, and data.version and clicking the + icon beside it.  

4. Save the query as Grype [Low vulnerabilities]. Ensure you select the Save as new search option

Low vulnerability alerts

Unknown vulnerability alerts

Perform the following steps to view the unknown severity vulnerability alerts on the Wazuh dashboard.

1. Navigate to Explore > Discover.

2. Type rule.groups:grype and rule.id:100107 in the filter bar and click Update

3. Under Available fields, add the following fields as columns by hovering on each field agent.name, data.image, data.severity, data.vulnerability_id, data.package, and data.version and clicking the + icon beside it.  

4. Save the query as Grype [Unknown vulnerabilities]. Ensure you select the Save as new search option

Grype Unknown vulnerability alerts

Note: Sometimes Grype generates vulnerabilities with “unknown” severity. This can arise from incomplete data, zero-day vulnerabilities, or differing vendor classifications and does not mean no risk exists. Investigate these findings using the provided details (ID, package, version) to assess potential impact.

Creating a custom dashboard

Create a custom dashboard with the saved templates for a single visualization display. 

1. Navigate to Explore > Dashboards > Create New Dashboard.

2. Select Add an existing link and click the saved visualizations (Grype [Critical vulnerabilities], Grype [High vulnerabilities], Grype [Unknown vulnerabilities]). This will add the visualizations to the new dashboard.

3. Save the dashboard as Grype container image vulnerabilities.

Grype custom dashboard

Conclusion

This blog post highlights the steps for integrating Grype with Wazuh to scan container images in your containerized environment. This integration can enhance your overall security posture by providing automated vulnerability scanning of container images before they are deployed in your environment. 

Wazuh is an open source security monitoring platform that provides a unified security management approach across various operating systems. Wazuh also has container security capabilities which when combined with a container image scanning tool such as Grype provides organizations with holistic security for their containerized environments. To learn more about Wazuh, check out our other blog posts and our ever-growing community.

References